All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support
@ 2019-07-15  1:27 Andre Przywara
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 1/7] sunxi: H6: DRAM: avoid memcpy() on MMIO registers Andre Przywara
                   ` (7 more replies)
  0 siblings, 8 replies; 14+ messages in thread
From: Andre Przywara @ 2019-07-15  1:27 UTC (permalink / raw)
  To: u-boot

A tiny update, dropping "1333" from the LPDDR3 timings filename, because
it actually isn't 1333, as Icenowy pointed out correctly. Also adding
Jernej's review tags. For more details see the Changelog below.
----------------

So far the SPL DRAM driver for the Allwinner H6 SoC only supports
LPDDR3 DRAM chips, which are used on most single board computers with
this SoC.
There are some TV boxes with the H6 out now, but most of them are
using DDR3 DRAM instead of LPDDR3.

This series extends the existing H6 DRAM driver to cover DDR3 DRAMs
as well. The information used in these patches is from:
- register dumps after Allwinner's boot0 (libdram) has initialised
  the DRAM
- some disassembly of the libdram library
- timing parameters as found in the boot0 binary
- comparison with Xilinx ZynqMP DRAM controller documentation

The box I played with (Eachlink H6 Mini) has 3GB of DDR3-1600 chips and
runs at 840 MHz, however I couldn't get it to work with these parameters.
Instead Jernej suggested to use a lower clock and adjust some timing
parameters, which made it work for me as well.

Many thanks to Jernej Skrabec for his help, also to others who helped
with testing and experiments.

The first two patches contain some fixes for the existing driver.
Patch 3 moves the existing LPDDR3 timing parameters into a separate file,
patch 5 introduces the respective DDR3 timings, patch 6 adds some
generic delay lines values.
Patch 4 enhances the DRAM controller driver to program DDR3 specific
registers as well and use different settings on other registers.
The final patch introduces support for the Eachlink H6 Mini TV box, with
the usual device tree and defconfig file.

Please have a look and comment!

Cheers,
Andre.

Changelog v2..v3:
- rebased against origin/master
- drop 1333 from LPDDR3 timings filename
- cosmetic change to comment
- adding Jernej's Reviewed-by: and Tested-by: tags
- updating defconfigs for two new boards

Changelog v1..v2:
- name DDR2T mode bit
- explain bonding ID bit
- generalise message about non-supported DRAM types
- update comments about JEDEC values to match DDR3-1333 timings
- use recommended max(ns, cycles) timing formulas where appropriate
- add MAINTAINERS entry for the Eachlink H6 Mini box

Andre Przywara (6):
  sunxi: H6: DRAM: avoid memcpy() on MMIO registers
  sunxi: H6: DRAM: follow recommended PHY init algorithm
  sunxi: H6: move LPDDR3 timing definition into separate file
  sunxi: H6: Add DDR3 support to DRAM controller driver
  sunxi: H6: Add DDR3-1333 timings
  sunxi: H6: Add basic Eachlink H6 Mini support

Jernej Skrabec (1):
  sunxi: H6: Add DDR3 DRAM delay values

 arch/arm/dts/Makefile                            |   1 +
 arch/arm/dts/sun50i-h6-eachlink-h6-mini.dts      | 116 +++++++++++
 arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h |  35 ++++
 arch/arm/mach-sunxi/Kconfig                      |  18 +-
 arch/arm/mach-sunxi/Makefile                     |   1 +
 arch/arm/mach-sunxi/dram_sun50i_h6.c             | 251 +++++++----------------
 arch/arm/mach-sunxi/dram_timings/Makefile        |   2 +
 arch/arm/mach-sunxi/dram_timings/h6_ddr3_1333.c  | 144 +++++++++++++
 arch/arm/mach-sunxi/dram_timings/h6_lpddr3.c     | 132 ++++++++++++
 board/sunxi/MAINTAINERS                          |   6 +
 configs/beelink_gs1_defconfig                    |   1 +
 configs/eachlink_h6_mini_defconfig               |  17 ++
 configs/orangepi_lite2_defconfig                 |   1 +
 configs/orangepi_one_plus_defconfig              |   1 +
 configs/pine_h64_defconfig                       |   1 +
 15 files changed, 549 insertions(+), 178 deletions(-)
 create mode 100644 arch/arm/dts/sun50i-h6-eachlink-h6-mini.dts
 create mode 100644 arch/arm/mach-sunxi/dram_timings/h6_ddr3_1333.c
 create mode 100644 arch/arm/mach-sunxi/dram_timings/h6_lpddr3.c
 create mode 100644 configs/eachlink_h6_mini_defconfig

-- 
2.14.5

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 1/7] sunxi: H6: DRAM: avoid memcpy() on MMIO registers
  2019-07-15  1:27 [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Andre Przywara
@ 2019-07-15  1:27 ` Andre Przywara
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 2/7] sunxi: H6: DRAM: follow recommended PHY init algorithm Andre Przywara
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Andre Przywara @ 2019-07-15  1:27 UTC (permalink / raw)
  To: u-boot

Using memcpy() is, however tempting, not a good idea: It depends on the
specific implementation of memcpy, also lacks barriers. In this
particular case the first registers were written using 64-bit writes,
and the last register using four separate single-byte writes.

Replace the memcpy with a proper loop using the writel() accessor.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Tested-by: Jernej Skrabec <jernej.skrabec@siol.net>
Reviewed-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/mach-sunxi/dram_sun50i_h6.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c
index 5da90a2835..e2f141eb9b 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
@@ -182,6 +182,7 @@ static void mctl_set_timing_lpddr3(struct dram_para *para)
 			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
 	struct sunxi_mctl_phy_reg * const mctl_phy =
 			(struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
+	int i;
 
 	u8 tccd		= 2;
 	u8 tfaw		= max(ns_to_t(50), 4);
@@ -237,8 +238,9 @@ static void mctl_set_timing_lpddr3(struct dram_para *para)
 	u8 twr2rd	= tcwl + 4 + 1 + twtr;
 	u8 trd2wr	= tcl + 4 + (tcksrea >> 1) - tcwl + 1;
 
-	/* set mode register */
-	memcpy(mctl_phy->mr, mr_lpddr3, sizeof(mr_lpddr3));
+	/* set mode registers */
+	for (i = 0; i < ARRAY_SIZE(mr_lpddr3); i++)
+		writel(mr_lpddr3[i], &mctl_phy->mr[i]);
 
 	/* set DRAM timing */
 	writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
-- 
2.14.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 2/7] sunxi: H6: DRAM: follow recommended PHY init algorithm
  2019-07-15  1:27 [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Andre Przywara
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 1/7] sunxi: H6: DRAM: avoid memcpy() on MMIO registers Andre Przywara
@ 2019-07-15  1:27 ` Andre Przywara
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 3/7] sunxi: H6: move LPDDR3 timing definition into separate file Andre Przywara
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Andre Przywara @ 2019-07-15  1:27 UTC (permalink / raw)
  To: u-boot

The DRAM controller manual suggests to first program the PHY
initialisation parameters to the PHY_PIR register, and then set bit 0 to
trigger the initialisation. This is also used in boot0.

Follow this recommendation by setting bit 0 in a separate step.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Tested-by: Jernej Skrabec <jernej.skrabec@siol.net>
Reviewed-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/mach-sunxi/dram_sun50i_h6.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c
index e2f141eb9b..7a8b724f08 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
@@ -75,12 +75,14 @@ static void mctl_core_init(struct dram_para *para)
 	mctl_channel_init(para);
 }
 
+/* PHY initialisation */
 static void mctl_phy_pir_init(u32 val)
 {
 	struct sunxi_mctl_phy_reg * const mctl_phy =
 			(struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
 
-	writel(val | BIT(0), &mctl_phy->pir);
+	writel(val, &mctl_phy->pir);
+	writel(val | BIT(0), &mctl_phy->pir);	/* Start initialisation. */
 	mctl_await_completion(&mctl_phy->pgsr[0], BIT(0), BIT(0));
 }
 
-- 
2.14.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 3/7] sunxi: H6: move LPDDR3 timing definition into separate file
  2019-07-15  1:27 [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Andre Przywara
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 1/7] sunxi: H6: DRAM: avoid memcpy() on MMIO registers Andre Przywara
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 2/7] sunxi: H6: DRAM: follow recommended PHY init algorithm Andre Przywara
@ 2019-07-15  1:27 ` Andre Przywara
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 4/7] sunxi: H6: Add DDR3 support to DRAM controller driver Andre Przywara
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Andre Przywara @ 2019-07-15  1:27 UTC (permalink / raw)
  To: u-boot

Currently the H6 DRAM driver only supports one kind of LPDDR3 DRAM.
Split the timing parameters for this LPDDR3 configuration  into a
separate file, to allow selecting an alternative later at compile time
(as the sunxi-dw driver does).

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Tested-by: Jernej Skrabec <jernej.skrabec@siol.net>
Reviewed-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h |  27 ++++
 arch/arm/mach-sunxi/Kconfig                      |  10 +-
 arch/arm/mach-sunxi/Makefile                     |   1 +
 arch/arm/mach-sunxi/dram_sun50i_h6.c             | 150 +----------------------
 arch/arm/mach-sunxi/dram_timings/Makefile        |   1 +
 arch/arm/mach-sunxi/dram_timings/h6_lpddr3.c     | 132 ++++++++++++++++++++
 configs/beelink_gs1_defconfig                    |   1 +
 configs/orangepi_lite2_defconfig                 |   1 +
 configs/orangepi_one_plus_defconfig              |   1 +
 configs/pine_h64_defconfig                       |   1 +
 10 files changed, 177 insertions(+), 148 deletions(-)
 create mode 100644 arch/arm/mach-sunxi/dram_timings/h6_lpddr3.c

diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
index eeb4da5c3f..54c4755556 100644
--- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
@@ -287,6 +287,31 @@ check_member(sunxi_mctl_phy_reg, dx[3].reserved_0xf0, 0xaf0);
 #define DCR_DDR4	(4 << 0)
 #define DCR_DDR8BANK	BIT(3)
 
+/*
+ * The delay parameters allow to allegedly specify delay times of some
+ * unknown unit for each individual bit trace in each of the four data bytes
+ * the 32-bit wide access consists of. Also three control signals can be
+ * adjusted individually.
+ */
+#define NR_OF_BYTE_LANES	(32 / BITS_PER_BYTE)
+/* The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable and DQSN */
+#define WR_LINES_PER_BYTE_LANE	(BITS_PER_BYTE + 4)
+/*
+ * The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable, DQSN,
+ * Termination and Power down
+ */
+#define RD_LINES_PER_BYTE_LANE	(BITS_PER_BYTE + 6)
+struct dram_para {
+	u32 clk;
+	enum sunxi_dram_type type;
+	u8 cols;
+	u8 rows;
+	u8 ranks;
+	const u8 dx_read_delays[NR_OF_BYTE_LANES][RD_LINES_PER_BYTE_LANE];
+	const u8 dx_write_delays[NR_OF_BYTE_LANES][WR_LINES_PER_BYTE_LANE];
+};
+
+
 static inline int ns_to_t(int nanoseconds)
 {
 	const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
@@ -294,4 +319,6 @@ static inline int ns_to_t(int nanoseconds)
 	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
 }
 
+void mctl_set_timing_params(struct dram_para *para);
+
 #endif /* _SUNXI_DRAM_SUN50I_H6_H */
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 1669e62a6d..d588936850 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -340,7 +340,7 @@ config ARM_BOOT_HOOK_RMR
 	This allows both the SPL and the U-Boot proper to be entered in
 	either mode and switch to AArch64 if needed.
 
-if SUNXI_DRAM_DW
+if SUNXI_DRAM_DW || DRAM_SUN50I_H6
 config SUNXI_DRAM_DDR3
 	bool
 
@@ -370,6 +370,14 @@ config SUNXI_DRAM_LPDDR3_STOCK
 	This option is the LPDDR3 timing used by the stock boot0 by
 	Allwinner.
 
+config SUNXI_DRAM_H6_LPDDR3
+	bool "LPDDR3 DRAM chips on the H6 DRAM controller"
+	select SUNXI_DRAM_LPDDR3
+	depends on DRAM_SUN50I_H6
+	---help---
+	This option is the LPDDR3 timing used by the stock boot0 by
+	Allwinner.
+
 config SUNXI_DRAM_DDR2_V3S
 	bool "DDR2 found in V3s chip"
 	select SUNXI_DRAM_DDR2
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index 43a93e3085..d129f33479 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -39,4 +39,5 @@ obj-$(CONFIG_SPL_SPI_SUNXI)	+= spl_spi_sunxi.o
 obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_sunxi_dw.o
 obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_timings/
 obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_sun50i_h6.o
+obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_timings/
 endif
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c
index 7a8b724f08..697b8af4ce 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
@@ -32,33 +32,8 @@
  * similar PHY is ZynqMP.
  */
 
-/*
- * The delay parameters below allow to allegedly specify delay times of some
- * unknown unit for each individual bit trace in each of the four data bytes
- * the 32-bit wide access consists of. Also three control signals can be
- * adjusted individually.
- */
-#define NR_OF_BYTE_LANES	(32 / BITS_PER_BYTE)
-/* The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable and DQSN */
-#define WR_LINES_PER_BYTE_LANE	(BITS_PER_BYTE + 4)
-/*
- * The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable, DQSN,
- * Termination and Power down
- */
-#define RD_LINES_PER_BYTE_LANE	(BITS_PER_BYTE + 6)
-struct dram_para {
-	u32 clk;
-	enum sunxi_dram_type type;
-	u8 cols;
-	u8 rows;
-	u8 ranks;
-	const u8 dx_read_delays[NR_OF_BYTE_LANES][RD_LINES_PER_BYTE_LANE];
-	const u8 dx_write_delays[NR_OF_BYTE_LANES][WR_LINES_PER_BYTE_LANE];
-};
-
 static void mctl_sys_init(struct dram_para *para);
 static void mctl_com_init(struct dram_para *para);
-static void mctl_set_timing_lpddr3(struct dram_para *para);
 static void mctl_channel_init(struct dram_para *para);
 
 static void mctl_core_init(struct dram_para *para)
@@ -67,7 +42,7 @@ static void mctl_core_init(struct dram_para *para)
 	mctl_com_init(para);
 	switch (para->type) {
 	case SUNXI_DRAM_TYPE_LPDDR3:
-		mctl_set_timing_lpddr3(para);
+		mctl_set_timing_params(para);
 		break;
 	default:
 		panic("Unsupported DRAM type!");
@@ -171,127 +146,6 @@ static void mctl_set_master_priority(void)
 	MBUS_CONF(HDCP2,  true,    HIGH, 2,  100,   64,   32);
 }
 
-static u32 mr_lpddr3[12] = {
-	0x00000000, 0x00000043, 0x0000001a, 0x00000001,
-	0x00000000, 0x00000000, 0x00000048, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000003,
-};
-
-/* TODO: flexible timing */
-static void mctl_set_timing_lpddr3(struct dram_para *para)
-{
-	struct sunxi_mctl_ctl_reg * const mctl_ctl =
-			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
-	struct sunxi_mctl_phy_reg * const mctl_phy =
-			(struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
-	int i;
-
-	u8 tccd		= 2;
-	u8 tfaw		= max(ns_to_t(50), 4);
-	u8 trrd		= max(ns_to_t(10), 2);
-	u8 trcd		= max(ns_to_t(24), 2);
-	u8 trc		= ns_to_t(70);
-	u8 txp		= max(ns_to_t(8), 2);
-	u8 twtr		= max(ns_to_t(8), 2);
-	u8 trtp		= max(ns_to_t(8), 2);
-	u8 twr		= max(ns_to_t(15), 2);
-	u8 trp		= ns_to_t(18);
-	u8 tras		= ns_to_t(42);
-	u8 twtr_sa	= ns_to_t(5);
-	u8 tcksrea	= ns_to_t(11);
-	u16 trefi	= ns_to_t(3900) / 32;
-	u16 trfc	= ns_to_t(210);
-	u16 txsr	= ns_to_t(220);
-
-	if (CONFIG_DRAM_CLK % 400 == 0) {
-		/* Round up these parameters */
-		twtr_sa++;
-		tcksrea++;
-	}
-
-	u8 tmrw		= 5;
-	u8 tmrd		= 5;
-	u8 tmod		= 12;
-	u8 tcke		= 3;
-	u8 tcksrx	= 5;
-	u8 tcksre	= 5;
-	u8 tckesr	= 5;
-	u8 trasmax	= CONFIG_DRAM_CLK / 60;
-	u8 txs		= 4;
-	u8 txsdll	= 4;
-	u8 txsabort	= 4;
-	u8 txsfast	= 4;
-
-	u8 tcl		= 5; /* CL 10 */
-	u8 tcwl		= 3; /* CWL 6 */
-	u8 t_rdata_en	= twtr_sa + 8;
-
-	u32 tdinit0	= (200 * CONFIG_DRAM_CLK) + 1;		/* 200us */
-	u32 tdinit1	= (100 * CONFIG_DRAM_CLK) / 1000 + 1;	/* 100ns */
-	u32 tdinit2	= (11 * CONFIG_DRAM_CLK) + 1;		/* 11us */
-	u32 tdinit3	= (1 * CONFIG_DRAM_CLK) + 1;		/* 1us */
-
-	u8 twtp		= tcwl + 4 + twr + 1;
-	/*
-	 * The code below for twr2rd and trd2wr follows the IP core's
-	 * document from ZynqMP and i.MX7. The BSP has both number
-	 * substracted by 2.
-	 */
-	u8 twr2rd	= tcwl + 4 + 1 + twtr;
-	u8 trd2wr	= tcl + 4 + (tcksrea >> 1) - tcwl + 1;
-
-	/* set mode registers */
-	for (i = 0; i < ARRAY_SIZE(mr_lpddr3); i++)
-		writel(mr_lpddr3[i], &mctl_phy->mr[i]);
-
-	/* set DRAM timing */
-	writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
-	       &mctl_ctl->dramtmg[0]);
-	writel((txp << 16) | (trtp << 8) | trc, &mctl_ctl->dramtmg[1]);
-	writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | twr2rd,
-	       &mctl_ctl->dramtmg[2]);
-	writel((tmrw << 20) | (tmrd << 12) | tmod, &mctl_ctl->dramtmg[3]);
-	writel((trcd << 24) | (tccd << 16) | (trrd << 8) | trp,
-	       &mctl_ctl->dramtmg[4]);
-	writel((tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | tcke,
-	       &mctl_ctl->dramtmg[5]);
-	/* Value suggested by ZynqMP manual and used by libdram */
-	writel((txp + 2) | 0x02020000, &mctl_ctl->dramtmg[6]);
-	writel((txsfast << 24) | (txsabort << 16) | (txsdll << 8) | txs,
-	       &mctl_ctl->dramtmg[8]);
-	writel(txsr, &mctl_ctl->dramtmg[14]);
-
-	clrsetbits_le32(&mctl_ctl->init[0], (3 << 30), (1 << 30));
-	writel(0, &mctl_ctl->dfimisc);
-	clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
-
-	/*
-	 * Set timing registers of the PHY.
-	 * Note: the PHY is clocked 2x from the DRAM frequency.
-	 */
-	writel((trrd << 25) | (tras << 17) | (trp << 9) | (trtp << 1),
-	       &mctl_phy->dtpr[0]);
-	writel((tfaw << 17) | 0x28000400 | (tmrd << 1), &mctl_phy->dtpr[1]);
-	writel(((txs << 6) - 1) | (tcke << 17), &mctl_phy->dtpr[2]);
-	writel(((txsdll << 22) - (0x1 << 16)) | twtr_sa | (tcksrea << 8),
-	       &mctl_phy->dtpr[3]);
-	writel((txp << 1) | (trfc << 17) | 0x800, &mctl_phy->dtpr[4]);
-	writel((trc << 17) | (trcd << 9) | (twtr << 1), &mctl_phy->dtpr[5]);
-	writel(0x0505, &mctl_phy->dtpr[6]);
-
-	/* Configure DFI timing */
-	writel(tcl | 0x2000200 | (t_rdata_en << 16) | 0x808000,
-	       &mctl_ctl->dfitmg0);
-	writel(0x040201, &mctl_ctl->dfitmg1);
-
-	/* Configure PHY timing */
-	writel(tdinit0 | (tdinit1 << 20), &mctl_phy->ptr[3]);
-	writel(tdinit2 | (tdinit3 << 18), &mctl_phy->ptr[4]);
-
-	/* set refresh timing */
-	writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
-}
-
 static void mctl_sys_init(struct dram_para *para)
 {
 	struct sunxi_ccm_reg * const ccm =
@@ -735,12 +589,14 @@ unsigned long sunxi_dram_init(void)
 			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
 	struct dram_para para = {
 		.clk = CONFIG_DRAM_CLK,
+#ifdef CONFIG_SUNXI_DRAM_H6_LPDDR3
 		.type = SUNXI_DRAM_TYPE_LPDDR3,
 		.ranks = 2,
 		.cols = 11,
 		.rows = 14,
 		.dx_read_delays  = SUN50I_H6_DX_READ_DELAYS,
 		.dx_write_delays = SUN50I_H6_DX_WRITE_DELAYS,
+#endif
 	};
 
 	unsigned long size;
diff --git a/arch/arm/mach-sunxi/dram_timings/Makefile b/arch/arm/mach-sunxi/dram_timings/Makefile
index 278a8a14cc..0886a95968 100644
--- a/arch/arm/mach-sunxi/dram_timings/Makefile
+++ b/arch/arm/mach-sunxi/dram_timings/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_SUNXI_DRAM_DDR3_1333)	+= ddr3_1333.o
 obj-$(CONFIG_SUNXI_DRAM_LPDDR3_STOCK)	+= lpddr3_stock.o
 obj-$(CONFIG_SUNXI_DRAM_DDR2_V3S)	+= ddr2_v3s.o
+obj-$(CONFIG_SUNXI_DRAM_H6_LPDDR3)	+= h6_lpddr3.o
diff --git a/arch/arm/mach-sunxi/dram_timings/h6_lpddr3.c b/arch/arm/mach-sunxi/dram_timings/h6_lpddr3.c
new file mode 100644
index 0000000000..1000860113
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_timings/h6_lpddr3.c
@@ -0,0 +1,132 @@
+/*
+ * sun50i H6 LPDDR3 timings
+ *
+ * (C) Copyright 2017      Icenowy Zheng <icenowy@aosc.io>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/cpu.h>
+
+static u32 mr_lpddr3[12] = {
+	0x00000000, 0x00000043, 0x0000001a, 0x00000001,
+	0x00000000, 0x00000000, 0x00000048, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000003,
+};
+
+/* TODO: flexible timing */
+void mctl_set_timing_params(struct dram_para *para)
+{
+	struct sunxi_mctl_ctl_reg * const mctl_ctl =
+			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+	struct sunxi_mctl_phy_reg * const mctl_phy =
+			(struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
+	int i;
+
+	u8 tccd		= 2;
+	u8 tfaw		= max(ns_to_t(50), 4);
+	u8 trrd		= max(ns_to_t(10), 2);
+	u8 trcd		= max(ns_to_t(24), 2);
+	u8 trc		= ns_to_t(70);
+	u8 txp		= max(ns_to_t(8), 2);
+	u8 twtr		= max(ns_to_t(8), 2);
+	u8 trtp		= max(ns_to_t(8), 2);
+	u8 twr		= max(ns_to_t(15), 2);
+	u8 trp		= ns_to_t(18);
+	u8 tras		= ns_to_t(42);
+	u8 twtr_sa	= ns_to_t(5);
+	u8 tcksrea	= ns_to_t(11);
+	u16 trefi	= ns_to_t(3900) / 32;
+	u16 trfc	= ns_to_t(210);
+	u16 txsr	= ns_to_t(220);
+
+	if (CONFIG_DRAM_CLK % 400 == 0) {
+		/* Round up these parameters */
+		twtr_sa++;
+		tcksrea++;
+	}
+
+	u8 tmrw		= 5;
+	u8 tmrd		= 5;
+	u8 tmod		= 12;
+	u8 tcke		= 3;
+	u8 tcksrx	= 5;
+	u8 tcksre	= 5;
+	u8 tckesr	= 5;
+	u8 trasmax	= CONFIG_DRAM_CLK / 60;
+	u8 txs		= 4;
+	u8 txsdll	= 4;
+	u8 txsabort	= 4;
+	u8 txsfast	= 4;
+
+	u8 tcl		= 5; /* CL 10 */
+	u8 tcwl		= 3; /* CWL 6 */
+	u8 t_rdata_en	= twtr_sa + 8;
+
+	u32 tdinit0	= (200 * CONFIG_DRAM_CLK) + 1;		/* 200us */
+	u32 tdinit1	= (100 * CONFIG_DRAM_CLK) / 1000 + 1;	/* 100ns */
+	u32 tdinit2	= (11 * CONFIG_DRAM_CLK) + 1;		/* 11us */
+	u32 tdinit3	= (1 * CONFIG_DRAM_CLK) + 1;		/* 1us */
+
+	u8 twtp		= tcwl + 4 + twr + 1;
+	/*
+	 * The code below for twr2rd and trd2wr follows the IP core's
+	 * document from ZynqMP and i.MX7. The BSP has both number
+	 * substracted by 2.
+	 */
+	u8 twr2rd	= tcwl + 4 + 1 + twtr;
+	u8 trd2wr	= tcl + 4 + (tcksrea >> 1) - tcwl + 1;
+
+	/* set mode registers */
+	for (i = 0; i < ARRAY_SIZE(mr_lpddr3); i++)
+		writel(mr_lpddr3[i], &mctl_phy->mr[i]);
+
+	/* set DRAM timing */
+	writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
+	       &mctl_ctl->dramtmg[0]);
+	writel((txp << 16) | (trtp << 8) | trc, &mctl_ctl->dramtmg[1]);
+	writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | twr2rd,
+	       &mctl_ctl->dramtmg[2]);
+	writel((tmrw << 20) | (tmrd << 12) | tmod, &mctl_ctl->dramtmg[3]);
+	writel((trcd << 24) | (tccd << 16) | (trrd << 8) | trp,
+	       &mctl_ctl->dramtmg[4]);
+	writel((tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | tcke,
+	       &mctl_ctl->dramtmg[5]);
+	/* Value suggested by ZynqMP manual and used by libdram */
+	writel((txp + 2) | 0x02020000, &mctl_ctl->dramtmg[6]);
+	writel((txsfast << 24) | (txsabort << 16) | (txsdll << 8) | txs,
+	       &mctl_ctl->dramtmg[8]);
+	writel(txsr, &mctl_ctl->dramtmg[14]);
+
+	clrsetbits_le32(&mctl_ctl->init[0], (3 << 30), (1 << 30));
+	writel(0, &mctl_ctl->dfimisc);
+	clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
+
+	/*
+	 * Set timing registers of the PHY.
+	 * Note: the PHY is clocked 2x from the DRAM frequency.
+	 */
+	writel((trrd << 25) | (tras << 17) | (trp << 9) | (trtp << 1),
+	       &mctl_phy->dtpr[0]);
+	writel((tfaw << 17) | 0x28000400 | (tmrd << 1), &mctl_phy->dtpr[1]);
+	writel(((txs << 6) - 1) | (tcke << 17), &mctl_phy->dtpr[2]);
+	writel(((txsdll << 22) - (0x1 << 16)) | twtr_sa | (tcksrea << 8),
+	       &mctl_phy->dtpr[3]);
+	writel((txp << 1) | (trfc << 17) | 0x800, &mctl_phy->dtpr[4]);
+	writel((trc << 17) | (trcd << 9) | (twtr << 1), &mctl_phy->dtpr[5]);
+	writel(0x0505, &mctl_phy->dtpr[6]);
+
+	/* Configure DFI timing */
+	writel(tcl | 0x2000200 | (t_rdata_en << 16) | 0x808000,
+	       &mctl_ctl->dfitmg0);
+	writel(0x040201, &mctl_ctl->dfitmg1);
+
+	/* Configure PHY timing */
+	writel(tdinit0 | (tdinit1 << 20), &mctl_phy->ptr[3]);
+	writel(tdinit2 | (tdinit3 << 18), &mctl_phy->ptr[4]);
+
+	/* set refresh timing */
+	writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
+}
diff --git a/configs/beelink_gs1_defconfig b/configs/beelink_gs1_defconfig
index f16d0fee22..e970abd0ec 100644
--- a/configs/beelink_gs1_defconfig
+++ b/configs/beelink_gs1_defconfig
@@ -3,6 +3,7 @@ CONFIG_ARCH_SUNXI=y
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H6=y
+CONFIG_SUNXI_DRAM_H6_LPDDR3=y
 CONFIG_MMC0_CD_PIN="PF6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_PSCI_RESET is not set
diff --git a/configs/orangepi_lite2_defconfig b/configs/orangepi_lite2_defconfig
index e5c2846eaa..dc0a38ebe5 100644
--- a/configs/orangepi_lite2_defconfig
+++ b/configs/orangepi_lite2_defconfig
@@ -3,6 +3,7 @@ CONFIG_ARCH_SUNXI=y
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H6=y
+CONFIG_SUNXI_DRAM_H6_LPDDR3=y
 CONFIG_MMC0_CD_PIN="PF6"
 # CONFIG_PSCI_RESET is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/orangepi_one_plus_defconfig b/configs/orangepi_one_plus_defconfig
index 65537c422f..e4b9f3a1c8 100644
--- a/configs/orangepi_one_plus_defconfig
+++ b/configs/orangepi_one_plus_defconfig
@@ -3,6 +3,7 @@ CONFIG_ARCH_SUNXI=y
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H6=y
+CONFIG_SUNXI_DRAM_H6_LPDDR3=y
 CONFIG_MMC0_CD_PIN="PF6"
 # CONFIG_PSCI_RESET is not set
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
index 5ac89b462c..d88a6b1fd8 100644
--- a/configs/pine_h64_defconfig
+++ b/configs/pine_h64_defconfig
@@ -3,6 +3,7 @@ CONFIG_ARCH_SUNXI=y
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H6=y
+CONFIG_SUNXI_DRAM_H6_LPDDR3=y
 CONFIG_MMC0_CD_PIN="PF6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 # CONFIG_PSCI_RESET is not set
-- 
2.14.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 4/7] sunxi: H6: Add DDR3 support to DRAM controller driver
  2019-07-15  1:27 [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Andre Przywara
                   ` (2 preceding siblings ...)
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 3/7] sunxi: H6: move LPDDR3 timing definition into separate file Andre Przywara
@ 2019-07-15  1:27 ` Andre Przywara
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 5/7] sunxi: H6: Add DDR3-1333 timings Andre Przywara
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Andre Przywara @ 2019-07-15  1:27 UTC (permalink / raw)
  To: u-boot

At the moment the H6 DRAM driver only supports LPDDR3 DRAM.

Extend the driver to cover DDR3 DRAM as well.

The changes are partly motivated by looking at the ZynqMP register
documentation, partly by looking at register dumps after boot0/libdram
has initialised the controller.

Many thanks to Jernej for contributing some fixes!

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Tested-by: Jernej Skrabec <jernej.skrabec@siol.net>
Reviewed-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h |  8 +++
 arch/arm/mach-sunxi/dram_sun50i_h6.c             | 82 ++++++++++++++++--------
 2 files changed, 62 insertions(+), 28 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
index 54c4755556..0a1da02376 100644
--- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
@@ -9,6 +9,8 @@
 #ifndef _SUNXI_DRAM_SUN50I_H6_H
 #define _SUNXI_DRAM_SUN50I_H6_H
 
+#include <stdbool.h>
+
 enum sunxi_dram_type {
 	SUNXI_DRAM_TYPE_DDR3 = 3,
 	SUNXI_DRAM_TYPE_DDR4,
@@ -16,6 +18,11 @@ enum sunxi_dram_type {
 	SUNXI_DRAM_TYPE_LPDDR3,
 };
 
+static inline bool sunxi_dram_is_lpddr(int type)
+{
+	return type >= SUNXI_DRAM_TYPE_LPDDR2;
+}
+
 /*
  * The following information is mainly retrieved by disassembly and some FPGA
  * test code of sun50iw3 platform.
@@ -286,6 +293,7 @@ check_member(sunxi_mctl_phy_reg, dx[3].reserved_0xf0, 0xaf0);
 #define DCR_DDR3	(3 << 0)
 #define DCR_DDR4	(4 << 0)
 #define DCR_DDR8BANK	BIT(3)
+#define DCR_DDR2T	BIT(28)
 
 /*
  * The delay parameters allow to allegedly specify delay times of some
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c
index 697b8af4ce..17649ffbf9 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
@@ -42,6 +42,7 @@ static void mctl_core_init(struct dram_para *para)
 	mctl_com_init(para);
 	switch (para->type) {
 	case SUNXI_DRAM_TYPE_LPDDR3:
+	case SUNXI_DRAM_TYPE_DDR3:
 		mctl_set_timing_params(para);
 		break;
 	default:
@@ -284,14 +285,11 @@ static void mctl_com_init(struct dram_para *para)
 	mctl_set_addrmap(para);
 
 	setbits_le32(&mctl_com->cr, BIT(31));
-	/*
-	 * This address is magic; it's in SID memory area, but there's no
-	 * known definition of it.
-	 * On my Pine H64 board it has content 7.
-	 */
-	if (readl(0x03006100) == 7)
+
+	/* The bonding ID seems to be always 7. */
+	if (readl(SUNXI_SIDC_BASE + 0x100) == 7)	/* bonding ID */
 		clrbits_le32(&mctl_com->cr, BIT(27));
-	else if (readl(0x03006100) == 3)
+	else if (readl(SUNXI_SIDC_BASE + 0x100) == 3)
 		setbits_le32(&mctl_com->cr, BIT(27));
 
 	if (para->clk > 408)
@@ -302,22 +300,37 @@ static void mctl_com_init(struct dram_para *para)
 		reg_val = 0x3f00;
 	clrsetbits_le32(&mctl_com->unk_0x008, 0x3f00, reg_val);
 
-	/* TODO: half DQ, non-LPDDR3 types */
-	writel(MSTR_DEVICETYPE_LPDDR3 | MSTR_BUSWIDTH_FULL |
-	       MSTR_BURST_LENGTH(8) | MSTR_ACTIVE_RANKS(para->ranks) |
-	       0x80000000, &mctl_ctl->mstr);
-	writel(DCR_LPDDR3 | DCR_DDR8BANK | 0x400, &mctl_phy->dcr);
+	/* TODO: half DQ, DDR4 */
+	reg_val = MSTR_BUSWIDTH_FULL | MSTR_BURST_LENGTH(8) |
+		  MSTR_ACTIVE_RANKS(para->ranks);
+	if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
+		reg_val |= MSTR_DEVICETYPE_LPDDR3;
+	if (para->type == SUNXI_DRAM_TYPE_DDR3)
+		reg_val |= MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE;
+	writel(reg_val | BIT(31), &mctl_ctl->mstr);
+
+	if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
+		reg_val = DCR_LPDDR3 | DCR_DDR8BANK;
+	if (para->type == SUNXI_DRAM_TYPE_DDR3)
+		reg_val = DCR_DDR3 | DCR_DDR8BANK | DCR_DDR2T;
+	writel(reg_val | 0x400, &mctl_phy->dcr);
 
 	if (para->ranks == 2)
 		writel(0x0303, &mctl_ctl->odtmap);
 	else
 		writel(0x0201, &mctl_ctl->odtmap);
 
-	/* TODO: non-LPDDR3 types */
-	tmp = para->clk * 7 / 2000;
-	reg_val = 0x0400;
-	reg_val |= (tmp + 7) << 24;
-	reg_val |= (((para->clk < 400) ? 3 : 4) - tmp) << 16;
+	/* TODO: DDR4 */
+	if (para->type == SUNXI_DRAM_TYPE_LPDDR3) {
+		tmp = para->clk * 7 / 2000;
+		reg_val = 0x0400;
+		reg_val |= (tmp + 7) << 24;
+		reg_val |= (((para->clk < 400) ? 3 : 4) - tmp) << 16;
+	} else if (para->type == SUNXI_DRAM_TYPE_DDR3) {
+		reg_val = 0x06000400;	/* TODO?: Use CL - CWL value in [7:0] */
+	} else {
+		panic("Only (LP)DDR3 supported (type = %d)\n", para->type);
+	}
 	writel(reg_val, &mctl_ctl->odtcfg);
 
 	/* TODO: half DQ */
@@ -372,6 +385,9 @@ static void mctl_bit_delay_set(struct dram_para *para)
 	setbits_le32(&mctl_phy->pgcr[0], BIT(26));
 	udelay(1);
 
+	if (para->type != SUNXI_DRAM_TYPE_LPDDR3)
+		return;
+
 	for (i = 1; i < 14; i++) {
 		val = readl(&mctl_phy->acbdlr[i]);
 		val += 0x0a0a0a0a;
@@ -419,7 +435,8 @@ static void mctl_channel_init(struct dram_para *para)
 	else
 		clrsetbits_le32(&mctl_phy->dtcr[1], 0x30000, 0x10000);
 
-	clrbits_le32(&mctl_phy->dtcr[1], BIT(1));
+	if (sunxi_dram_is_lpddr(para->type))
+		clrbits_le32(&mctl_phy->dtcr[1], BIT(1));
 	if (para->ranks == 2) {
 		writel(0x00010001, &mctl_phy->rankidr);
 		writel(0x20000, &mctl_phy->odtcr);
@@ -428,8 +445,11 @@ static void mctl_channel_init(struct dram_para *para)
 		writel(0x10000, &mctl_phy->odtcr);
 	}
 
-	/* TODO: non-LPDDR3 types */
-	clrsetbits_le32(&mctl_phy->dtcr[0], 0xF0000000, 0x10000040);
+	/* set bits [3:0] to 1? 0 not valid in ZynqMP d/s */
+	if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
+		clrsetbits_le32(&mctl_phy->dtcr[0], 0xF0000000, 0x10000040);
+	else
+		clrsetbits_le32(&mctl_phy->dtcr[0], 0xF0000000, 0x10000000);
 	if (para->clk <= 792) {
 		if (para->clk <= 672) {
 			if (para->clk <= 600)
@@ -459,12 +479,13 @@ static void mctl_channel_init(struct dram_para *para)
 			writel(0x06060606, &mctl_phy->acbdlr[i]);
 	}
 
-	/* TODO: non-LPDDR3 types */
-	mctl_phy_pir_init(PIR_ZCAL | PIR_DCAL | PIR_PHYRST | PIR_DRAMINIT |
-			  PIR_QSGATE | PIR_RDDSKW | PIR_WRDSKW | PIR_RDEYE |
-			  PIR_WREYE);
+	val = PIR_ZCAL | PIR_DCAL | PIR_PHYRST | PIR_DRAMINIT | PIR_QSGATE |
+	      PIR_RDDSKW | PIR_WRDSKW | PIR_RDEYE | PIR_WREYE;
+	if (para->type == SUNXI_DRAM_TYPE_DDR3)
+		val |= PIR_DRAMRST | PIR_WL;
+	mctl_phy_pir_init(val);
 
-	/* TODO: non-LPDDR3 types */
+	/* TODO: DDR4 types ? */
 	for (i = 0; i < 4; i++)
 		writel(0x00000909, &mctl_phy->dx[i].gcr[5]);
 
@@ -520,7 +541,8 @@ static void mctl_channel_init(struct dram_para *para)
 		panic("Error while initializing DRAM PHY!\n");
 	}
 
-	clrsetbits_le32(&mctl_phy->dsgcr, 0xc0, 0x40);
+	if (sunxi_dram_is_lpddr(para->type))
+		clrsetbits_le32(&mctl_phy->dsgcr, 0xc0, 0x40);
 	clrbits_le32(&mctl_phy->pgcr[1], 0x40);
 	clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
 	writel(1, &mctl_ctl->swctl);
@@ -589,11 +611,15 @@ unsigned long sunxi_dram_init(void)
 			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
 	struct dram_para para = {
 		.clk = CONFIG_DRAM_CLK,
-#ifdef CONFIG_SUNXI_DRAM_H6_LPDDR3
-		.type = SUNXI_DRAM_TYPE_LPDDR3,
 		.ranks = 2,
 		.cols = 11,
 		.rows = 14,
+#ifdef CONFIG_SUNXI_DRAM_H6_LPDDR3
+		.type = SUNXI_DRAM_TYPE_LPDDR3,
+		.dx_read_delays  = SUN50I_H6_DX_READ_DELAYS,
+		.dx_write_delays = SUN50I_H6_DX_WRITE_DELAYS,
+#elif defined(CONFIG_SUNXI_DRAM_H6_DDR3_1333)
+		.type = SUNXI_DRAM_TYPE_DDR3,
 		.dx_read_delays  = SUN50I_H6_DX_READ_DELAYS,
 		.dx_write_delays = SUN50I_H6_DX_WRITE_DELAYS,
 #endif
-- 
2.14.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 5/7] sunxi: H6: Add DDR3-1333 timings
  2019-07-15  1:27 [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Andre Przywara
                   ` (3 preceding siblings ...)
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 4/7] sunxi: H6: Add DDR3 support to DRAM controller driver Andre Przywara
@ 2019-07-15  1:27 ` Andre Przywara
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 6/7] sunxi: H6: Add DDR3 DRAM delay values Andre Przywara
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Andre Przywara @ 2019-07-15  1:27 UTC (permalink / raw)
  To: u-boot

Add a routine to program the timing parameters for DDR3-1333 DRAM chips
connected to the H6 DRAM controller.

The values were gathered from doing back-calculations from a register
dump, trying to match them up with the official JEDEC DDDR3 spec.
If in doubt, the register dump values were taken for now, but the JEDEC
recommendation were added as a comment.

Many thanks to Jernej for contributing fixes!

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Tested-by: Jernej Skrabec <jernej.skrabec@siol.net>
Reviewed-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/mach-sunxi/Kconfig                     |   8 ++
 arch/arm/mach-sunxi/dram_timings/Makefile       |   1 +
 arch/arm/mach-sunxi/dram_timings/h6_ddr3_1333.c | 144 ++++++++++++++++++++++++
 3 files changed, 153 insertions(+)
 create mode 100644 arch/arm/mach-sunxi/dram_timings/h6_ddr3_1333.c

diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index d588936850..d4e7d89e9e 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -378,6 +378,14 @@ config SUNXI_DRAM_H6_LPDDR3
 	This option is the LPDDR3 timing used by the stock boot0 by
 	Allwinner.
 
+config SUNXI_DRAM_H6_DDR3_1333
+	bool "DDR3-1333 boot0 timings on the H6 DRAM controller"
+	select SUNXI_DRAM_DDR3
+	depends on DRAM_SUN50I_H6
+	---help---
+	This option is the DDR3 timing used by the boot0 on H6 TV boxes
+	which use a DDR3-1333 timing.
+
 config SUNXI_DRAM_DDR2_V3S
 	bool "DDR2 found in V3s chip"
 	select SUNXI_DRAM_DDR2
diff --git a/arch/arm/mach-sunxi/dram_timings/Makefile b/arch/arm/mach-sunxi/dram_timings/Makefile
index 0886a95968..0deb9911fd 100644
--- a/arch/arm/mach-sunxi/dram_timings/Makefile
+++ b/arch/arm/mach-sunxi/dram_timings/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_SUNXI_DRAM_DDR3_1333)	+= ddr3_1333.o
 obj-$(CONFIG_SUNXI_DRAM_LPDDR3_STOCK)	+= lpddr3_stock.o
 obj-$(CONFIG_SUNXI_DRAM_DDR2_V3S)	+= ddr2_v3s.o
 obj-$(CONFIG_SUNXI_DRAM_H6_LPDDR3)	+= h6_lpddr3.o
+obj-$(CONFIG_SUNXI_DRAM_H6_DDR3_1333)	+= h6_ddr3_1333.o
diff --git a/arch/arm/mach-sunxi/dram_timings/h6_ddr3_1333.c b/arch/arm/mach-sunxi/dram_timings/h6_ddr3_1333.c
new file mode 100644
index 0000000000..611eaa3024
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_timings/h6_ddr3_1333.c
@@ -0,0 +1,144 @@
+/*
+ * sun50i H6 DDR3-1333 timings, as programmed by Allwinner's boot0
+ * for some TV boxes with the H6 and DDR3 memory.
+ *
+ * The chips are probably able to be driven by a faster clock, but boot0
+ * uses a more conservative timing (as usual).
+ *
+ * (C) Copyright 2018,2019 Arm Ltd.
+ *   based on previous work by:
+ *   (C) Copyright 2017      Icenowy Zheng <icenowy@aosc.io>
+ *
+ * References used:
+ * - JEDEC DDR3 SDRAM standard:	JESD79-3F.pdf
+ * - Samsung K4B2G0446D datasheet
+ * - ZynqMP UG1087 register DDRC/PHY documentation
+ *
+ * Many thanks to Jernej Skrabec for contributing some fixes!
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/cpu.h>
+
+/*
+ * Only the first four are used for DDR3(?)
+ * MR0: BL8, seq. read burst, no test, fast exit (DLL on), no DLL reset,
+ *	CAS latency (CL): 11, write recovery (WR): 12
+ * MR1: DLL enabled, output strength RZQ/6, Rtt_norm RZQ/2,
+ *	write levelling disabled, TDQS disabled, output buffer enabled
+ * MR2: manual full array self refresh, dynamic ODT off,
+ * 	CAS write latency (CWL): 8
+ */
+static u32 mr_ddr3[7] = {
+	0x00001c70, 0x00000040, 0x00000018, 0x00000000,
+	0x00000000, 0x00000400, 0x00000848,
+};
+
+/* TODO: flexible timing */
+void mctl_set_timing_params(struct dram_para *para)
+{
+	struct sunxi_mctl_ctl_reg * const mctl_ctl =
+			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+	struct sunxi_mctl_phy_reg * const mctl_phy =
+			(struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
+	int i;
+
+	u8 tccd		= 2;			/* JEDEC: 4nCK */
+	u8 tfaw		= ns_to_t(50);		/* JEDEC: 30 ns w/ 1K pages */
+	u8 trrd		= max(ns_to_t(6), 4);	/* JEDEC: max(6 ns, 4nCK) */
+	u8 trcd		= ns_to_t(15);		/* JEDEC: 13.5 ns */
+	u8 trc		= ns_to_t(53);		/* JEDEC: 49.5 ns */
+	u8 txp		= max(ns_to_t(6), 3);	/* JEDEC: max(6 ns, 3nCK) */
+	u8 twtr		= max(ns_to_t(8), 2);	/* JEDEC: max(7.5 ns, 4nCK) */
+	u8 trtp		= max(ns_to_t(8), 2);	/* JEDEC: max(7.5 ns, 4nCK) */
+	u8 twr		= ns_to_t(15);		/* JEDEC: 15 ns */
+	u8 trp		= ns_to_t(15);		/* JEDEC: >= 13.75 ns */
+	u8 tras		= ns_to_t(38);		/* JEDEC >= 36 ns, <= 9*trefi */
+	u8 twtr_sa	= 2;			/* ? */
+	u8 tcksrea	= 4;			/* ? */
+	u16 trefi	= ns_to_t(7800) / 32;	/* JEDEC: 7.8us@Tcase <= 85C */
+	u16 trfc	= ns_to_t(350);		/* JEDEC: 160 ns for 2Gb */
+	u16 txsr	= 4;			/* ? */
+
+	u8 tmrw		= 0;			/* ? */
+	u8 tmrd		= 4;			/* JEDEC: 4nCK */
+	u8 tmod		= max(ns_to_t(15), 12);	/* JEDEC: max(15 ns, 12nCK) */
+	u8 tcke		= max(ns_to_t(6), 3);	/* JEDEC: max(5.625 ns, 3nCK) */
+	u8 tcksrx	= max(ns_to_t(10), 5);	/* JEDEC: max(10 ns, 5nCK) */
+	u8 tcksre	= max(ns_to_t(10), 5);	/* JEDEC: max(10 ns, 5nCK) */
+	u8 tckesr	= tcke + 1;		/* JEDEC: tCKE(min) + 1nCK */
+	u8 trasmax	= 24;			/* JEDEC: tREFI * 9 */
+	u8 txs		= ns_to_t(360) / 32;	/* JEDEC: max(5nCK,tRFC+10ns) */
+	u8 txsdll	= 4;			/* JEDEC: 512 nCK */
+	u8 txsabort	= 4;			/* ? */
+	u8 txsfast	= 4;			/* ? */
+	u8 tcl		= 6;			/* JEDEC: CL / 2 => 6 */
+	u8 tcwl		= 4;			/* JEDEC: 8 */
+	u8 t_rdata_en	= 7;			/* ? */
+
+	u32 tdinit0	= (500 * CONFIG_DRAM_CLK) + 1;	/* 500us */
+	u32 tdinit1	= (360 * CONFIG_DRAM_CLK) / 1000 + 1;
+	u32 tdinit2	= (200 * CONFIG_DRAM_CLK) + 1;
+	u32 tdinit3	= (1 * CONFIG_DRAM_CLK) + 1;	/* 1us */
+
+	u8 twtp		= tcwl + 2 + twr;	/* (WL + BL / 2 + tWR) / 2 */
+	u8 twr2rd	= tcwl + 2 + twtr;	/* (WL + BL / 2 + tWTR) / 2 */
+	u8 trd2wr	= 5;			/* (RL + BL / 2 + 2 - WL) / 2 */
+
+	if (tcl + 1 >= trtp + trp)
+		trtp = tcl + 2 - trp;
+
+	/* set mode registers */
+	for (i = 0; i < ARRAY_SIZE(mr_ddr3); i++)
+		writel(mr_ddr3[i], &mctl_phy->mr[i]);
+
+	/* set DRAM timing */
+	writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
+	       &mctl_ctl->dramtmg[0]);
+	writel((txp << 16) | (trtp << 8) | trc, &mctl_ctl->dramtmg[1]);
+	writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | twr2rd,
+	       &mctl_ctl->dramtmg[2]);
+	writel((tmrw << 20) | (tmrd << 12) | tmod, &mctl_ctl->dramtmg[3]);
+	writel((trcd << 24) | (tccd << 16) | (trrd << 8) | trp,
+	       &mctl_ctl->dramtmg[4]);
+	writel((tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | tcke,
+	       &mctl_ctl->dramtmg[5]);
+	/* Value suggested by ZynqMP manual and used by libdram */
+	writel((txp + 2) | 0x02020000, &mctl_ctl->dramtmg[6]);
+	writel((txsfast << 24) | (txsabort << 16) | (txsdll << 8) | txs,
+	       &mctl_ctl->dramtmg[8]);
+	writel(txsr, &mctl_ctl->dramtmg[14]);
+
+	clrsetbits_le32(&mctl_ctl->init[0], (3 << 30), (1 << 30));
+	writel(0, &mctl_ctl->dfimisc);
+	clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
+
+	/*
+	 * Set timing registers of the PHY.
+	 * Note: the PHY is clocked 2x from the DRAM frequency.
+	 */
+	writel((trrd << 25) | (tras << 17) | (trp << 9) | (trtp << 1),
+	       &mctl_phy->dtpr[0]);
+	writel((tfaw << 17) | 0x28000400 | (tmrd << 1), &mctl_phy->dtpr[1]);
+	writel(((txs << 6) - 1) | (tcke << 17), &mctl_phy->dtpr[2]);
+	writel(((txsdll << 22) - (0x1 << 16)) | twtr_sa | (tcksrea << 8),
+	       &mctl_phy->dtpr[3]);
+	writel((txp << 1) | (trfc << 17) | 0x800, &mctl_phy->dtpr[4]);
+	writel((trc << 17) | (trcd << 9) | (twtr << 1), &mctl_phy->dtpr[5]);
+	writel(0x0505, &mctl_phy->dtpr[6]);
+
+	/* Configure DFI timing */
+	writel(tcl | 0x2000200 | (t_rdata_en << 16) | 0x808000,
+	       &mctl_ctl->dfitmg0);
+	writel(0x040201, &mctl_ctl->dfitmg1);
+
+	/* Configure PHY timing. Zynq uses different registers. */
+	writel(tdinit0 | (tdinit1 << 20), &mctl_phy->ptr[3]);
+	writel(tdinit2 | (tdinit3 << 18), &mctl_phy->ptr[4]);
+
+	/* set refresh timing */
+	writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
+}
-- 
2.14.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 6/7] sunxi: H6: Add DDR3 DRAM delay values
  2019-07-15  1:27 [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Andre Przywara
                   ` (4 preceding siblings ...)
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 5/7] sunxi: H6: Add DDR3-1333 timings Andre Przywara
@ 2019-07-15  1:27 ` Andre Przywara
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 7/7] sunxi: H6: Add basic Eachlink H6 Mini support Andre Przywara
  2019-07-15 11:14 ` [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Jagan Teki
  7 siblings, 0 replies; 14+ messages in thread
From: Andre Przywara @ 2019-07-15  1:27 UTC (permalink / raw)
  To: u-boot

From: Jernej Skrabec <jernej.skrabec@siol.net>

Add some basic line delay values to be used with DDR3 DRAM chips on
some H6 TV boxes.
Taken from a register dump after boot0 initialised the DRAM.
Put them as the default delay values for DDR3 DRAM until we know better.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/mach-sunxi/dram_sun50i_h6.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c
index 17649ffbf9..2a8275da3a 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
@@ -594,17 +594,28 @@ unsigned long mctl_calc_size(struct dram_para *para)
 	return (1ULL << (para->cols + para->rows + 3)) * 4 * para->ranks;
 }
 
-#define SUN50I_H6_DX_WRITE_DELAYS				\
+#define SUN50I_H6_LPDDR3_DX_WRITE_DELAYS			\
 	{{  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
 	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
 	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  4,  0 },	\
 	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }}
-#define SUN50I_H6_DX_READ_DELAYS					\
+#define SUN50I_H6_LPDDR3_DX_READ_DELAYS					\
 	{{  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 },	\
 	 {  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 },	\
 	 {  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 },	\
 	 {  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 }}
 
+#define SUN50I_H6_DDR3_DX_WRITE_DELAYS				\
+	{{  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }}
+#define SUN50I_H6_DDR3_DX_READ_DELAYS					\
+	{{  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  4,  4,  4,  4,  4,  4,  4,  4,  4,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }}
+
 unsigned long sunxi_dram_init(void)
 {
 	struct sunxi_mctl_com_reg * const mctl_com =
@@ -616,12 +627,12 @@ unsigned long sunxi_dram_init(void)
 		.rows = 14,
 #ifdef CONFIG_SUNXI_DRAM_H6_LPDDR3
 		.type = SUNXI_DRAM_TYPE_LPDDR3,
-		.dx_read_delays  = SUN50I_H6_DX_READ_DELAYS,
-		.dx_write_delays = SUN50I_H6_DX_WRITE_DELAYS,
+		.dx_read_delays  = SUN50I_H6_LPDDR3_DX_READ_DELAYS,
+		.dx_write_delays = SUN50I_H6_LPDDR3_DX_WRITE_DELAYS,
 #elif defined(CONFIG_SUNXI_DRAM_H6_DDR3_1333)
 		.type = SUNXI_DRAM_TYPE_DDR3,
-		.dx_read_delays  = SUN50I_H6_DX_READ_DELAYS,
-		.dx_write_delays = SUN50I_H6_DX_WRITE_DELAYS,
+		.dx_read_delays  = SUN50I_H6_DDR3_DX_READ_DELAYS,
+		.dx_write_delays = SUN50I_H6_DDR3_DX_WRITE_DELAYS,
 #endif
 	};
 
-- 
2.14.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 7/7] sunxi: H6: Add basic Eachlink H6 Mini support
  2019-07-15  1:27 [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Andre Przywara
                   ` (5 preceding siblings ...)
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 6/7] sunxi: H6: Add DDR3 DRAM delay values Andre Przywara
@ 2019-07-15  1:27 ` Andre Przywara
  2019-07-15  7:11   ` Jagan Teki
  2019-07-15 11:14 ` [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Jagan Teki
  7 siblings, 1 reply; 14+ messages in thread
From: Andre Przywara @ 2019-07-15  1:27 UTC (permalink / raw)
  To: u-boot

The Eachlink H6 Mini is a modestly priced TV box, using the Allwinner H6
SoC. It comes with 3GB of DRAM and 32GB of eMMC in the typical TV box
enclosure.

This adds a basic device tree and defconfig for it.

It contrast to the other supported H6 boards the H6 Mini uses DDR3 DRAM
chips (not LPDDR3), which require a different DRAM controller setup.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/dts/Makefile                       |   1 +
 arch/arm/dts/sun50i-h6-eachlink-h6-mini.dts | 116 ++++++++++++++++++++++++++++
 board/sunxi/MAINTAINERS                     |   6 ++
 configs/eachlink_h6_mini_defconfig          |  17 ++++
 4 files changed, 140 insertions(+)
 create mode 100644 arch/arm/dts/sun50i-h6-eachlink-h6-mini.dts
 create mode 100644 configs/eachlink_h6_mini_defconfig

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 39cf4c3b3d..dd676ac090 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -511,6 +511,7 @@ dtb-$(CONFIG_MACH_SUN50I_H5) += \
 	sun50i-h5-orangepi-zero-plus2.dtb
 dtb-$(CONFIG_MACH_SUN50I_H6) += \
 	sun50i-h6-beelink-gs1.dtb \
+	sun50i-h6-eachlink-h6-mini.dtb \
 	sun50i-h6-orangepi-lite2.dtb \
 	sun50i-h6-orangepi-one-plus.dtb \
 	sun50i-h6-pine-h64.dtb
diff --git a/arch/arm/dts/sun50i-h6-eachlink-h6-mini.dts b/arch/arm/dts/sun50i-h6-eachlink-h6-mini.dts
new file mode 100644
index 0000000000..5956b5ccd7
--- /dev/null
+++ b/arch/arm/dts/sun50i-h6-eachlink-h6-mini.dts
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (c) 2018 Arm Ltd.
+ * based on work by:
+ *   Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+/dts-v1/;
+
+#include "sun50i-h6.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Eachlink H6 Mini";
+	compatible = "eachlink,h6-mini", "allwinner,sun50i-h6";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	connector {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_in: endpoint {
+				remote-endpoint = <&hdmi_out_con>;
+			};
+		};
+	};
+
+	reg_vcc3v3: vcc3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	reg_vcc5v: vcc5v {
+		/* supply from the micro-USB DC jack */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+};
+
+&de {
+	status = "okay";
+};
+
+&hdmi {
+	status = "okay";
+};
+
+&hdmi_out {
+	hdmi_out_con: endpoint {
+		remote-endpoint = <&hdmi_con_in>;
+	};
+};
+
+&ehci0 {
+	phys = <&usb2phy 0>;
+	status = "okay";
+};
+
+&ehci3 {
+	status = "okay";
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_vcc3v3>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&mmc2 {
+	vmmc-supply = <&reg_vcc3v3>;
+	vqmmc-supply = <&reg_vcc3v3>;
+	non-removable;
+	cap-mmc-hw-reset;
+	bus-width = <8>;
+	status = "okay";
+};
+
+&ohci0 {
+	phys = <&usb2phy 0>;
+	status = "okay";
+};
+
+&ohci3 {
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_ph_pins>;
+	status = "okay";
+};
+
+&usb2otg {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usb2phy {
+	usb0_vbus-supply = <&reg_vcc5v>;
+	status = "okay";
+};
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index bdd1854197..fa8c2ef181 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -195,6 +195,12 @@ M:	Chen-Yu Tsai <wens@csie.org>
 S:	Maintained
 F:	configs/Cubietruck_plus_defconfig
 
+EACHLINK H6 MINI
+M:	Andre Przywara <andre.przywara@arm.com>
+S:	Maintained
+F:	configs/eachlink_h6_mini_defconfig
+F:	arch/arm/dts/sun50i-h6-eachlink-h6-mini.dts
+
 EMLID NEUTIS N5 DEV BOARD
 M:	Aleksandr Aleksandrov <aleksandr.aleksandrov@emlid.com>
 S:	Maintained
diff --git a/configs/eachlink_h6_mini_defconfig b/configs/eachlink_h6_mini_defconfig
new file mode 100644
index 0000000000..d471a24dd5
--- /dev/null
+++ b/configs/eachlink_h6_mini_defconfig
@@ -0,0 +1,17 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SPL=y
+CONFIG_MACH_SUN50I_H6=y
+CONFIG_DRAM_CLK=660
+CONFIG_DRAM_ZQ=3881979
+CONFIG_SUNXI_DRAM_H6_DDR3_1333=y
+CONFIG_MMC0_CD_PIN="PF6"
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+# CONFIG_PSCI_RESET is not set
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL_TEXT_BASE=0x20060
+# CONFIG_CMD_FLASH is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-eachlink-h6-mini"
-- 
2.14.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 7/7] sunxi: H6: Add basic Eachlink H6 Mini support
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 7/7] sunxi: H6: Add basic Eachlink H6 Mini support Andre Przywara
@ 2019-07-15  7:11   ` Jagan Teki
  2019-07-15  9:21     ` Andre Przywara
  0 siblings, 1 reply; 14+ messages in thread
From: Jagan Teki @ 2019-07-15  7:11 UTC (permalink / raw)
  To: u-boot

On Mon, Jul 15, 2019 at 6:57 AM Andre Przywara <andre.przywara@arm.com> wrote:
>
> The Eachlink H6 Mini is a modestly priced TV box, using the Allwinner H6
> SoC. It comes with 3GB of DRAM and 32GB of eMMC in the typical TV box
> enclosure.
>
> This adds a basic device tree and defconfig for it.
>
> It contrast to the other supported H6 boards the H6 Mini uses DDR3 DRAM
> chips (not LPDDR3), which require a different DRAM controller setup.

Send the linux sync commit, rest seems to fine for me. will update the
commit while applying.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 7/7] sunxi: H6: Add basic Eachlink H6 Mini support
  2019-07-15  7:11   ` Jagan Teki
@ 2019-07-15  9:21     ` Andre Przywara
  2019-07-15 10:13       ` Jagan Teki
  0 siblings, 1 reply; 14+ messages in thread
From: Andre Przywara @ 2019-07-15  9:21 UTC (permalink / raw)
  To: u-boot

On Mon, 15 Jul 2019 12:41:34 +0530
Jagan Teki <jagan@amarulasolutions.com> wrote:

Hi Jagan!

> On Mon, Jul 15, 2019 at 6:57 AM Andre Przywara <andre.przywara@arm.com> wrote:
> >
> > The Eachlink H6 Mini is a modestly priced TV box, using the Allwinner H6
> > SoC. It comes with 3GB of DRAM and 32GB of eMMC in the typical TV box
> > enclosure.
> >
> > This adds a basic device tree and defconfig for it.
> >
> > It contrast to the other supported H6 boards the H6 Mini uses DDR3 DRAM
> > chips (not LPDDR3), which require a different DRAM controller setup.  
> 
> Send the linux sync commit, rest seems to fine for me. will update the
> commit while applying.

Which sync commit? I haven't send a device tree for Linux yet, if that is
what you mean. Reason is I don't have much working beyond MMC and
USB(2.0). I was hoping for at least HDMI to work, because this is a TV box
and requires opening and soldering to get serial output.
Also I guess it's a bit of a chicken and egg problem, a Linux DT wouldn't
make much sense without U-Boot support, especially if it's more than just
a defconfig as in this case.

So can we just merge this patch as well? Then people can at least start to
play with it. We can sync and update the DT later.

Cheers,
Andre.

P.S. I will try to send a sunxi64 Linux->U-Boot DT sync later this week. I
have the patches ready, just need to test them with several kernels.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 7/7] sunxi: H6: Add basic Eachlink H6 Mini support
  2019-07-15  9:21     ` Andre Przywara
@ 2019-07-15 10:13       ` Jagan Teki
  2019-07-15 10:21         ` Andre Przywara
  0 siblings, 1 reply; 14+ messages in thread
From: Jagan Teki @ 2019-07-15 10:13 UTC (permalink / raw)
  To: u-boot

On Mon, Jul 15, 2019 at 2:51 PM Andre Przywara <andre.przywara@arm.com> wrote:
>
> On Mon, 15 Jul 2019 12:41:34 +0530
> Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> Hi Jagan!
>
> > On Mon, Jul 15, 2019 at 6:57 AM Andre Przywara <andre.przywara@arm.com> wrote:
> > >
> > > The Eachlink H6 Mini is a modestly priced TV box, using the Allwinner H6
> > > SoC. It comes with 3GB of DRAM and 32GB of eMMC in the typical TV box
> > > enclosure.
> > >
> > > This adds a basic device tree and defconfig for it.
> > >
> > > It contrast to the other supported H6 boards the H6 Mini uses DDR3 DRAM
> > > chips (not LPDDR3), which require a different DRAM controller setup.
> >
> > Send the linux sync commit, rest seems to fine for me. will update the
> > commit while applying.
>
> Which sync commit? I haven't send a device tree for Linux yet, if that is

sun50i-h6-eachlink-h6-mini.dts this was synced from Linux right? need
head commit id of this dts.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 7/7] sunxi: H6: Add basic Eachlink H6 Mini support
  2019-07-15 10:13       ` Jagan Teki
@ 2019-07-15 10:21         ` Andre Przywara
  2019-07-15 11:13           ` Jagan Teki
  0 siblings, 1 reply; 14+ messages in thread
From: Andre Przywara @ 2019-07-15 10:21 UTC (permalink / raw)
  To: u-boot

On Mon, 15 Jul 2019 15:43:10 +0530
Jagan Teki <jagan@amarulasolutions.com> wrote:

Hi,

> On Mon, Jul 15, 2019 at 2:51 PM Andre Przywara <andre.przywara@arm.com> wrote:
> >
> > On Mon, 15 Jul 2019 12:41:34 +0530
> > Jagan Teki <jagan@amarulasolutions.com> wrote:
> >
> > Hi Jagan!
> >  
> > > On Mon, Jul 15, 2019 at 6:57 AM Andre Przywara <andre.przywara@arm.com> wrote:  
> > > >
> > > > The Eachlink H6 Mini is a modestly priced TV box, using the Allwinner H6
> > > > SoC. It comes with 3GB of DRAM and 32GB of eMMC in the typical TV box
> > > > enclosure.
> > > >
> > > > This adds a basic device tree and defconfig for it.
> > > >
> > > > It contrast to the other supported H6 boards the H6 Mini uses DDR3 DRAM
> > > > chips (not LPDDR3), which require a different DRAM controller setup.  
> > >
> > > Send the linux sync commit, rest seems to fine for me. will update the
> > > commit while applying.  
> >
> > Which sync commit? I haven't send a device tree for Linux yet, if that is  
> 
> sun50i-h6-eachlink-h6-mini.dts this was synced from Linux right? need
> head commit id of this dts.

As I was trying to say in the line above: There is no sun50i-h6-eachlink-h6-mini.dts in Linux (yet), for the said reasons.

Cheers,
Andre.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 7/7] sunxi: H6: Add basic Eachlink H6 Mini support
  2019-07-15 10:21         ` Andre Przywara
@ 2019-07-15 11:13           ` Jagan Teki
  0 siblings, 0 replies; 14+ messages in thread
From: Jagan Teki @ 2019-07-15 11:13 UTC (permalink / raw)
  To: u-boot

On Mon, Jul 15, 2019 at 3:51 PM Andre Przywara <andre.przywara@arm.com> wrote:
>
> On Mon, 15 Jul 2019 15:43:10 +0530
> Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> Hi,
>
> > On Mon, Jul 15, 2019 at 2:51 PM Andre Przywara <andre.przywara@arm.com> wrote:
> > >
> > > On Mon, 15 Jul 2019 12:41:34 +0530
> > > Jagan Teki <jagan@amarulasolutions.com> wrote:
> > >
> > > Hi Jagan!
> > >
> > > > On Mon, Jul 15, 2019 at 6:57 AM Andre Przywara <andre.przywara@arm.com> wrote:
> > > > >
> > > > > The Eachlink H6 Mini is a modestly priced TV box, using the Allwinner H6
> > > > > SoC. It comes with 3GB of DRAM and 32GB of eMMC in the typical TV box
> > > > > enclosure.
> > > > >
> > > > > This adds a basic device tree and defconfig for it.
> > > > >
> > > > > It contrast to the other supported H6 boards the H6 Mini uses DDR3 DRAM
> > > > > chips (not LPDDR3), which require a different DRAM controller setup.
> > > >
> > > > Send the linux sync commit, rest seems to fine for me. will update the
> > > > commit while applying.
> > >
> > > Which sync commit? I haven't send a device tree for Linux yet, if that is
> >
> > sun50i-h6-eachlink-h6-mini.dts this was synced from Linux right? need
> > head commit id of this dts.
>
> As I was trying to say in the line above: There is no sun50i-h6-eachlink-h6-mini.dts in Linux (yet), for the said reasons.

Ohh. Sorry for overlook. Will skip this patch for now.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support
  2019-07-15  1:27 [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Andre Przywara
                   ` (6 preceding siblings ...)
  2019-07-15  1:27 ` [U-Boot] [PATCH v3 7/7] sunxi: H6: Add basic Eachlink H6 Mini support Andre Przywara
@ 2019-07-15 11:14 ` Jagan Teki
  7 siblings, 0 replies; 14+ messages in thread
From: Jagan Teki @ 2019-07-15 11:14 UTC (permalink / raw)
  To: u-boot

On Mon, Jul 15, 2019 at 6:57 AM Andre Przywara <andre.przywara@arm.com> wrote:
>
> A tiny update, dropping "1333" from the LPDDR3 timings filename, because
> it actually isn't 1333, as Icenowy pointed out correctly. Also adding
> Jernej's review tags. For more details see the Changelog below.
> ----------------
>
> So far the SPL DRAM driver for the Allwinner H6 SoC only supports
> LPDDR3 DRAM chips, which are used on most single board computers with
> this SoC.
> There are some TV boxes with the H6 out now, but most of them are
> using DDR3 DRAM instead of LPDDR3.
>
> This series extends the existing H6 DRAM driver to cover DDR3 DRAMs
> as well. The information used in these patches is from:
> - register dumps after Allwinner's boot0 (libdram) has initialised
>   the DRAM
> - some disassembly of the libdram library
> - timing parameters as found in the boot0 binary
> - comparison with Xilinx ZynqMP DRAM controller documentation
>
> The box I played with (Eachlink H6 Mini) has 3GB of DDR3-1600 chips and
> runs at 840 MHz, however I couldn't get it to work with these parameters.
> Instead Jernej suggested to use a lower clock and adjust some timing
> parameters, which made it work for me as well.
>
> Many thanks to Jernej Skrabec for his help, also to others who helped
> with testing and experiments.
>
> The first two patches contain some fixes for the existing driver.
> Patch 3 moves the existing LPDDR3 timing parameters into a separate file,
> patch 5 introduces the respective DDR3 timings, patch 6 adds some
> generic delay lines values.
> Patch 4 enhances the DRAM controller driver to program DDR3 specific
> registers as well and use different settings on other registers.
> The final patch introduces support for the Eachlink H6 Mini TV box, with
> the usual device tree and defconfig file.
>
> Please have a look and comment!
>
> Cheers,
> Andre.
>
> Changelog v2..v3:
> - rebased against origin/master
> - drop 1333 from LPDDR3 timings filename
> - cosmetic change to comment
> - adding Jernej's Reviewed-by: and Tested-by: tags
> - updating defconfigs for two new boards
>
> Changelog v1..v2:
> - name DDR2T mode bit
> - explain bonding ID bit
> - generalise message about non-supported DRAM types
> - update comments about JEDEC values to match DDR3-1333 timings
> - use recommended max(ns, cycles) timing formulas where appropriate
> - add MAINTAINERS entry for the Eachlink H6 Mini box
>
> Andre Przywara (6):
>   sunxi: H6: DRAM: avoid memcpy() on MMIO registers
>   sunxi: H6: DRAM: follow recommended PHY init algorithm
>   sunxi: H6: move LPDDR3 timing definition into separate file
>   sunxi: H6: Add DDR3 support to DRAM controller driver
>   sunxi: H6: Add DDR3-1333 timings

Applied to u-boot-sunxi/master

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2019-07-15 11:14 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-15  1:27 [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Andre Przywara
2019-07-15  1:27 ` [U-Boot] [PATCH v3 1/7] sunxi: H6: DRAM: avoid memcpy() on MMIO registers Andre Przywara
2019-07-15  1:27 ` [U-Boot] [PATCH v3 2/7] sunxi: H6: DRAM: follow recommended PHY init algorithm Andre Przywara
2019-07-15  1:27 ` [U-Boot] [PATCH v3 3/7] sunxi: H6: move LPDDR3 timing definition into separate file Andre Przywara
2019-07-15  1:27 ` [U-Boot] [PATCH v3 4/7] sunxi: H6: Add DDR3 support to DRAM controller driver Andre Przywara
2019-07-15  1:27 ` [U-Boot] [PATCH v3 5/7] sunxi: H6: Add DDR3-1333 timings Andre Przywara
2019-07-15  1:27 ` [U-Boot] [PATCH v3 6/7] sunxi: H6: Add DDR3 DRAM delay values Andre Przywara
2019-07-15  1:27 ` [U-Boot] [PATCH v3 7/7] sunxi: H6: Add basic Eachlink H6 Mini support Andre Przywara
2019-07-15  7:11   ` Jagan Teki
2019-07-15  9:21     ` Andre Przywara
2019-07-15 10:13       ` Jagan Teki
2019-07-15 10:21         ` Andre Przywara
2019-07-15 11:13           ` Jagan Teki
2019-07-15 11:14 ` [U-Boot] [PATCH v3 0/7] sunxi: Add H6 DDR3 DRAM support Jagan Teki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.