All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/
@ 2014-12-16 20:31 Hans de Goede
  2014-12-16 20:31 ` [U-Boot] [PATCH 02/14] sunxi: Add support for the rsb (Reduced Serial Bus) Hans de Goede
                   ` (13 more replies)
  0 siblings, 14 replies; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

The p2wi interface is only available on sun6i, adjust the gpio pinmux defines
for it to reflect this.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/cpu/armv7/sunxi/p2wi.c        | 4 ++--
 arch/arm/include/asm/arch-sunxi/gpio.h | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/cpu/armv7/sunxi/p2wi.c b/arch/arm/cpu/armv7/sunxi/p2wi.c
index 48613bd..52c2c53 100644
--- a/arch/arm/cpu/armv7/sunxi/p2wi.c
+++ b/arch/arm/cpu/armv7/sunxi/p2wi.c
@@ -31,8 +31,8 @@ void p2wi_init(void)
 	/* Enable p2wi and PIO clk, and de-assert their resets */
 	prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_P2WI);
 
-	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUNXI_GPL0_R_P2WI_SCK);
-	sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUNXI_GPL1_R_P2WI_SDA);
+	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN6I_GPL0_R_P2WI_SCK);
+	sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN6I_GPL1_R_P2WI_SDA);
 
 	/* Reset p2wi controller and set clock to CLKIN(12)/8 = 1.5 MHz */
 	writel(P2WI_CTRL_RESET, &p2wi->ctrl);
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index 366c0dc..9f972ce 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -173,8 +173,8 @@ enum sunxi_gpio_number {
 
 #define SUN4I_GPI4_SDC3		2
 
-#define SUNXI_GPL0_R_P2WI_SCK	3
-#define SUNXI_GPL1_R_P2WI_SDA	3
+#define SUN6I_GPL0_R_P2WI_SCK	3
+#define SUN6I_GPL1_R_P2WI_SDA	3
 
 #define SUN8I_GPL2_R_UART_TX	2
 #define SUN8I_GPL3_R_UART_RX	2
-- 
2.1.0

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

* [U-Boot] [PATCH 02/14] sunxi: Add support for the rsb (Reduced Serial Bus)
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-17  2:22   ` Chen-Yu Tsai
  2014-12-16 20:31 ` [U-Boot] [PATCH 03/14] sunxi: axp221: Add axp223 support Hans de Goede
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

sun8i (A23) introduces a new bus for communicating with the pmic, the rsb,
the rsb is also used to communicate with the pmic on the A80, and is
documented in the A80 user manual.

This commit adds support for this based on the rsb driver from the allwinner
u-boot sources.

Note: Not yet ready for upstream, code needs some significant cleanups.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/cpu/armv7/sunxi/Makefile      |   1 +
 arch/arm/cpu/armv7/sunxi/rsb.c         | 158 +++++++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-sunxi/cpu.h  |   3 +-
 arch/arm/include/asm/arch-sunxi/gpio.h |   2 +
 arch/arm/include/asm/arch-sunxi/prcm.h |   3 +-
 arch/arm/include/asm/arch-sunxi/rsb.h  |  55 ++++++++++++
 6 files changed, 220 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/sunxi/rsb.c
 create mode 100644 arch/arm/include/asm/arch-sunxi/rsb.h

diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 1337b60..3e8975a 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -15,6 +15,7 @@ obj-y	+= pinmux.o
 obj-$(CONFIG_MACH_SUN6I)	+= prcm.o
 obj-$(CONFIG_MACH_SUN8I)	+= prcm.o
 obj-$(CONFIG_MACH_SUN6I)	+= p2wi.o
+obj-$(CONFIG_MACH_SUN8I)	+= rsb.o
 obj-$(CONFIG_MACH_SUN4I)	+= clock_sun4i.o
 obj-$(CONFIG_MACH_SUN5I)	+= clock_sun4i.o
 obj-$(CONFIG_MACH_SUN6I)	+= clock_sun6i.o
diff --git a/arch/arm/cpu/armv7/sunxi/rsb.c b/arch/arm/cpu/armv7/sunxi/rsb.c
new file mode 100644
index 0000000..b72bb9d
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/rsb.c
@@ -0,0 +1,158 @@
+/*
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on allwinner u-boot sources rsb code which is:
+ * (C) Copyright 2007-2013
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * lixiang <lixiang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/prcm.h>
+#include <asm/arch/rsb.h>
+
+static void rsb_cfg_io(void)
+{
+	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL0_R_RSB_SCK);
+	sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL1_R_RSB_SDA);
+	sunxi_gpio_set_pull(SUNXI_GPL(0), 1);
+	sunxi_gpio_set_pull(SUNXI_GPL(1), 1);
+	sunxi_gpio_set_drv(SUNXI_GPL(0), 2);
+	sunxi_gpio_set_drv(SUNXI_GPL(1), 2);
+}
+
+static void rsb_set_clk(void)
+{
+	struct sunxi_rsb_reg * const rsb =
+		(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+	u32 div = 0;
+	u32 cd_odly = 0;
+
+	/* Source is Hosc24M, set RSB clk to 3Mhz */
+	div = 24000000 / 3000000 / 2 - 1;
+	cd_odly = div >> 1;
+	if (!cd_odly)
+		cd_odly = 1;
+
+	writel((cd_odly << 8) | div, &rsb->ccr);
+}
+
+void rsb_init(void)
+{
+	struct sunxi_rsb_reg * const rsb =
+		(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+
+	rsb_cfg_io();
+
+	/* Enable RSB and PIO clk, and de-assert their resets */
+	prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB);
+
+	writel(RSB_CTRL_SOFT_RST, &rsb->ctrl);
+	rsb_set_clk();
+}
+
+static int rsb_await_trans(void)
+{
+	struct sunxi_rsb_reg * const rsb =
+		(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+	unsigned long tmo = timer_get_us() + 1000000;
+	u32 stat;
+	int ret;
+
+	while (1) {
+		stat = readl(&rsb->stat);
+		if (stat & RSB_STAT_LBSY_INT) {
+			ret = -EBUSY;
+			break;
+		}
+		if (stat & RSB_STAT_TERR_INT) {
+			ret = -EIO;
+			break;
+		}
+		if (stat & RSB_STAT_TOVER_INT) {
+			ret = 0;
+			break;
+		}
+		if (timer_get_us() > tmo) {
+			ret = -ETIME;
+			break;
+		}
+	}
+	writel(stat, &rsb->stat); /* Clear status bits */
+
+	return ret;
+}
+
+int rsb_set_device_mode(u32 device_mode_data)
+{
+	struct sunxi_rsb_reg * const rsb =
+		(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+	unsigned long tmo = timer_get_us() + 1000000;
+
+	writel(RSB_DMCR_DEVICE_MODE_START | device_mode_data, &rsb->dmcr);
+
+	while (readl(&rsb->dmcr) & RSB_DMCR_DEVICE_MODE_START) {
+		if (timer_get_us() > tmo)
+			return -ETIME;
+	}
+
+	return rsb_await_trans();
+}
+
+static int rsb_do_trans(void)
+{
+	struct sunxi_rsb_reg * const rsb =
+		(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+
+	setbits_le32(&rsb->ctrl, RSB_CTRL_START_TRANS);
+	return rsb_await_trans();
+}
+
+int rsb_set_device_address(u16 device_addr, u16 runtime_addr)
+{
+	struct sunxi_rsb_reg * const rsb =
+		(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+
+	writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr) |
+	       RSB_DEVADDR_DEVICE_ADDR(device_addr), &rsb->devaddr);
+	writel(RSB_CMD_SET_RTSADDR, &rsb->cmd);
+
+	return rsb_do_trans();
+}
+
+int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data)
+{
+	struct sunxi_rsb_reg * const rsb =
+		(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+
+	writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr);
+	writel(reg_addr, &rsb->addr);
+	writel(data, &rsb->data);
+	writel(RSB_CMD_BYTE_WRITE, &rsb->cmd);
+
+	return rsb_do_trans();
+}
+
+int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data)
+{
+	struct sunxi_rsb_reg * const rsb =
+		(struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
+	int ret;
+
+	writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr);
+	writel(reg_addr, &rsb->addr);
+	writel(RSB_CMD_BYTE_READ, &rsb->cmd);
+
+	ret = rsb_do_trans();
+	if (ret)
+		return ret;
+
+	*data = readl(&rsb->data) & 0xff;
+
+	return 0;
+}
diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
index 9500262..49c1614 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -128,7 +128,8 @@
 #define SUN6I_CPUCFG_BASE		0x01f01c00
 #define SUNXI_R_UART_BASE		0x01f02800
 #define SUNXI_R_PIO_BASE		0x01f02c00
-#define SUNXI_P2WI_BASE			0x01f03400
+#define SUNXI_P2WI_BASE			0x01f03400	/* on sun6i */
+#define SUNXI_RSB_BASE			0x01f03400	/* on sun8i */
 
 /* CoreSight Debug Module */
 #define SUNXI_CSDM_BASE			0x3f500000
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index 9f972ce..6623f15 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -176,6 +176,8 @@ enum sunxi_gpio_number {
 #define SUN6I_GPL0_R_P2WI_SCK	3
 #define SUN6I_GPL1_R_P2WI_SDA	3
 
+#define SUN8I_GPL0_R_RSB_SCK	2
+#define SUN8I_GPL1_R_RSB_SDA	2
 #define SUN8I_GPL2_R_UART_TX	2
 #define SUN8I_GPL3_R_UART_RX	2
 
diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
index 88de1ff..82ed541 100644
--- a/arch/arm/include/asm/arch-sunxi/prcm.h
+++ b/arch/arm/include/asm/arch-sunxi/prcm.h
@@ -50,7 +50,8 @@
 #define PRCM_APB0_GATE_PIO (0x1 << 0)
 #define PRCM_APB0_GATE_IR (0x1 << 1)
 #define PRCM_APB0_GATE_TIMER01 (0x1 << 2)
-#define PRCM_APB0_GATE_P2WI (0x1 << 3)
+#define PRCM_APB0_GATE_P2WI (0x1 << 3)		/* sun6i */
+#define PRCM_APB0_GATE_RSB (0x1 << 3)		/* sun8i */
 #define PRCM_APB0_GATE_UART (0x1 << 4)
 #define PRCM_APB0_GATE_1WIRE (0x1 << 5)
 #define PRCM_APB0_GATE_I2C (0x1 << 6)
diff --git a/arch/arm/include/asm/arch-sunxi/rsb.h b/arch/arm/include/asm/arch-sunxi/rsb.h
new file mode 100644
index 0000000..95a595a
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/rsb.h
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on allwinner u-boot sources rsb code which is:
+ * (C) Copyright 2007-2013
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * lixiang <lixiang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __SUNXI_RSB_H
+#define __SUNXI_RSB_H
+
+#include <common.h>
+#include <asm/io.h>
+
+struct sunxi_rsb_reg {
+	u32 ctrl;	/* 0x00 */
+	u32 ccr;	/* 0x04 */
+	u32 inte;	/* 0x08 */
+	u32 stat;	/* 0x0c */
+	u32 addr;	/* 0x10 */
+	u8 res0[8];	/* 0x14 */
+	u32 data;	/* 0x1c */
+	u8 res1[4];	/* 0x20 */
+	u32 lcr;	/* 0x24 */
+	u32 dmcr;	/* 0x28 */
+	u32 cmd;	/* 0x2c */
+	u32 devaddr;	/* 0x30 */
+};
+
+#define RSB_CTRL_SOFT_RST		(1 << 0)
+#define RSB_CTRL_START_TRANS		(1 << 7)
+
+#define RSB_STAT_TOVER_INT		(1 << 0)
+#define RSB_STAT_TERR_INT		(1 << 1)
+#define RSB_STAT_LBSY_INT		(1 << 2)
+
+#define RSB_DMCR_DEVICE_MODE_START	(1 << 31)
+
+#define RSB_CMD_BYTE_WRITE		0x4e
+#define RSB_CMD_BYTE_READ		0x8b
+#define RSB_CMD_SET_RTSADDR		0xe8
+
+#define RSB_DEVADDR_RUNTIME_ADDR(x)	((x) << 16)
+#define RSB_DEVADDR_DEVICE_ADDR(x)	((x) << 0)
+
+void rsb_init(void);
+int rsb_set_device_mode(u32 device_mode_data);
+int rsb_set_device_address(u16 device_addr, u16 runtime_addr);
+int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data);
+int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data);
+
+#endif
-- 
2.1.0

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

* [U-Boot] [PATCH 03/14] sunxi: axp221: Add axp223 support
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
  2014-12-16 20:31 ` [U-Boot] [PATCH 02/14] sunxi: Add support for the rsb (Reduced Serial Bus) Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-17  2:34   ` Chen-Yu Tsai
  2014-12-18 19:00   ` Ian Campbell
  2014-12-16 20:31 ` [U-Boot] [PATCH 04/14] sunxi: axp221: Add Kconfig help and sane defaults for typical ldo usage Hans de Goede
                   ` (11 subsequent siblings)
  13 siblings, 2 replies; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

The axp223 appears to be the same as the axp221, except that it uses the
rsb to communicate rather then the p2wi. At least all the registers we use
are 100% the same.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/cpu/armv7/sunxi/cpu_info.c |  2 +-
 drivers/power/Kconfig               |  8 ++--
 drivers/power/axp221.c              | 88 ++++++++++++++++++++++++++++---------
 include/axp221.h                    |  4 ++
 4 files changed, 76 insertions(+), 26 deletions(-)

diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c
index 7a3a4ca..b6cb9de 100644
--- a/arch/arm/cpu/armv7/sunxi/cpu_info.c
+++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c
@@ -76,7 +76,7 @@ int print_cpuinfo(void)
 
 int sunxi_get_sid(unsigned int *sid)
 {
-#ifdef CONFIG_MACH_SUN6I
+#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
 #ifdef CONFIG_AXP221_POWER
 	return axp221_get_sid(sid);
 #else
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 1ec7c0e..7373a79 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -1,10 +1,10 @@
 config AXP221_POWER
-	boolean "axp221 pmic support"
-	depends on MACH_SUN6I
+	boolean "axp221 / axp223 pmic support"
+	depends on MACH_SUN6I || MACH_SUN8I
 	default y
 	---help---
-	Say y here to enable support for the axp221 pmic found on most sun6i
-	(A31) boards.
+	Say y here to enable support for the axp221 / axp223 pmic found on most
+	sun6i (A31) / sun8i (A23) boards.
 
 config AXP221_DLDO1_VOLT
 	int "axp221 dldo1 voltage"
diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c
index 826567a..717adad 100644
--- a/drivers/power/axp221.c
+++ b/drivers/power/axp221.c
@@ -1,4 +1,10 @@
 /*
+ * AXP221 and AXP223 driver
+ *
+ * IMPORTANT when making changes to this file check that the registers
+ * used are the same for the axp221 and axp223.
+ * 
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
  * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
  *
  * SPDX-License-Identifier:	GPL-2.0+
@@ -7,8 +13,50 @@
 #include <common.h>
 #include <errno.h>
 #include <asm/arch/p2wi.h>
+#include <asm/arch/rsb.h>
 #include <axp221.h>
 
+/*
+ * The axp221 uses the p2wi bus, the axp223 is identical (for all registers
+ * used sofar) but uses the rsb bus. These functions abstract this.
+ */
+static int pmic_bus_init(void)
+{
+#ifdef CONFIG_MACH_SUN6I
+	p2wi_init();
+	return p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
+					AXP221_INIT_DATA);
+#else
+	int ret;
+
+	rsb_init();
+	
+	ret = rsb_set_device_mode(AXP223_DEVICE_MODE_DATA);
+	if (ret)
+		return ret;
+
+	return rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
+#endif
+}
+
+static int pmic_bus_read(const u8 addr, u8 *data)
+{
+#ifdef CONFIG_MACH_SUN6I
+	return p2wi_read(addr, data);
+#else
+	return rsb_read(AXP223_RUNTIME_ADDR, addr, data);
+#endif
+}
+
+static int pmic_bus_write(const u8 addr, u8 data)
+{
+#ifdef CONFIG_MACH_SUN6I
+	return p2wi_write(addr, data);
+#else
+	return rsb_write(AXP223_RUNTIME_ADDR, addr, data);
+#endif
+}
+
 static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div)
 {
 	if (mvolt < min)
@@ -24,12 +72,12 @@ static int axp221_setbits(u8 reg, u8 bits)
 	int ret;
 	u8 val;
 
-	ret = p2wi_read(reg, &val);
+	ret = pmic_bus_read(reg, &val);
 	if (ret)
 		return ret;
 
 	val |= bits;
-	return p2wi_write(reg, val);
+	return pmic_bus_write(reg, val);
 }
 
 int axp221_set_dcdc1(unsigned int mvolt)
@@ -37,7 +85,7 @@ int axp221_set_dcdc1(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
 
-	ret = p2wi_write(AXP221_DCDC1_CTRL, cfg);
+	ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
 	if (ret)
 		return ret;
 
@@ -49,28 +97,28 @@ int axp221_set_dcdc2(unsigned int mvolt)
 {
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
 
-	return p2wi_write(AXP221_DCDC2_CTRL, cfg);
+	return pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
 }
 
 int axp221_set_dcdc3(unsigned int mvolt)
 {
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
 
-	return p2wi_write(AXP221_DCDC3_CTRL, cfg);
+	return pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
 }
 
 int axp221_set_dcdc4(unsigned int mvolt)
 {
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
 
-	return p2wi_write(AXP221_DCDC4_CTRL, cfg);
+	return pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
 }
 
 int axp221_set_dcdc5(unsigned int mvolt)
 {
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
 
-	return p2wi_write(AXP221_DCDC5_CTRL, cfg);
+	return pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
 }
 
 int axp221_set_dldo1(unsigned int mvolt)
@@ -78,7 +126,7 @@ int axp221_set_dldo1(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
-	ret = p2wi_write(AXP221_DLDO1_CTRL, cfg);
+	ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg);
 	if (ret)
 		return ret;
 
@@ -91,7 +139,7 @@ int axp221_set_dldo2(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
-	ret = p2wi_write(AXP221_DLDO2_CTRL, cfg);
+	ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg);
 	if (ret)
 		return ret;
 
@@ -104,7 +152,7 @@ int axp221_set_dldo3(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
-	ret = p2wi_write(AXP221_DLDO3_CTRL, cfg);
+	ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg);
 	if (ret)
 		return ret;
 
@@ -117,7 +165,7 @@ int axp221_set_dldo4(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
-	ret = p2wi_write(AXP221_DLDO4_CTRL, cfg);
+	ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg);
 	if (ret)
 		return ret;
 
@@ -130,7 +178,7 @@ int axp221_set_aldo1(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
-	ret = p2wi_write(AXP221_ALDO1_CTRL, cfg);
+	ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
 	if (ret)
 		return ret;
 
@@ -143,7 +191,7 @@ int axp221_set_aldo2(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
-	ret = p2wi_write(AXP221_ALDO2_CTRL, cfg);
+	ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
 	if (ret)
 		return ret;
 
@@ -156,7 +204,7 @@ int axp221_set_aldo3(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
-	ret = p2wi_write(AXP221_ALDO3_CTRL, cfg);
+	ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
 	if (ret)
 		return ret;
 
@@ -169,13 +217,11 @@ int axp221_init(void)
 	u8 axp_chip_id;
 	int ret;
 
-	p2wi_init();
-	ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
-				       AXP221_INIT_DATA);
+	ret = pmic_bus_init();
 	if (ret)
 		return ret;
 
-	ret = p2wi_read(AXP221_CHIP_ID, &axp_chip_id);
+	ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id);
 	if (ret)
 		return ret;
 
@@ -194,17 +240,17 @@ int axp221_get_sid(unsigned int *sid)
 	if (ret)
 		return ret;
 
-	ret = p2wi_write(AXP221_PAGE, 1);
+	ret = pmic_bus_write(AXP221_PAGE, 1);
 	if (ret)
 		return ret;
 
 	for (i = 0; i < 16; i++) {
-		ret = p2wi_read(AXP221_SID + i, &dest[i]);
+		ret = pmic_bus_read(AXP221_SID + i, &dest[i]);
 		if (ret)
 			return ret;
 	}
 
-	p2wi_write(AXP221_PAGE, 0);
+	pmic_bus_write(AXP221_PAGE, 0);
 
 	for (i = 0; i < 4; i++)
 		sid[i] = be32_to_cpu(sid[i]);
diff --git a/include/axp221.h b/include/axp221.h
index db219c6..10d35e1 100644
--- a/include/axp221.h
+++ b/include/axp221.h
@@ -10,6 +10,10 @@
 #define AXP221_CTRL_ADDR 0x3e
 #define AXP221_INIT_DATA 0x3e
 
+#define AXP223_DEVICE_ADDR 0x3a3
+#define AXP223_RUNTIME_ADDR 0x2d
+#define AXP223_DEVICE_MODE_DATA 0x7c3e00
+
 /* Page 0 addresses */
 #define AXP221_CHIP_ID		0x03
 #define AXP221_OUTPUT_CTRL1	0x10
-- 
2.1.0

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

* [U-Boot] [PATCH 04/14] sunxi: axp221: Add Kconfig help and sane defaults for typical ldo usage
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
  2014-12-16 20:31 ` [U-Boot] [PATCH 02/14] sunxi: Add support for the rsb (Reduced Serial Bus) Hans de Goede
  2014-12-16 20:31 ` [U-Boot] [PATCH 03/14] sunxi: axp221: Add axp223 support Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-18 19:02   ` Ian Campbell
  2014-12-16 20:31 ` [U-Boot] [PATCH 05/14] sunxi: axp221: Make dcdc1 voltage configurable Hans de Goede
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

Some of the ldo-s of the axp221 are used in the same way on most boards, add
comments to the Kconfig help text to reflect this, and give them defaults
matching their typical usage.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 configs/CSQ_CS908_defconfig       |  3 ---
 configs/Colombus_defconfig        |  3 ---
 configs/Hummingbird_A31_defconfig |  4 ----
 configs/Mele_M9_defconfig         |  3 ---
 drivers/power/Kconfig             | 20 ++++++++++++++------
 5 files changed, 14 insertions(+), 19 deletions(-)

diff --git a/configs/CSQ_CS908_defconfig b/configs/CSQ_CS908_defconfig
index 4c9cff6..1b6cdbf 100644
--- a/configs/CSQ_CS908_defconfig
+++ b/configs/CSQ_CS908_defconfig
@@ -11,9 +11,6 @@ CONFIG_FDTFILE="sun6i-a31s-cs908.dtb"
 +S:CONFIG_AXP221_DLDO1_VOLT=3300
 # Wifi power
 +S:CONFIG_AXP221_ALDO1_VOLT=3300
-# HDMI power ?
-+S:CONFIG_AXP221_ALDO2_VOLT=1800
-+S:CONFIG_AXP221_ALDO3_VOLT=3000
 # No Vbus gpio for either usb
 +S:CONFIG_USB1_VBUS_PIN=""
 +S:CONFIG_USB2_VBUS_PIN=""
diff --git a/configs/Colombus_defconfig b/configs/Colombus_defconfig
index b8c5400..f42ae52 100644
--- a/configs/Colombus_defconfig
+++ b/configs/Colombus_defconfig
@@ -9,8 +9,5 @@ CONFIG_FDTFILE="sun6i-a31-colombus.dtb"
 +S:CONFIG_DRAM_ZQ=251
 # Wifi power
 +S:CONFIG_AXP221_ALDO1_VOLT=3300
-# HDMI power ?
-+S:CONFIG_AXP221_ALDO2_VOLT=1800
-+S:CONFIG_AXP221_ALDO3_VOLT=3000
 # No Vbus gpio for usb1
 +S:CONFIG_USB1_VBUS_PIN=""
diff --git a/configs/Hummingbird_A31_defconfig b/configs/Hummingbird_A31_defconfig
index 73855c5..7f59a0d 100644
--- a/configs/Hummingbird_A31_defconfig
+++ b/configs/Hummingbird_A31_defconfig
@@ -9,10 +9,6 @@ CONFIG_FDTFILE="sun6i-a31-hummingbird.dtb"
 +S:CONFIG_DRAM_ZQ=251
 # Wifi power
 +S:CONFIG_AXP221_ALDO1_VOLT=3300
-# PM-CPUS GPIO power
-+S:CONFIG_AXP221_ALDO2_VOLT=1800
-# SoC IR, PLL and Analog power (must be 3.0V)
-+S:CONFIG_AXP221_ALDO3_VOLT=3000
 # Vbus gpio for usb1
 +S:CONFIG_USB1_VBUS_PIN="PH24"
 # No Vbus gpio for usb2
diff --git a/configs/Mele_M9_defconfig b/configs/Mele_M9_defconfig
index a598254..445cc57 100644
--- a/configs/Mele_M9_defconfig
+++ b/configs/Mele_M9_defconfig
@@ -13,9 +13,6 @@ CONFIG_FDTFILE="sun6i-a31-m9.dtb"
 +S:CONFIG_AXP221_DLDO4_VOLT=3300
 # Wifi power
 +S:CONFIG_AXP221_ALDO1_VOLT=3300
-# HDMI power ?
-+S:CONFIG_AXP221_ALDO2_VOLT=1800
-+S:CONFIG_AXP221_ALDO3_VOLT=3000
 # Vbus gpio for usb1
 +S:CONFIG_USB1_VBUS_PIN="PC27"
 # No Vbus gpio for usb2
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 7373a79..af66887 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -12,7 +12,9 @@ config AXP221_DLDO1_VOLT
 	default -1
 	---help---
 	Set the voltage (mV) to program the axp221 dldo1 at, set to -1 to
-	disable dldo1.
+	disable dldo1. On sun6i (A31) boards with ethernet this is often used
+	to power the ethernet phy. On sun8i (A23) boards this is often used to
+	power the wifi.
 
 config AXP221_DLDO4_VOLT
 	int "axp221 dldo4 voltage"
@@ -28,20 +30,26 @@ config AXP221_ALDO1_VOLT
 	default -1
 	---help---
 	Set the voltage (mV) to program the axp221 aldo1 at, set to -1 to
-	disable aldo1.
+	disable aldo1. On sun6i (A31) boards which have a wifi module this is
+	often used to power the wifi module.
 
 config AXP221_ALDO2_VOLT
 	int "axp221 aldo2 voltage"
 	depends on AXP221_POWER
-	default -1
+	default 1800 if MACH_SUN6I
+	default 2500 if MACH_SUN8I
 	---help---
 	Set the voltage (mV) to program the axp221 aldo2 at, set to -1 to
-	disable aldo2.
+	disable aldo2. On sun6i (A31) boards this is typically connected to
+	VCC-PM, which powers the port M gpios, and should be set to 1.8V.
+	On sun8i (A23) this is typically connected to VDD-DLL and must be
+	set to 2.5V.
 
 config AXP221_ALDO3_VOLT
 	int "axp221 aldo3 voltage"
 	depends on AXP221_POWER
-	default -1
+	default 3000
 	---help---
 	Set the voltage (mV) to program the axp221 aldo3 at, set to -1 to
-	disable aldo3.
+	disable aldo3. This is typically connected to VCC-PLL and AVCC and
+	must be set to 3V.
-- 
2.1.0

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

* [U-Boot] [PATCH 05/14] sunxi: axp221: Make dcdc1 voltage configurable
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
                   ` (2 preceding siblings ...)
  2014-12-16 20:31 ` [U-Boot] [PATCH 04/14] sunxi: axp221: Add Kconfig help and sane defaults for typical ldo usage Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-18 19:03   ` Ian Campbell
  2014-12-16 20:31 ` [U-Boot] [PATCH 06/14] sunxi: axp221: Explicitly turn off unused voltages Hans de Goede
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

The dcdc1 voltage is typically used as generic 3.3V IO voltage for things like
GPIO-s, sdcard interfaces, etc. On most boards this is undervolted to 3.0V to
safe battery, but not on all, make it configurable so that we can use the
same settings as the original firmware on all boards.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 board/sunxi/board.c       |  2 +-
 configs/Mele_M9_defconfig |  2 ++
 drivers/power/Kconfig     | 10 ++++++++++
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index b5dfe95..e2ebf83 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -175,7 +175,7 @@ void sunxi_board_init(void)
 #endif
 #ifdef CONFIG_AXP221_POWER
 	power_failed = axp221_init();
-	power_failed |= axp221_set_dcdc1(3000);
+	power_failed |= axp221_set_dcdc1(CONFIG_AXP221_DCDC1_VOLT);
 	power_failed |= axp221_set_dcdc2(1200);
 	power_failed |= axp221_set_dcdc3(1200);
 	power_failed |= axp221_set_dcdc4(1200);
diff --git a/configs/Mele_M9_defconfig b/configs/Mele_M9_defconfig
index 445cc57..e5ab0ec 100644
--- a/configs/Mele_M9_defconfig
+++ b/configs/Mele_M9_defconfig
@@ -7,6 +7,8 @@ CONFIG_FDTFILE="sun6i-a31-m9.dtb"
 +S:CONFIG_TARGET_MELE_M9=y
 +S:CONFIG_DRAM_CLK=312
 +S:CONFIG_DRAM_ZQ=120
+# The Mele M9 uses 3.3V for general IO
++S:CONFIG_AXP221_DCDC1_VOLT=3300
 # Ethernet phy power
 +S:CONFIG_AXP221_DLDO1_VOLT=3300
 # USB hub power
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index af66887..e132759 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -6,6 +6,16 @@ config AXP221_POWER
 	Say y here to enable support for the axp221 / axp223 pmic found on most
 	sun6i (A31) / sun8i (A23) boards.
 
+config AXP221_DCDC1_VOLT
+	int "axp221 dcdc1 voltage"
+	depends on AXP221_POWER
+	default 3000
+	---help---
+	Set the voltage (mV) to program the axp221 dcdc1 at, set to 0 to
+	disable dcdc1. This is typically used as generic 3.3V IO voltage for
+	things like GPIO-s, sdcard interfaces, etc. On most boards this is
+	undervolted to 3.0V to safe battery.
+
 config AXP221_DLDO1_VOLT
 	int "axp221 dldo1 voltage"
 	depends on AXP221_POWER
-- 
2.1.0

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

* [U-Boot] [PATCH 06/14] sunxi: axp221: Explicitly turn off unused voltages
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
                   ` (3 preceding siblings ...)
  2014-12-16 20:31 ` [U-Boot] [PATCH 05/14] sunxi: axp221: Make dcdc1 voltage configurable Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-18 19:04   ` Ian Campbell
  2014-12-16 20:31 ` [U-Boot] [PATCH 07/14] sunxi: axp221: Disable dcdc4 on sun8i (A23) Hans de Goede
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

Explicitly turn off unused voltages, rather then leaving them as is. Likewise
explictly enabled the dcdc convertors, rather then assuming they are already
enabled at boot.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 board/sunxi/board.c    |  10 -----
 drivers/power/Kconfig  |  16 ++++----
 drivers/power/axp221.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++---
 include/axp221.h       |   8 +++-
 4 files changed, 111 insertions(+), 25 deletions(-)

diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index e2ebf83..5bf19b7 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -180,22 +180,12 @@ void sunxi_board_init(void)
 	power_failed |= axp221_set_dcdc3(1200);
 	power_failed |= axp221_set_dcdc4(1200);
 	power_failed |= axp221_set_dcdc5(1500);
-#if CONFIG_AXP221_DLDO1_VOLT != -1
 	power_failed |= axp221_set_dldo1(CONFIG_AXP221_DLDO1_VOLT);
-#endif
-#if CONFIG_AXP221_DLDO4_VOLT != -1
 	power_failed |= axp221_set_dldo4(CONFIG_AXP221_DLDO4_VOLT);
-#endif
-#if CONFIG_AXP221_ALDO1_VOLT != -1
 	power_failed |= axp221_set_aldo1(CONFIG_AXP221_ALDO1_VOLT);
-#endif
-#if CONFIG_AXP221_ALDO2_VOLT != -1
 	power_failed |= axp221_set_aldo2(CONFIG_AXP221_ALDO2_VOLT);
-#endif
-#if CONFIG_AXP221_ALDO3_VOLT != -1
 	power_failed |= axp221_set_aldo3(CONFIG_AXP221_ALDO3_VOLT);
 #endif
-#endif
 
 	printf("DRAM:");
 	ramsize = sunxi_dram_init();
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index e132759..ef0c093 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -19,9 +19,9 @@ config AXP221_DCDC1_VOLT
 config AXP221_DLDO1_VOLT
 	int "axp221 dldo1 voltage"
 	depends on AXP221_POWER
-	default -1
+	default 0
 	---help---
-	Set the voltage (mV) to program the axp221 dldo1 at, set to -1 to
+	Set the voltage (mV) to program the axp221 dldo1 at, set to 0 to
 	disable dldo1. On sun6i (A31) boards with ethernet this is often used
 	to power the ethernet phy. On sun8i (A23) boards this is often used to
 	power the wifi.
@@ -29,17 +29,17 @@ config AXP221_DLDO1_VOLT
 config AXP221_DLDO4_VOLT
 	int "axp221 dldo4 voltage"
 	depends on AXP221_POWER
-	default -1
+	default 0
 	---help---
-	Set the voltage (mV) to program the axp221 dldo4 at, set to -1 to
+	Set the voltage (mV) to program the axp221 dldo4 at, set to 0 to
 	disable dldo4.
 
 config AXP221_ALDO1_VOLT
 	int "axp221 aldo1 voltage"
 	depends on AXP221_POWER
-	default -1
+	default 0
 	---help---
-	Set the voltage (mV) to program the axp221 aldo1 at, set to -1 to
+	Set the voltage (mV) to program the axp221 aldo1 at, set to 0 to
 	disable aldo1. On sun6i (A31) boards which have a wifi module this is
 	often used to power the wifi module.
 
@@ -49,7 +49,7 @@ config AXP221_ALDO2_VOLT
 	default 1800 if MACH_SUN6I
 	default 2500 if MACH_SUN8I
 	---help---
-	Set the voltage (mV) to program the axp221 aldo2 at, set to -1 to
+	Set the voltage (mV) to program the axp221 aldo2 at, set to 0 to
 	disable aldo2. On sun6i (A31) boards this is typically connected to
 	VCC-PM, which powers the port M gpios, and should be set to 1.8V.
 	On sun8i (A23) this is typically connected to VDD-DLL and must be
@@ -60,6 +60,6 @@ config AXP221_ALDO3_VOLT
 	depends on AXP221_POWER
 	default 3000
 	---help---
-	Set the voltage (mV) to program the axp221 aldo3 at, set to -1 to
+	Set the voltage (mV) to program the axp221 aldo3 at, set to 0 to
 	disable aldo3. This is typically connected to VCC-PLL and AVCC and
 	must be set to 3V.
diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c
index 717adad..c438849 100644
--- a/drivers/power/axp221.c
+++ b/drivers/power/axp221.c
@@ -80,45 +80,107 @@ static int axp221_setbits(u8 reg, u8 bits)
 	return pmic_bus_write(reg, val);
 }
 
+static int axp221_clrbits(u8 reg, u8 bits)
+{
+	int ret;
+	u8 val;
+
+	ret = pmic_bus_read(reg, &val);
+	if (ret)
+		return ret;
+
+	val &= ~bits;
+	return pmic_bus_write(reg, val);
+}
+
 int axp221_set_dcdc1(unsigned int mvolt)
 {
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
 
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
+				      AXP221_OUTPUT_CTRL1_DCDC1_EN);
+
 	ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
 	if (ret)
 		return ret;
 
-	return axp221_setbits(AXP221_OUTPUT_CTRL2,
-			      AXP221_OUTPUT_CTRL2_DCDC1_EN);
+	ret = axp221_setbits(AXP221_OUTPUT_CTRL2,
+			     AXP221_OUTPUT_CTRL2_DCDC1SW_EN);
+	if (ret)
+		return ret;
+
+	return axp221_setbits(AXP221_OUTPUT_CTRL1,
+			      AXP221_OUTPUT_CTRL1_DCDC1_EN);
 }
 
 int axp221_set_dcdc2(unsigned int mvolt)
 {
+	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
 
-	return pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
+				      AXP221_OUTPUT_CTRL1_DCDC2_EN);
+
+	ret = pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
+	if (ret)
+		return ret;
+
+	return axp221_setbits(AXP221_OUTPUT_CTRL1,
+			      AXP221_OUTPUT_CTRL1_DCDC2_EN);
 }
 
 int axp221_set_dcdc3(unsigned int mvolt)
 {
+	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
 
-	return pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
+				      AXP221_OUTPUT_CTRL1_DCDC3_EN);
+
+	ret = pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
+	if (ret)
+		return ret;
+
+	return axp221_setbits(AXP221_OUTPUT_CTRL1,
+			      AXP221_OUTPUT_CTRL1_DCDC3_EN);
 }
 
 int axp221_set_dcdc4(unsigned int mvolt)
 {
+	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
 
-	return pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
+				      AXP221_OUTPUT_CTRL1_DCDC4_EN);
+
+	ret = pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
+	if (ret)
+		return ret;
+
+	return axp221_setbits(AXP221_OUTPUT_CTRL1,
+			      AXP221_OUTPUT_CTRL1_DCDC4_EN);
 }
 
 int axp221_set_dcdc5(unsigned int mvolt)
 {
+	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
 
-	return pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
+				      AXP221_OUTPUT_CTRL1_DCDC5_EN);
+
+	ret = pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
+	if (ret)
+		return ret;
+
+	return axp221_setbits(AXP221_OUTPUT_CTRL1,
+			      AXP221_OUTPUT_CTRL1_DCDC5_EN);
 }
 
 int axp221_set_dldo1(unsigned int mvolt)
@@ -126,6 +188,10 @@ int axp221_set_dldo1(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
+				      AXP221_OUTPUT_CTRL2_DLDO1_EN);
+
 	ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg);
 	if (ret)
 		return ret;
@@ -139,6 +205,10 @@ int axp221_set_dldo2(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
+				      AXP221_OUTPUT_CTRL2_DLDO2_EN);
+
 	ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg);
 	if (ret)
 		return ret;
@@ -152,6 +222,10 @@ int axp221_set_dldo3(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
+				      AXP221_OUTPUT_CTRL2_DLDO3_EN);
+
 	ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg);
 	if (ret)
 		return ret;
@@ -165,6 +239,10 @@ int axp221_set_dldo4(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL2,
+				      AXP221_OUTPUT_CTRL2_DLDO4_EN);
+
 	ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg);
 	if (ret)
 		return ret;
@@ -178,6 +256,10 @@ int axp221_set_aldo1(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
+				      AXP221_OUTPUT_CTRL1_ALDO1_EN);
+
 	ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
 	if (ret)
 		return ret;
@@ -191,6 +273,10 @@ int axp221_set_aldo2(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL1,
+				      AXP221_OUTPUT_CTRL1_ALDO2_EN);
+
 	ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
 	if (ret)
 		return ret;
@@ -204,6 +290,10 @@ int axp221_set_aldo3(unsigned int mvolt)
 	int ret;
 	u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
 
+	if (mvolt == 0)
+		return axp221_clrbits(AXP221_OUTPUT_CTRL3,
+				      AXP221_OUTPUT_CTRL3_ALDO3_EN);
+
 	ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
 	if (ret)
 		return ret;
diff --git a/include/axp221.h b/include/axp221.h
index 10d35e1..a6e52e3 100644
--- a/include/axp221.h
+++ b/include/axp221.h
@@ -17,6 +17,12 @@
 /* Page 0 addresses */
 #define AXP221_CHIP_ID		0x03
 #define AXP221_OUTPUT_CTRL1	0x10
+#define AXP221_OUTPUT_CTRL1_DCDC0_EN	(1 << 0)
+#define AXP221_OUTPUT_CTRL1_DCDC1_EN	(1 << 1)
+#define AXP221_OUTPUT_CTRL1_DCDC2_EN	(1 << 2)
+#define AXP221_OUTPUT_CTRL1_DCDC3_EN	(1 << 3)
+#define AXP221_OUTPUT_CTRL1_DCDC4_EN	(1 << 4)
+#define AXP221_OUTPUT_CTRL1_DCDC5_EN	(1 << 5)
 #define AXP221_OUTPUT_CTRL1_ALDO1_EN	(1 << 6)
 #define AXP221_OUTPUT_CTRL1_ALDO2_EN	(1 << 7)
 #define AXP221_OUTPUT_CTRL2	0x12
@@ -24,7 +30,7 @@
 #define AXP221_OUTPUT_CTRL2_DLDO2_EN	(1 << 4)
 #define AXP221_OUTPUT_CTRL2_DLDO3_EN	(1 << 5)
 #define AXP221_OUTPUT_CTRL2_DLDO4_EN	(1 << 6)
-#define AXP221_OUTPUT_CTRL2_DCDC1_EN	(1 << 7)
+#define AXP221_OUTPUT_CTRL2_DCDC1SW_EN	(1 << 7)
 #define AXP221_OUTPUT_CTRL3	0x13
 #define AXP221_OUTPUT_CTRL3_ALDO3_EN	(1 << 7)
 #define AXP221_DLDO1_CTRL	0x15
-- 
2.1.0

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

* [U-Boot] [PATCH 07/14] sunxi: axp221: Disable dcdc4 on sun8i (A23)
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
                   ` (4 preceding siblings ...)
  2014-12-16 20:31 ` [U-Boot] [PATCH 06/14] sunxi: axp221: Explicitly turn off unused voltages Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-18 19:05   ` Ian Campbell
  2014-12-16 20:31 ` [U-Boot] [PATCH 08/14] sun6i: Add a sigma_delta_enable paramter to clock_set_pll5() Hans de Goede
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

dcdc4 is not used on sun8i, disable it.

While at it also add comments to the other fixed voltages to document what
they are used for.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 board/sunxi/board.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 5bf19b7..7d6d075 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -176,10 +176,14 @@ void sunxi_board_init(void)
 #ifdef CONFIG_AXP221_POWER
 	power_failed = axp221_init();
 	power_failed |= axp221_set_dcdc1(CONFIG_AXP221_DCDC1_VOLT);
-	power_failed |= axp221_set_dcdc2(1200);
-	power_failed |= axp221_set_dcdc3(1200);
-	power_failed |= axp221_set_dcdc4(1200);
-	power_failed |= axp221_set_dcdc5(1500);
+	power_failed |= axp221_set_dcdc2(1200); /* A31:VDD-GPU, A23:VDD-SYS */
+	power_failed |= axp221_set_dcdc3(1200); /* VDD-CPU */
+#ifdef CONFIG_MACH_SUN6I
+	power_failed |= axp221_set_dcdc4(1200); /* A31:VDD-SYS */
+#else
+	power_failed |= axp221_set_dcdc4(0);    /* A23:unused */
+#endif
+	power_failed |= axp221_set_dcdc5(1500); /* VCC-DRAM */
 	power_failed |= axp221_set_dldo1(CONFIG_AXP221_DLDO1_VOLT);
 	power_failed |= axp221_set_dldo4(CONFIG_AXP221_DLDO4_VOLT);
 	power_failed |= axp221_set_aldo1(CONFIG_AXP221_ALDO1_VOLT);
-- 
2.1.0

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

* [U-Boot] [PATCH 08/14] sun6i: Add a sigma_delta_enable paramter to clock_set_pll5()
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
                   ` (5 preceding siblings ...)
  2014-12-16 20:31 ` [U-Boot] [PATCH 07/14] sunxi: axp221: Disable dcdc4 on sun8i (A23) Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-18 19:07   ` Ian Campbell
  2014-12-19 10:02   ` Siarhei Siamashka
  2014-12-16 20:31 ` [U-Boot] [PATCH 09/14] sun6i: Add k and m parameters " Hans de Goede
                   ` (6 subsequent siblings)
  13 siblings, 2 replies; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

The sun8i dram code sometimes wants to enable sigma delta mode,
add a parameter to allow this.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/cpu/armv7/sunxi/clock_sun6i.c        | 9 +++++++--
 arch/arm/cpu/armv7/sunxi/dram_sun6i.c         | 2 +-
 arch/arm/include/asm/arch-sunxi/clock.h       | 1 -
 arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 5 +++++
 4 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
index 8e949c6..193e314 100644
--- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
@@ -144,15 +144,20 @@ void clock_set_pll3(unsigned int clk)
 	       &ccm->pll3_cfg);
 }
 
-void clock_set_pll5(unsigned int clk)
+void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
 {
 	struct sunxi_ccm_reg * const ccm =
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	const int k = 2;
 	const int m = 1;
 
+	if (sigma_delta_enable)
+		writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg);
+
 	/* PLL5 rate = 24000000 * n * k / m */
-	writel(CCM_PLL5_CTRL_EN | CCM_PLL5_CTRL_UPD |
+	writel(CCM_PLL5_CTRL_EN |
+	       (sigma_delta_enable ? CCM_PLL5_CTRL_SIGMA_DELTA_EN : 0) |
+	       CCM_PLL5_CTRL_UPD |
 	       CCM_PLL5_CTRL_N(clk / (24000000 * k / m)) |
 	       CCM_PLL5_CTRL_K(k) | CCM_PLL5_CTRL_M(m), &ccm->pll5_cfg);
 
diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
index 61bb8d4..bc6428a 100644
--- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
@@ -46,7 +46,7 @@ static void mctl_sys_init(void)
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	const int dram_clk_div = 2;
 
-	clock_set_pll5(DRAM_CLK * dram_clk_div);
+	clock_set_pll5(DRAM_CLK * dram_clk_div, false);
 
 	clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV0_MASK,
 		CCM_DRAMCLK_CFG_DIV0(dram_clk_div) | CCM_DRAMCLK_CFG_RST |
diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
index 64acff3..505c363 100644
--- a/arch/arm/include/asm/arch-sunxi/clock.h
+++ b/arch/arm/include/asm/arch-sunxi/clock.h
@@ -26,7 +26,6 @@ int clock_init(void);
 int clock_twi_onoff(int port, int state);
 void clock_set_pll1(unsigned int hz);
 void clock_set_pll3(unsigned int hz);
-void clock_set_pll5(unsigned int hz);
 unsigned int clock_get_pll5p(void);
 unsigned int clock_get_pll6(void);
 void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz);
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index 3d4fcd1..f807af3 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -185,6 +185,7 @@ struct sunxi_ccm_reg {
 #define CCM_PLL5_CTRL_K(n)		((((n) - 1) & 0x3) << 4)
 #define CCM_PLL5_CTRL_N(n)		((((n) - 1) & 0x1f) << 8)
 #define CCM_PLL5_CTRL_UPD		(0x1 << 20)
+#define CCM_PLL5_CTRL_SIGMA_DELTA_EN	(0x1 << 24)
 #define CCM_PLL5_CTRL_EN		(0x1 << 31)
 
 #define PLL6_CFG_DEFAULT		0x90041811 /* 600 MHz */
@@ -274,6 +275,8 @@ struct sunxi_ccm_reg {
 
 #define MBUS_CLK_DEFAULT		0x81000001 /* PLL6 / 2 */
 
+#define CCM_PLL5_PATTERN		0xd1303333
+
 /* ahb_reset0 offsets */
 #define AHB_RESET_OFFSET_GMAC		17
 #define AHB_RESET_OFFSET_MCTL		14
@@ -308,4 +311,6 @@ struct sunxi_ccm_reg {
 #define CCM_DE_CTRL_PLL10		(5 << 24)
 #define CCM_DE_CTRL_GATE		(1 << 31)
 
+void clock_set_pll5(unsigned int clk, bool sigma_delta_enable);
+
 #endif /* _SUNXI_CLOCK_SUN6I_H */
-- 
2.1.0

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

* [U-Boot] [PATCH 09/14] sun6i: Add k and m parameters to clock_set_pll5()
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
                   ` (6 preceding siblings ...)
  2014-12-16 20:31 ` [U-Boot] [PATCH 08/14] sun6i: Add a sigma_delta_enable paramter to clock_set_pll5() Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-18 19:07   ` Ian Campbell
  2014-12-19 10:03   ` Siarhei Siamashka
  2014-12-16 20:31 ` [U-Boot] [PATCH 10/14] sunxi: Move await_completion dram helper to dram.h Hans de Goede
                   ` (5 subsequent siblings)
  13 siblings, 2 replies; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

The A23 (sun8i) requires different values for these then sun6i, so make them
function parameters.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/cpu/armv7/sunxi/clock_sun6i.c        | 4 +---
 arch/arm/cpu/armv7/sunxi/dram_sun6i.c         | 2 +-
 arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 +-
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
index 193e314..8ef19df 100644
--- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
@@ -144,12 +144,10 @@ void clock_set_pll3(unsigned int clk)
 	       &ccm->pll3_cfg);
 }
 
-void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
+void clock_set_pll5(unsigned int clk, int k, int m, bool sigma_delta_enable)
 {
 	struct sunxi_ccm_reg * const ccm =
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
-	const int k = 2;
-	const int m = 1;
 
 	if (sigma_delta_enable)
 		writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg);
diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
index bc6428a..a8bbdfd 100644
--- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
@@ -46,7 +46,7 @@ static void mctl_sys_init(void)
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 	const int dram_clk_div = 2;
 
-	clock_set_pll5(DRAM_CLK * dram_clk_div, false);
+	clock_set_pll5(DRAM_CLK * dram_clk_div, 2, 1, false);
 
 	clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV0_MASK,
 		CCM_DRAMCLK_CFG_DIV0(dram_clk_div) | CCM_DRAMCLK_CFG_RST |
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index f807af3..7d61216 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -311,6 +311,6 @@ struct sunxi_ccm_reg {
 #define CCM_DE_CTRL_PLL10		(5 << 24)
 #define CCM_DE_CTRL_GATE		(1 << 31)
 
-void clock_set_pll5(unsigned int clk, bool sigma_delta_enable);
+void clock_set_pll5(unsigned int clk, int k, int m, bool sigma_delta_enable);
 
 #endif /* _SUNXI_CLOCK_SUN6I_H */
-- 
2.1.0

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

* [U-Boot] [PATCH 10/14] sunxi: Move await_completion dram helper to dram.h
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
                   ` (7 preceding siblings ...)
  2014-12-16 20:31 ` [U-Boot] [PATCH 09/14] sun6i: Add k and m parameters " Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-18 19:08   ` Ian Campbell
  2014-12-19 10:06   ` Siarhei Siamashka
  2014-12-16 20:31 ` [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i Hans de Goede
                   ` (4 subsequent siblings)
  13 siblings, 2 replies; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

The await_completion helper is already copy pasted between the sun4i and sun6i
dram code, and we need it for sun8i too, so lets make it an inline helper in
dram.h, rather then adding yet another copy.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/cpu/armv7/sunxi/dram_sun4i.c  | 17 ++---------------
 arch/arm/cpu/armv7/sunxi/dram_sun6i.c  | 31 +++++++++----------------------
 arch/arm/include/asm/arch-sunxi/dram.h | 14 ++++++++++++++
 3 files changed, 25 insertions(+), 37 deletions(-)

diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun4i.c b/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
index ec8aaa7..c736fa3 100644
--- a/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
@@ -36,24 +36,11 @@
 #define CPU_CFG_CHIP_REV_B 0x3
 
 /*
- * Wait up to 1s for value to be set in given part of reg.
- */
-static void await_completion(u32 *reg, u32 mask, u32 val)
-{
-	unsigned long tmo = timer_get_us() + 1000000;
-
-	while ((readl(reg) & mask) != val) {
-		if (timer_get_us() > tmo)
-			panic("Timeout initialising DRAM\n");
-	}
-}
-
-/*
  * Wait up to 1s for mask to be clear in given reg.
  */
 static inline void await_bits_clear(u32 *reg, u32 mask)
 {
-	await_completion(reg, mask, 0);
+	mctl_await_completion(reg, mask, 0);
 }
 
 /*
@@ -61,7 +48,7 @@ static inline void await_bits_clear(u32 *reg, u32 mask)
  */
 static inline void await_bits_set(u32 *reg, u32 mask)
 {
-	await_completion(reg, mask, mask);
+	mctl_await_completion(reg, mask, mask);
 }
 
 /*
diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
index a8bbdfd..e1670e5 100644
--- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
@@ -27,19 +27,6 @@ struct dram_sun6i_para {
 	u16 page_size;
 };
 
-/*
- * Wait up to 1s for value to be set in given part of reg.
- */
-static void await_completion(u32 *reg, u32 mask, u32 val)
-{
-	unsigned long tmo = timer_get_us() + 1000000;
-
-	while ((readl(reg) & mask) != val) {
-		if (timer_get_us() > tmo)
-			panic("Timeout initialising DRAM\n");
-	}
-}
-
 static void mctl_sys_init(void)
 {
 	struct sunxi_ccm_reg * const ccm =
@@ -51,7 +38,7 @@ static void mctl_sys_init(void)
 	clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV0_MASK,
 		CCM_DRAMCLK_CFG_DIV0(dram_clk_div) | CCM_DRAMCLK_CFG_RST |
 		CCM_DRAMCLK_CFG_UPD);
-	await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
+	mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
 
 	writel(MDFS_CLK_DEFAULT, &ccm->mdfs_clk_cfg);
 
@@ -107,8 +94,8 @@ static bool mctl_rank_detect(u32 *gsr0, int rank)
 	const u32 done = MCTL_DX_GSR0_RANK0_TRAIN_DONE << rank;
 	const u32 err = MCTL_DX_GSR0_RANK0_TRAIN_ERR << rank;
 
-	await_completion(gsr0, done, done);
-	await_completion(gsr0 + 0x10, done, done);
+	mctl_await_completion(gsr0, done, done);
+	mctl_await_completion(gsr0 + 0x10, done, done);
 
 	return !(readl(gsr0) & err) && !(readl(gsr0 + 0x10) & err);
 }
@@ -129,7 +116,7 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
 	}
 
 	writel(MCTL_MCMD_NOP, &mctl_ctl->mcmd);
-	await_completion(&mctl_ctl->mcmd, MCTL_MCMD_BUSY, 0);
+	mctl_await_completion(&mctl_ctl->mcmd, MCTL_MCMD_BUSY, 0);
 
 	/* PHY initialization */
 	writel(MCTL_PGCR, &mctl_phy->pgcr);
@@ -166,14 +153,14 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
 	writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx2gcr);
 	writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx3gcr);
 
-	await_completion(&mctl_phy->pgsr, 0x03, 0x03);
+	mctl_await_completion(&mctl_phy->pgsr, 0x03, 0x03);
 
 	writel(CONFIG_DRAM_ZQ, &mctl_phy->zq0cr1);
 
 	setbits_le32(&mctl_phy->pir, MCTL_PIR_CLEAR_STATUS);
 	writel(MCTL_PIR_STEP1, &mctl_phy->pir);
 	udelay(10);
-	await_completion(&mctl_phy->pgsr, 0x1f, 0x1f);
+	mctl_await_completion(&mctl_phy->pgsr, 0x1f, 0x1f);
 
 	/* rank detect */
 	if (!mctl_rank_detect(&mctl_phy->dx0gsr0, 1)) {
@@ -204,14 +191,14 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
 	setbits_le32(&mctl_phy->pir, MCTL_PIR_CLEAR_STATUS);
 	writel(MCTL_PIR_STEP2, &mctl_phy->pir);
 	udelay(10);
-	await_completion(&mctl_phy->pgsr, 0x11, 0x11);
+	mctl_await_completion(&mctl_phy->pgsr, 0x11, 0x11);
 
 	if (readl(&mctl_phy->pgsr) & MCTL_PGSR_TRAIN_ERR_MASK)
 		panic("Training error initialising DRAM\n");
 
 	/* Move to configure state */
 	writel(MCTL_SCTL_CONFIG, &mctl_ctl->sctl);
-	await_completion(&mctl_ctl->sstat, 0x07, 0x01);
+	mctl_await_completion(&mctl_ctl->sstat, 0x07, 0x01);
 
 	/* Set number of clks per micro-second */
 	writel(DRAM_CLK / 1000000, &mctl_ctl->togcnt1u);
@@ -270,7 +257,7 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
 
 	/* Move to access state */
 	writel(MCTL_SCTL_ACCESS, &mctl_ctl->sctl);
-	await_completion(&mctl_ctl->sstat, 0x07, 0x03);
+	mctl_await_completion(&mctl_ctl->sstat, 0x07, 0x03);
 }
 
 static void mctl_com_init(struct dram_sun6i_para *para)
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 9072e68..18924f5 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -12,6 +12,7 @@
 #ifndef _SUNXI_DRAM_H
 #define _SUNXI_DRAM_H
 
+#include <asm/io.h>
 #include <linux/types.h>
 
 /* dram regs definition */
@@ -23,4 +24,17 @@
 
 unsigned long sunxi_dram_init(void);
 
+/*
+ * Wait up to 1s for value to be set in given part of reg.
+ */
+static inline void mctl_await_completion(u32 *reg, u32 mask, u32 val)
+{
+	unsigned long tmo = timer_get_us() + 1000000;
+
+	while ((readl(reg) & mask) != val) {
+		if (timer_get_us() > tmo)
+			panic("Timeout initialising DRAM\n");
+	}
+}
+
 #endif /* _SUNXI_DRAM_H */
-- 
2.1.0

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

* [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
                   ` (8 preceding siblings ...)
  2014-12-16 20:31 ` [U-Boot] [PATCH 10/14] sunxi: Move await_completion dram helper to dram.h Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-18 19:12   ` Ian Campbell
  2014-12-16 20:31 ` [U-Boot] [PATCH 12/14] sunxi: Use memcmp for mctl_mem_matches Hans de Goede
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

The sun8i boot0 code fills the DRAM with a "random" pattern before comparing
it at different offsets to do columns, etc. detection. The sun6i boot0 code
does not do it, but it seems like a good idea to do this regardless.

The new mctl_mem_fill function this introduces is added as an inline helper
in dram.h, so that it can be shared with the sun8i dram code.

While at it move mctl_mem_matches to dram.h for re-use in sun8i too.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/cpu/armv7/sunxi/dram_sun6i.c  | 15 +--------------
 arch/arm/include/asm/arch-sunxi/dram.h | 29 +++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
index e1670e5..4675c48 100644
--- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
@@ -326,20 +326,6 @@ static void mctl_port_cfg(void)
 	writel(0x00000307, &mctl_com->mbagcr[5]);
 }
 
-static bool mctl_mem_matches(u32 offset)
-{
-	const int match_count = 64;
-	int i, matches = 0;
-
-	for (i = 0; i < match_count; i++) {
-		if (readl(CONFIG_SYS_SDRAM_BASE + i * 4) ==
-		    readl(CONFIG_SYS_SDRAM_BASE + offset + i * 4))
-			matches++;
-	}
-
-	return matches == match_count;
-}
-
 unsigned long sunxi_dram_init(void)
 {
 	struct sunxi_mctl_com_reg * const mctl_com =
@@ -391,6 +377,7 @@ unsigned long sunxi_dram_init(void)
 		    MCTL_CR_BANK(1) | MCTL_CR_RANK(1));
 
 	/* Detect and set page size */
+	mctl_mem_fill();
 	for (columns = 7; columns < 20; columns++) {
 		if (mctl_mem_matches(1 << columns))
 			break;
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 18924f5..0bf718c 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -22,6 +22,8 @@
 #include <asm/arch/dram_sun4i.h>
 #endif
 
+#define MCTL_MEM_FILL_MATCH_COUNT 64
+
 unsigned long sunxi_dram_init(void);
 
 /*
@@ -37,4 +39,31 @@ static inline void mctl_await_completion(u32 *reg, u32 mask, u32 val)
 	}
 }
 
+/*
+ * Fill beginning of DRAM with "random" data for mctl_mem_matches()
+ */
+static inline void mctl_mem_fill(void)
+{
+	int i;
+
+	for (i = 0; i < MCTL_MEM_FILL_MATCH_COUNT; i++)
+		writel(0xaa55aa55 + i, CONFIG_SYS_SDRAM_BASE + i * 4);
+}
+
+/*
+ * Test if memory at offset offset matches memory@begin of DRAM
+ */
+static inline bool mctl_mem_matches(u32 offset)
+{
+	int i, matches = 0;
+
+	for (i = 0; i < MCTL_MEM_FILL_MATCH_COUNT; i++) {
+		if (readl(CONFIG_SYS_SDRAM_BASE + i * 4) ==
+		    readl(CONFIG_SYS_SDRAM_BASE + offset + i * 4))
+			matches++;
+	}
+
+	return matches == MCTL_MEM_FILL_MATCH_COUNT;
+}
+
 #endif /* _SUNXI_DRAM_H */
-- 
2.1.0

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

* [U-Boot] [PATCH 12/14] sunxi: Use memcmp for mctl_mem_matches
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
                   ` (9 preceding siblings ...)
  2014-12-16 20:31 ` [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-18 19:13   ` Ian Campbell
  2014-12-16 20:31 ` [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support Hans de Goede
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

Use memcmp for mctl_mem_matches instead of DIY.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/include/asm/arch-sunxi/dram.h | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 0bf718c..a8a37d5 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -55,15 +55,9 @@ static inline void mctl_mem_fill(void)
  */
 static inline bool mctl_mem_matches(u32 offset)
 {
-	int i, matches = 0;
-
-	for (i = 0; i < MCTL_MEM_FILL_MATCH_COUNT; i++) {
-		if (readl(CONFIG_SYS_SDRAM_BASE + i * 4) ==
-		    readl(CONFIG_SYS_SDRAM_BASE + offset + i * 4))
-			matches++;
-	}
-
-	return matches == MCTL_MEM_FILL_MATCH_COUNT;
+	return memcmp((u32 *)CONFIG_SYS_SDRAM_BASE,
+		      (u32 *)(CONFIG_SYS_SDRAM_BASE + offset),
+		      MCTL_MEM_FILL_MATCH_COUNT * 4) == 0;
 }
 
 #endif /* _SUNXI_DRAM_H */
-- 
2.1.0

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

* [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
                   ` (10 preceding siblings ...)
  2014-12-16 20:31 ` [U-Boot] [PATCH 12/14] sunxi: Use memcmp for mctl_mem_matches Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-18 11:12   ` Chen-Yu Tsai
                     ` (2 more replies)
  2014-12-16 20:31 ` [U-Boot] [PATCH 14/14] sun8i: Add defconfig for Ippo_q8h v1.2 Hans de Goede
  2014-12-18 18:56 ` [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Ian Campbell
  13 siblings, 3 replies; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

Based on the register / dram_para headers from the Allwinner u-boot / linux
sources + the init sequences from boot0.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/cpu/armv7/sunxi/Makefile             |   1 +
 arch/arm/cpu/armv7/sunxi/board.c              |   3 +-
 arch/arm/cpu/armv7/sunxi/dram_sun8i.c         | 340 ++++++++++++++++++++++++++
 arch/arm/include/asm/arch-sunxi/clock_sun6i.h |   4 +
 arch/arm/include/asm/arch-sunxi/dram.h        |   2 +
 arch/arm/include/asm/arch-sunxi/dram_sun8i.h  | 266 ++++++++++++++++++++
 board/sunxi/Kconfig                           |   3 +-
 configs/Ippo_q8h_v5_defconfig                 |  17 +-
 include/configs/sun8i.h                       |   2 +
 9 files changed, 631 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/sunxi/dram_sun8i.c
 create mode 100644 arch/arm/include/asm/arch-sunxi/dram_sun8i.h

diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 3e8975a..1e89937 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_SUN4I)	+= dram_sun4i.o
 obj-$(CONFIG_MACH_SUN5I)	+= dram_sun4i.o
 obj-$(CONFIG_MACH_SUN6I)	+= dram_sun6i.o
 obj-$(CONFIG_MACH_SUN7I)	+= dram_sun4i.o
+obj-$(CONFIG_MACH_SUN8I)	+= dram_sun8i.o
 ifdef CONFIG_SPL_FEL
 obj-y	+= start.o
 endif
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
index 9b3e80c..bc98c56 100644
--- a/arch/arm/cpu/armv7/sunxi/board.c
+++ b/arch/arm/cpu/armv7/sunxi/board.c
@@ -114,7 +114,8 @@ void reset_cpu(ulong addr)
 /* do some early init */
 void s_init(void)
 {
-#if defined CONFIG_SPL_BUILD && defined CONFIG_MACH_SUN6I
+#if defined CONFIG_SPL_BUILD && \
+		(defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I)
 	/* Magic (undocmented) value taken from boot0, without this DRAM
 	 * access gets messed up (seems cache related) */
 	setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun8i.c b/arch/arm/cpu/armv7/sunxi/dram_sun8i.c
new file mode 100644
index 0000000..3736fd1
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun8i.c
@@ -0,0 +1,340 @@
+/*
+ * Sun8i platform dram controller init.
+ *
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * Note this code uses a lot of magic hex values, that is because this code
+ * simply replays the init sequence as done by the Allwinner boot0 code, so
+ * we do not know what these values mean. There are no symbolic constants for
+ * these magic values, since we do not know how to name them and making up
+ * names for them is not useful.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/prcm.h>
+
+static const struct dram_para dram_para = {
+	.clock = CONFIG_DRAM_CLK,
+	.type = 3,
+	.zq = CONFIG_DRAM_ZQ,
+	.odt_en = 1,
+	.para1 = 0, /* not used (only used when tpr13 bit 31 is set */
+	.para2 = 0, /* not used (only used when tpr13 bit 31 is set */
+	.mr0 = 6736,
+	.mr1 = 4,
+	.mr2 = 16,
+	.mr3 = 0,
+	/* tpr0 - 10 contain timing constants or-ed together in u32 vals */
+	.tpr0 = 0x2ab83def,
+	.tpr1 = 0x18082356,
+	.tpr2 = 0x00034156,
+	.tpr3 = 0x448c5533,
+	.tpr4 = 0x08010d00,
+	.tpr5 = 0x0340b20f,
+	.tpr6 = 0x20d118cc,
+	.tpr7 = 0x14062485,
+	.tpr8 = 0x220d1d52,
+	.tpr9 = 0x1e078c22,
+	.tpr10 = 0x3c,
+	.tpr11 = 0, /* not used */
+	.tpr12 = 0, /* not used */
+	.tpr13 = 0x30000,
+};
+
+static void mctl_sys_init(void)
+{
+	struct sunxi_ccm_reg * const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+	/* enable pll5, note the divide by 2 is deliberate! */
+	clock_set_pll5(dram_para.clock * 1000000 / 2, 1, 2,
+		       dram_para.tpr13 & 0x40000);
+
+	/* deassert ahb mctl reset */
+	setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
+
+	/* enable ahb mctl clock */
+	setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
+}
+
+static void mctl_apply_odt_correction(u32 *reg, int correction)
+{
+	int val;
+
+	val = (readl(reg) >> 8) & 0xff;
+	val += correction;
+
+	/* clamp */
+	if (val < 0)
+		val = 0;
+	else if (val > 255)
+		val = 255;
+
+	clrsetbits_le32(reg, 0xff00, val << 8);
+}
+
+static void mctl_init(u32 *bus_width)
+{
+	struct sunxi_ccm_reg * const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	struct sunxi_mctl_com_reg * const mctl_com =
+		(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+	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 correction;
+
+	if (dram_para.tpr13 & 0x20)
+		writel(0x40b, &mctl_phy->dcr);
+	else
+		writel(0x1000040b, &mctl_phy->dcr);
+
+	if (dram_para.clock >= 480)
+		writel(0x5c000, &mctl_phy->dllgcr);
+	else
+		writel(0xdc000, &mctl_phy->dllgcr);
+
+	writel(0x0a003e3f, &mctl_phy->pgcr0);
+	writel(0x03008421, &mctl_phy->pgcr1);
+
+	writel(dram_para.mr0, &mctl_phy->mr0);
+	writel(dram_para.mr1, &mctl_phy->mr1);
+	writel(dram_para.mr2, &mctl_phy->mr2);
+	writel(dram_para.mr3, &mctl_phy->mr3);
+
+	if (!(dram_para.tpr13 & 0x10000)) {
+		clrsetbits_le32(&mctl_phy->dx0gcr, 0x3800, 0x2000);
+		clrsetbits_le32(&mctl_phy->dx1gcr, 0x3800, 0x2000);
+	}
+
+	/*
+	 * All the masking and shifting below converts what I assume are DDR
+	 * timing constants from Allwinner dram_para tpr format to the actual
+	 * timing registers format.
+	 */
+
+	writel((dram_para.tpr0 & 0x000fffff), &mctl_phy->ptr2);
+	writel((dram_para.tpr1 & 0x1fffffff), &mctl_phy->ptr3);
+	writel((dram_para.tpr0 & 0x3ff00000) >> 2 |
+	       (dram_para.tpr2 & 0x0003ffff), &mctl_phy->ptr4);
+
+	writel(dram_para.tpr3, &mctl_phy->dtpr0);
+	writel(dram_para.tpr4, &mctl_phy->dtpr2);
+
+	writel(0x01000081, &mctl_phy->dtcr);
+
+	if (dram_para.clock <= 240 || !(dram_para.odt_en & 0x01)) {
+		clrbits_le32(&mctl_phy->dx0gcr, 0x600);
+		clrbits_le32(&mctl_phy->dx1gcr, 0x600);
+	}
+	if (dram_para.clock <= 240) {
+		writel(0, &mctl_phy->odtcr);
+		writel(0, &mctl_ctl->odtmap);
+	}
+
+	writel(((dram_para.tpr5 & 0x0f00) << 12) |
+	       ((dram_para.tpr5 & 0x00f8) <<  9) |
+	       ((dram_para.tpr5 & 0x0007) <<  8),
+	       &mctl_ctl->rfshctl0);
+
+	writel(((dram_para.tpr5 & 0x0003f000) << 12) |
+	       ((dram_para.tpr5 & 0x00fc0000) >>  2) |
+	       ((dram_para.tpr5 & 0x3f000000) >> 16) |
+	       ((dram_para.tpr6 & 0x0000003f) >>  0),
+	       &mctl_ctl->dramtmg0);
+
+	writel(((dram_para.tpr6 & 0x000007c0) << 10) | 
+	       ((dram_para.tpr6 & 0x0000f800) >> 3) |
+	       ((dram_para.tpr6 & 0x003f0000) >> 16),
+	       &mctl_ctl->dramtmg1);
+
+	writel(((dram_para.tpr6 & 0x0fc00000) << 2) |
+	       ((dram_para.tpr7 & 0x0000001f) << 16) |
+	       ((dram_para.tpr7 & 0x000003e0) << 3) |
+	       ((dram_para.tpr7 & 0x0000fc00) >> 10),
+	       &mctl_ctl->dramtmg2);
+
+	writel(((dram_para.tpr7 & 0x03ff0000) >> 16) |
+	       ((dram_para.tpr6 & 0xf0000000) >> 16),
+	       &mctl_ctl->dramtmg3);
+
+	writel(((dram_para.tpr7 & 0x3c000000) >> 2 ) |
+	       ((dram_para.tpr8 & 0x00000007) << 16) |
+	       ((dram_para.tpr8 & 0x00000038) << 5) |
+	       ((dram_para.tpr8 & 0x000003c0) >> 6),
+	       &mctl_ctl->dramtmg4);
+
+	writel(((dram_para.tpr8 & 0x00003c00) << 14) |
+	       ((dram_para.tpr8 & 0x0003c000) <<  2) |
+	       ((dram_para.tpr8 & 0x00fc0000) >> 10) |
+	       ((dram_para.tpr8 & 0x0f000000) >> 24),
+	       &mctl_ctl->dramtmg5);
+
+	writel(0x00000008, &mctl_ctl->dramtmg8);
+
+	writel(((dram_para.tpr8 & 0xf0000000) >> 4) |
+	       ((dram_para.tpr9 & 0x00007c00) << 6) |
+	       ((dram_para.tpr9 & 0x000003e0) << 3) |
+	       ((dram_para.tpr9 & 0x0000001f) >> 0),
+	       &mctl_ctl->pitmg0);
+
+	setbits_le32(&mctl_ctl->pitmg1, 0x80000);
+
+	writel(((dram_para.tpr9 & 0x003f8000) << 9) | 0x2001,
+	       &mctl_ctl->sched);
+
+	writel((dram_para.mr0 << 16) | dram_para.mr1, &mctl_ctl->init3);
+	writel((dram_para.mr2 << 16) | dram_para.mr3, &mctl_ctl->init4);
+
+	writel(0x00000000, &mctl_ctl->pimisc);
+	writel(0x80000000, &mctl_ctl->upd0);
+
+	writel(((dram_para.tpr9  & 0xffc00000) >> 22) |
+	       ((dram_para.tpr10 & 0x00000fff) << 16),
+	       &mctl_ctl->rfshtmg);
+
+	if (dram_para.tpr13 & 0x20)
+		writel(0x01040001, &mctl_ctl->mstr);
+	else
+		writel(0x01040401, &mctl_ctl->mstr);
+
+	if (!(dram_para.tpr13 & 0x20000)) {
+		writel(0x00000002, &mctl_ctl->pwrctl);
+		writel(0x00008001, &mctl_ctl->pwrtmg);
+	}
+
+	writel(0x00000001, &mctl_ctl->rfshctl3);
+	writel(0x00000001, &mctl_ctl->pimisc);
+
+	/* deassert dram_clk_cfg reset */
+	setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
+
+	setbits_le32(&mctl_com->ccr, 0x80000);
+
+	/* zq stuff */
+	writel((dram_para.zq >> 8) & 0xff, &mctl_phy->zqcr1);
+
+	writel(0x00000003, &mctl_phy->pir);
+	udelay(10);
+	mctl_await_completion(&mctl_phy->pgsr0, 0x09, 0x09);
+
+	writel(readl(&mctl_phy->zqsr0) | 0x10000000, &mctl_phy->zqcr2);
+	writel(dram_para.zq & 0xff, &mctl_phy->zqcr1);
+
+	/* A23-v1.0 SDK uses 0xfdf3, A23-v2.0 SDK uses 0x5f3 */
+	writel(0x000005f3, &mctl_phy->pir);
+	udelay(10);
+	mctl_await_completion(&mctl_phy->pgsr0, 0x03, 0x03);
+
+	if (readl(&mctl_phy->dx1gsr0) & 0x1000000) {
+		*bus_width = 8;
+		writel(0, &mctl_phy->dx1gcr);
+		writel(dram_para.zq & 0xff, &mctl_phy->zqcr1);
+		writel(0x5f3, &mctl_phy->pir);
+		udelay(10000);
+		setbits_le32(&mctl_ctl->mstr, 0x1000);
+	} else
+		*bus_width = 16;
+
+	correction = (dram_para.odt_en >> 8) & 0xff;
+	if (correction) {
+		if (dram_para.odt_en & 0x80000000)
+			correction = -correction;
+
+		mctl_apply_odt_correction(&mctl_phy->dx0lcdlr1, correction);
+		mctl_apply_odt_correction(&mctl_phy->dx1lcdlr1, correction);
+	}
+
+	mctl_await_completion(&mctl_ctl->statr, 0x01, 0x01);
+
+	writel(0x08003e3f, &mctl_phy->pgcr0);
+	writel(0x00000000, &mctl_ctl->rfshctl3);
+}
+
+unsigned long sunxi_dram_init(void)
+{
+	struct sunxi_mctl_com_reg * const mctl_com =
+		(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+	const u32 columns = 13;
+	u32 bus, bus_width, offset, page_size, rows;
+
+	mctl_sys_init();
+	mctl_init(&bus_width);
+
+	if (bus_width == 16) {
+		page_size = 8;
+		bus = 1;
+	} else {
+		page_size = 7;
+		bus = 0;
+	}
+
+	if (!(dram_para.tpr13 & 0x80000000)) {
+		/* Detect and set rows */
+		writel(0x000310f4 | MCTL_CR_PAGE_SIZE(page_size),
+		       &mctl_com->cr);
+		setbits_le32(&mctl_com->swonr, 0x0003ffff);
+		mctl_mem_fill();
+		for (rows = 11; rows < 16; rows++) {
+			offset = 1 << (rows + columns + bus);
+			if (mctl_mem_matches(offset))
+				break;
+		}
+		clrsetbits_le32(&mctl_com->cr, MCTL_CR_ROW_MASK,
+				MCTL_CR_ROW(rows));
+	} else {
+		rows = (dram_para.para1 >> 16) & 0xff;
+		writel(((dram_para.para2 & 0x000000f0) << 11) |
+		       ((rows - 1) << 4) |
+		       ((dram_para.para1 & 0x0f000000) >> 22) |
+		       0x31000 | MCTL_CR_PAGE_SIZE(page_size),
+		       &mctl_com->cr);
+		setbits_le32(&mctl_com->swonr, 0x0003ffff);
+	}
+
+	/* Setup DRAM master priority? If this is left out things still work */
+	writel(0x00000008, &mctl_com->mcr0_0);
+	writel(0x0001000d, &mctl_com->mcr1_0);
+	writel(0x00000004, &mctl_com->mcr0_1);
+	writel(0x00000080, &mctl_com->mcr1_1);
+	writel(0x00000004, &mctl_com->mcr0_2);
+	writel(0x00000019, &mctl_com->mcr1_2);
+	writel(0x00000004, &mctl_com->mcr0_3);
+	writel(0x00000080, &mctl_com->mcr1_3);
+	writel(0x00000004, &mctl_com->mcr0_4);
+	writel(0x01010040, &mctl_com->mcr1_4);
+	writel(0x00000004, &mctl_com->mcr0_5);
+	writel(0x0001002f, &mctl_com->mcr1_5);
+	writel(0x00000004, &mctl_com->mcr0_6);
+	writel(0x00010020, &mctl_com->mcr1_6);
+	writel(0x00000004, &mctl_com->mcr0_7);
+	writel(0x00010020, &mctl_com->mcr1_7);
+	writel(0x00000008, &mctl_com->mcr0_8);
+	writel(0x00000001, &mctl_com->mcr1_8);
+	writel(0x00000008, &mctl_com->mcr0_9);
+	writel(0x00000005, &mctl_com->mcr1_9);
+	writel(0x00000008, &mctl_com->mcr0_10);
+	writel(0x00000003, &mctl_com->mcr1_10);
+	writel(0x00000008, &mctl_com->mcr0_11);
+	writel(0x00000005, &mctl_com->mcr1_11);
+	writel(0x00000008, &mctl_com->mcr0_12);
+	writel(0x00000003, &mctl_com->mcr1_12);
+	writel(0x00000008, &mctl_com->mcr0_13);
+	writel(0x00000004, &mctl_com->mcr1_13);
+	writel(0x00000008, &mctl_com->mcr0_14);
+	writel(0x00000002, &mctl_com->mcr1_14);
+	writel(0x00000008, &mctl_com->mcr0_15);
+	writel(0x00000003, &mctl_com->mcr1_15);
+	writel(0x00010138, &mctl_com->bwcr);
+
+	return 1 << (rows + columns + bus);
+}
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index 7d61216..45a199c 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -273,7 +273,11 @@ struct sunxi_ccm_reg {
 #define CCM_HDMI_CTRL_DDC_GATE		(0x1 << 30)
 #define CCM_HDMI_CTRL_GATE		(0x1 << 31)
 
+#ifndef CONFIG_MACH_SUN8I
 #define MBUS_CLK_DEFAULT		0x81000001 /* PLL6 / 2 */
+#else
+#define MBUS_CLK_DEFAULT		0x81000003 /* PLL6 / 4 */
+#endif
 
 #define CCM_PLL5_PATTERN		0xd1303333
 
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index a8a37d5..8d78029 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -18,6 +18,8 @@
 /* dram regs definition */
 #if defined(CONFIG_MACH_SUN6I)
 #include <asm/arch/dram_sun6i.h>
+#elif defined(CONFIG_MACH_SUN8I)
+#include <asm/arch/dram_sun8i.h>
 #else
 #include <asm/arch/dram_sun4i.h>
 #endif
diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i.h
new file mode 100644
index 0000000..425cf37
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i.h
@@ -0,0 +1,266 @@
+/*
+ * Sun8i platform dram controller register and constant defines
+ *
+ * (C) Copyright 2007-2013
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * CPL <cplanxy@allwinnertech.com>
+ * Jerry Wang <wangflord@allwinnertech.com>
+ *
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _SUNXI_DRAM_SUN8I_H
+#define _SUNXI_DRAM_SUN8I_H
+
+struct dram_para {
+	u32 clock;
+	u32 type;
+	u32 zq;
+	u32 odt_en;
+	u32 para1;
+	u32 para2;
+	u32 mr0;
+	u32 mr1;
+	u32 mr2;
+	u32 mr3;
+	u32 tpr0;
+	u32 tpr1;
+	u32 tpr2;
+	u32 tpr3;
+	u32 tpr4;
+	u32 tpr5;
+   	u32 tpr6;
+	u32 tpr7;
+	u32 tpr8;
+	u32 tpr9;
+	u32 tpr10;
+	u32 tpr11;
+	u32 tpr12;
+	u32 tpr13;
+};
+
+struct sunxi_mctl_com_reg {
+	u32 cr;			/* 0x00 */
+	u32 ccr;		/* 0x04 controller configuration register */
+	u32 dbgcr;		/* 0x08 */
+	u8 res0[0x4];		/* 0x0c */
+	u32 mcr0_0;		/* 0x10 */
+	u32 mcr1_0;		/* 0x14 */
+	u32 mcr0_1;		/* 0x18 */
+	u32 mcr1_1;		/* 0x1c */
+	u32 mcr0_2;		/* 0x20 */
+	u32 mcr1_2;		/* 0x24 */
+	u32 mcr0_3;		/* 0x28 */
+	u32 mcr1_3;		/* 0x2c */
+	u32 mcr0_4;		/* 0x30 */
+	u32 mcr1_4;		/* 0x34 */
+	u32 mcr0_5;		/* 0x38 */
+	u32 mcr1_5;		/* 0x3c */
+	u32 mcr0_6;		/* 0x40 */
+	u32 mcr1_6;		/* 0x44 */
+	u32 mcr0_7;		/* 0x48 */
+	u32 mcr1_7;		/* 0x4c */
+	u32 mcr0_8;		/* 0x50 */
+	u32 mcr1_8;		/* 0x54 */
+	u32 mcr0_9;		/* 0x58 */
+	u32 mcr1_9;		/* 0x5c */
+	u32 mcr0_10;		/* 0x60 */
+	u32 mcr1_10;		/* 0x64 */
+	u32 mcr0_11;		/* 0x68 */
+	u32 mcr1_11;		/* 0x6c */
+	u32 mcr0_12;		/* 0x70 */
+	u32 mcr1_12;		/* 0x74 */
+	u32 mcr0_13;		/* 0x78 */
+	u32 mcr1_13;		/* 0x7c */
+	u32 mcr0_14;		/* 0x80 */
+	u32 mcr1_14;		/* 0x84 */
+	u32 mcr0_15;		/* 0x88 */
+	u32 mcr1_15;		/* 0x8c */
+	u32 bwcr;		/* 0x90 */
+	u32 maer;		/* 0x94 */
+	u8 res1[0x4];		/* 0x98 */
+	u32 mcgcr;		/* 0x9c */
+	u32 bwctr;		/* 0xa0 */
+	u8 res2[0x4];		/* 0xa4 */
+	u32 swonr;		/* 0xa8 */
+	u32 swoffr;		/* 0xac */
+};
+
+struct sunxi_mctl_ctl_reg {
+	u32 mstr;		/* 0x00 */
+	u32 statr;		/* 0x04 */
+	u8 res0[0x08];		/* 0x08 */
+	u32 mrctrl0;		/* 0x10 */
+	u32 mrctrl1;		/* 0x14 */
+	u32 mrstatr;		/* 0x18 */
+	u8 res1[0x04];		/* 0x1c */
+	u32 derateen;		/* 0x20 */
+	u32 deratenint;		/* 0x24 */
+	u8 res2[0x08];		/* 0x28 */
+	u32 pwrctl;		/* 0x30 */
+	u32 pwrtmg;		/* 0x34 */
+	u8 res3[0x18];		/* 0x38 */
+	u32 rfshctl0;		/* 0x50 */
+	u32 rfshctl1;		/* 0x54 */
+	u8 res4[0x8];		/* 0x58 */
+	u32 rfshctl3;		/* 0x60 */
+	u32 rfshtmg;		/* 0x64 */
+	u8 res6[0x68];		/* 0x68 */
+	u32 init0;		/* 0xd0 */
+	u32 init1;		/* 0xd4 */
+	u32 init2;		/* 0xd8 */
+	u32 init3;		/* 0xdc */
+	u32 init4;		/* 0xe0 */
+	u32 init5;		/* 0xe4 */
+	u8 res7[0x0c];		/* 0xe8 */
+	u32 rankctl;		/* 0xf4 */
+	u8 res8[0x08];		/* 0xf8 */
+	u32 dramtmg0;		/* 0x100 */
+	u32 dramtmg1;		/* 0x104 */
+	u32 dramtmg2;		/* 0x108 */
+	u32 dramtmg3;		/* 0x10c */
+	u32 dramtmg4;		/* 0x110 */
+	u32 dramtmg5;		/* 0x114 */
+	u32 dramtmg6;		/* 0x118 */
+	u32 dramtmg7;		/* 0x11c */
+	u32 dramtmg8;		/* 0x120 */
+	u8 res9[0x5c];		/* 0x124 */
+	u32 zqctl0;		/* 0x180 */
+	u32 zqctl1;		/* 0x184 */
+	u32 zqctl2;		/* 0x188 */
+	u32 zqstat;		/* 0x18c */
+	u32 pitmg0;		/* 0x190 */
+	u32 pitmg1;		/* 0x194 */
+	u32 plpcfg0;		/* 0x198 */
+	u8 res10[0x04];		/* 0x19c */
+	u32 upd0;		/* 0x1a0 */
+	u32 upd1;		/* 0x1a4 */
+	u32 upd2;		/* 0x1a8 */
+	u32 upd3;		/* 0x1ac */
+	u32 pimisc;		/* 0x1b0 */
+	u8 res11[0x1c];		/* 0x1b4 */
+	u32 trainctl0;		/* 0x1d0 */
+	u32 trainctl1;		/* 0x1d4 */
+	u32 trainctl2;		/* 0x1d8 */
+	u32 trainstat;		/* 0x1dc */
+	u8 res12[0x60];		/* 0x1e0 */
+	u32 odtcfg;		/* 0x240 */
+	u32 odtmap;		/* 0x244 */
+	u8 res13[0x08];		/* 0x248 */
+	u32 sched;		/* 0x250 */
+	u8 res14[0x04];		/* 0x254 */
+	u32 perfshpr0;		/* 0x258 */
+	u32 perfshpr1;		/* 0x25c */
+	u32 perflpr0;		/* 0x260 */
+	u32 perflpr1;		/* 0x264 */
+	u32 perfwr0;		/* 0x268 */
+	u32 perfwr1;		/* 0x26c */
+};
+
+struct sunxi_mctl_phy_reg {
+	u8 res0[0x04];		/* 0x00 */
+	u32 pir;		/* 0x04 */
+	u32 pgcr0;		/* 0x08 phy general configuration register */
+	u32 pgcr1;		/* 0x0c phy general configuration register */
+	u32 pgsr0;		/* 0x10 */
+	u32 pgsr1;		/* 0x14 */
+	u32 dllgcr;		/* 0x18 */
+	u32 ptr0;		/* 0x1c */
+	u32 ptr1;		/* 0x20 */
+	u32 ptr2;		/* 0x24 */
+	u32 ptr3;		/* 0x28 */
+	u32 ptr4;		/* 0x2c */
+	u32 acmdlr;		/* 0x30 */
+	u32 acbdlr;		/* 0x34 */
+	u32 aciocr;		/* 0x38 */
+	u32 dxccr;		/* 0x3c DATX8 common configuration register */
+	u32 dsgcr;		/* 0x40 dram system general config register */
+	u32 dcr;		/* 0x44 */
+	u32 dtpr0;		/* 0x48 dram timing parameters register 0 */
+	u32 dtpr1;		/* 0x4c dram timing parameters register 1 */
+	u32 dtpr2;		/* 0x50 dram timing parameters register 2 */
+	u32 mr0;		/* 0x54 mode register 0 */
+	u32 mr1;		/* 0x58 mode register 1 */
+	u32 mr2;		/* 0x5c mode register 2 */
+	u32 mr3;		/* 0x60 mode register 3 */
+	u32 odtcr;		/* 0x64 */
+	u32 dtcr;		/* 0x68 */
+	u32 dtar0;		/* 0x6c data training address register 0 */
+	u32 dtar1;		/* 0x70 data training address register 1 */
+	u32 dtar2;		/* 0x74 data training address register 2 */
+	u32 dtar3;		/* 0x78 data training address register 3 */
+	u32 dtdr0;		/* 0x7c */
+	u32 dtdr1;		/* 0x80 */
+	u32 dtedr0;		/* 0x84 */
+	u32 dtedr1;		/* 0x88 */
+	u32 pgcr2;		/* 0x8c */
+	u8 res1[0x70];		/* 0x90 */
+	u32 bistrr;		/* 0x100 */
+	u32 bistwcr;		/* 0x104 */
+	u32 bistmskr0;		/* 0x108 */
+	u32 bistmskr1;		/* 0x10c */
+	u32 bistmskr2;		/* 0x110 */
+	u32 bistlsr;		/* 0x114 */
+	u32 bistar0;		/* 0x118 */
+	u32 bistar1;		/* 0x11c */
+	u32 bistar2;		/* 0x120 */
+	u32 bistupdr;		/* 0x124 */
+	u32 bistgsr;		/* 0x128 */
+	u32 bistwer;		/* 0x12c */
+	u32 bistber0;		/* 0x130 */
+	u32 bistber1;		/* 0x134 */
+	u32 bistber2;		/* 0x138 */
+	u32 bistber3;		/* 0x13c */
+	u32 bistwcsr;		/* 0x140 */
+	u32 bistfwr0;		/* 0x144 */
+	u32 bistfwr1;		/* 0x148 */
+	u32 bistfwr2;		/* 0x14c */
+	u8 res2[0x30];		/* 0x150 */
+	u32 zqcr0;		/* 0x180 zq control register 0 */
+	u32 zqcr1;		/* 0x184 zq control register 1 */
+	u32 zqsr0;		/* 0x188 zq status register 0 */
+	u32 zqsr1;		/* 0x18c zq status register 1 */
+	u32 zqcr2;		/* 0x190 zq control register 2 */
+	u8 res3[0x2c];		/* 0x194 */
+	u32 dx0gcr;		/* 0x1c0 */
+	u32 dx0gsr0;		/* 0x1c4 */
+	u32 dx0gsr1;		/* 0x1c8 */
+	u32 dx0bdlr0;		/* 0x1cc */
+	u32 dx0bdlr1;		/* 0x1d0 */
+	u32 dx0bdlr2;		/* 0x1d4 */
+	u32 dx0bdlr3;		/* 0x1d8 */
+	u32 dx0bdlr4;		/* 0x1dc */
+	u32 dx0lcdlr0;		/* 0x1e0 */
+	u32 dx0lcdlr1;		/* 0x1e4 */
+	u32 dx0lcdlr2;		/* 0x1e8 */
+	u32 dx0mdlr;		/* 0x1ec */
+	u32 dx0gtr;		/* 0x1f0 */
+	u32 dx0gsr2;		/* 0x1f4 */
+	u8 res4[0x08];		/* 0x1f8 */
+	u32 dx1gcr;		/* 0x200 */
+	u32 dx1gsr0;		/* 0x204 */
+	u32 dx1gsr1;		/* 0x208 */
+	u32 dx1bdlr0;		/* 0x20c */
+	u32 dx1bdlr1;		/* 0x210 */
+	u32 dx1bdlr2;		/* 0x214 */
+	u32 dx1bdlr3;		/* 0x218 */
+	u32 dx1bdlr4;		/* 0x21c */
+	u32 dx1lcdlr0;		/* 0x220 */
+	u32 dx1lcdlr1;		/* 0x224 */
+	u32 dx1lcdlr2;		/* 0x228 */
+	u32 dx1mdlr;		/* 0x22c */
+	u32 dx1gtr;		/* 0x230 */
+	u32 dx1gsr2;		/* 0x234 */
+};
+
+/*
+ * DRAM common (sunxi_mctl_com_reg) register constants.
+ */
+#define MCTL_CR_ROW_MASK		(0xf << 4)
+#define MCTL_CR_ROW(x)			(((x) - 1) << 4)
+#define MCTL_CR_PAGE_SIZE_MASK		(0xf << 8)
+#define MCTL_CR_PAGE_SIZE(x)		((x) << 8)
+
+#endif /* _SUNXI_DRAM_SUN8I_H */
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
index 5bb2f58..5a88ba0 100644
--- a/board/sunxi/Kconfig
+++ b/board/sunxi/Kconfig
@@ -29,10 +29,11 @@ config MACH_SUN7I
 config MACH_SUN8I
 	bool "sun8i (Allwinner A23)"
 	select CPU_V7
+	select SUPPORT_SPL
 
 endchoice
 
-if MACH_SUN6I
+if MACH_SUN6I || MACH_SUN8I
 
 config DRAM_CLK
 	int "sun6i dram clock speed"
diff --git a/configs/Ippo_q8h_v5_defconfig b/configs/Ippo_q8h_v5_defconfig
index 50c2f93..37aa46d 100644
--- a/configs/Ippo_q8h_v5_defconfig
+++ b/configs/Ippo_q8h_v5_defconfig
@@ -1,8 +1,15 @@
+CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=5"
-CONFIG_ARM=y
-CONFIG_ARCH_SUNXI=y
-CONFIG_MACH_SUN8I=y
-CONFIG_TARGET_IPPO_Q8H_V5=y
-CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-ippo-q8h-v5.dtb"
+CONFIG_FDTFILE="sun8i-a23-ippo-q8h-v5.dtb"
 CONFIG_VIDEO=n
 CONFIG_USB_KEYBOARD=n
++S:CONFIG_ARM=y
++S:CONFIG_ARCH_SUNXI=y
++S:CONFIG_MACH_SUN8I=y
++S:CONFIG_DRAM_CLK=480
+# zq = 0xf777
++S:CONFIG_DRAM_ZQ=63351
+# Wifi power
++S:CONFIG_AXP221_DLDO1_VOLT=3300
+# aldo1 is connected to VCC-IO, VCC-PD, VCC-USB and VCC-HP
++S:CONFIG_AXP221_ALDO1_VOLT=3000
diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h
index 6f1fc48..792422d 100644
--- a/include/configs/sun8i.h
+++ b/include/configs/sun8i.h
@@ -12,6 +12,8 @@
 /*
  * A23 specific configuration
  */
+#define CONFIG_CLK_FULL_SPEED	1008000000
+
 #define CONFIG_SYS_PROMPT	"sun8i# "
 
 /*
-- 
2.1.0

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

* [U-Boot] [PATCH 14/14] sun8i: Add defconfig for Ippo_q8h v1.2
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
                   ` (11 preceding siblings ...)
  2014-12-16 20:31 ` [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support Hans de Goede
@ 2014-12-16 20:31 ` Hans de Goede
  2014-12-18 19:19   ` Ian Campbell
  2014-12-18 18:56 ` [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Ian Campbell
  13 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-16 20:31 UTC (permalink / raw)
  To: u-boot

We need separate defconfigs for the v5 and v1.2 versions of this board, as
they use different DRAM parameters.

Note they also use different dtb files, as the wifi is different too.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 configs/Ippo_q8h_v1.2_defconfig | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 configs/Ippo_q8h_v1.2_defconfig

diff --git a/configs/Ippo_q8h_v1.2_defconfig b/configs/Ippo_q8h_v1.2_defconfig
new file mode 100644
index 0000000..fefed32
--- /dev/null
+++ b/configs/Ippo_q8h_v1.2_defconfig
@@ -0,0 +1,15 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=5"
+CONFIG_FDTFILE="sun8i-a23-ippo-q8h-v1.2.dtb"
+CONFIG_VIDEO=n
+CONFIG_USB_KEYBOARD=n
++S:CONFIG_ARM=y
++S:CONFIG_ARCH_SUNXI=y
++S:CONFIG_MACH_SUN8I=y
++S:CONFIG_DRAM_CLK=432
+# zq = 0xf74a
++S:CONFIG_DRAM_ZQ=63306
+# Wifi power
++S:CONFIG_AXP221_DLDO1_VOLT=3300
+# aldo1 is connected to VCC-IO, VCC-PD, VCC-USB and VCC-HP
++S:CONFIG_AXP221_ALDO1_VOLT=3000
-- 
2.1.0

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

* [U-Boot] [PATCH 02/14] sunxi: Add support for the rsb (Reduced Serial Bus)
  2014-12-16 20:31 ` [U-Boot] [PATCH 02/14] sunxi: Add support for the rsb (Reduced Serial Bus) Hans de Goede
@ 2014-12-17  2:22   ` Chen-Yu Tsai
  2014-12-17 12:56     ` Hans de Goede
  0 siblings, 1 reply; 54+ messages in thread
From: Chen-Yu Tsai @ 2014-12-17  2:22 UTC (permalink / raw)
  To: u-boot

Hi,

On Wed, Dec 17, 2014 at 4:31 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> sun8i (A23) introduces a new bus for communicating with the pmic, the rsb,
> the rsb is also used to communicate with the pmic on the A80, and is
> documented in the A80 user manual.
>
> This commit adds support for this based on the rsb driver from the allwinner
> u-boot sources.
>
> Note: Not yet ready for upstream, code needs some significant cleanups.

Confusing note.

>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  arch/arm/cpu/armv7/sunxi/Makefile      |   1 +
>  arch/arm/cpu/armv7/sunxi/rsb.c         | 158 +++++++++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-sunxi/cpu.h  |   3 +-
>  arch/arm/include/asm/arch-sunxi/gpio.h |   2 +
>  arch/arm/include/asm/arch-sunxi/prcm.h |   3 +-
>  arch/arm/include/asm/arch-sunxi/rsb.h  |  55 ++++++++++++
>  6 files changed, 220 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arm/cpu/armv7/sunxi/rsb.c
>  create mode 100644 arch/arm/include/asm/arch-sunxi/rsb.h
>
> diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
> index 1337b60..3e8975a 100644
> --- a/arch/arm/cpu/armv7/sunxi/Makefile
> +++ b/arch/arm/cpu/armv7/sunxi/Makefile
> @@ -15,6 +15,7 @@ obj-y += pinmux.o
>  obj-$(CONFIG_MACH_SUN6I)       += prcm.o
>  obj-$(CONFIG_MACH_SUN8I)       += prcm.o
>  obj-$(CONFIG_MACH_SUN6I)       += p2wi.o
> +obj-$(CONFIG_MACH_SUN8I)       += rsb.o
>  obj-$(CONFIG_MACH_SUN4I)       += clock_sun4i.o
>  obj-$(CONFIG_MACH_SUN5I)       += clock_sun4i.o
>  obj-$(CONFIG_MACH_SUN6I)       += clock_sun6i.o
> diff --git a/arch/arm/cpu/armv7/sunxi/rsb.c b/arch/arm/cpu/armv7/sunxi/rsb.c
> new file mode 100644
> index 0000000..b72bb9d
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/sunxi/rsb.c
> @@ -0,0 +1,158 @@
> +/*
> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
> + *
> + * Based on allwinner u-boot sources rsb code which is:
> + * (C) Copyright 2007-2013
> + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
> + * lixiang <lixiang@allwinnertech.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <errno.h>
> +#include <asm/arch/cpu.h>
> +#include <asm/arch/gpio.h>
> +#include <asm/arch/prcm.h>
> +#include <asm/arch/rsb.h>
> +
> +static void rsb_cfg_io(void)
> +{
> +       sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL0_R_RSB_SCK);
> +       sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL1_R_RSB_SDA);
> +       sunxi_gpio_set_pull(SUNXI_GPL(0), 1);
> +       sunxi_gpio_set_pull(SUNXI_GPL(1), 1);
> +       sunxi_gpio_set_drv(SUNXI_GPL(0), 2);
> +       sunxi_gpio_set_drv(SUNXI_GPL(1), 2);
> +}
> +
> +static void rsb_set_clk(void)
> +{
> +       struct sunxi_rsb_reg * const rsb =
> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
> +       u32 div = 0;
> +       u32 cd_odly = 0;
> +
> +       /* Source is Hosc24M, set RSB clk to 3Mhz */
> +       div = 24000000 / 3000000 / 2 - 1;
> +       cd_odly = div >> 1;
> +       if (!cd_odly)
> +               cd_odly = 1;
> +
> +       writel((cd_odly << 8) | div, &rsb->ccr);
> +}
> +
> +void rsb_init(void)
> +{
> +       struct sunxi_rsb_reg * const rsb =
> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
> +
> +       rsb_cfg_io();
> +
> +       /* Enable RSB and PIO clk, and de-assert their resets */
> +       prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB);
> +
> +       writel(RSB_CTRL_SOFT_RST, &rsb->ctrl);

Do we need a small delay here for the device to finish reset?

> +       rsb_set_clk();
> +}
> +
> +static int rsb_await_trans(void)
> +{
> +       struct sunxi_rsb_reg * const rsb =
> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
> +       unsigned long tmo = timer_get_us() + 1000000;
> +       u32 stat;
> +       int ret;
> +
> +       while (1) {
> +               stat = readl(&rsb->stat);
> +               if (stat & RSB_STAT_LBSY_INT) {
> +                       ret = -EBUSY;
> +                       break;
> +               }
> +               if (stat & RSB_STAT_TERR_INT) {
> +                       ret = -EIO;
> +                       break;
> +               }
> +               if (stat & RSB_STAT_TOVER_INT) {
> +                       ret = 0;
> +                       break;
> +               }
> +               if (timer_get_us() > tmo) {
> +                       ret = -ETIME;
> +                       break;
> +               }
> +       }
> +       writel(stat, &rsb->stat); /* Clear status bits */
> +
> +       return ret;
> +}
> +
> +int rsb_set_device_mode(u32 device_mode_data)
> +{
> +       struct sunxi_rsb_reg * const rsb =
> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
> +       unsigned long tmo = timer_get_us() + 1000000;
> +
> +       writel(RSB_DMCR_DEVICE_MODE_START | device_mode_data, &rsb->dmcr);
> +
> +       while (readl(&rsb->dmcr) & RSB_DMCR_DEVICE_MODE_START) {
> +               if (timer_get_us() > tmo)
> +                       return -ETIME;
> +       }
> +
> +       return rsb_await_trans();
> +}
> +
> +static int rsb_do_trans(void)
> +{
> +       struct sunxi_rsb_reg * const rsb =
> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
> +
> +       setbits_le32(&rsb->ctrl, RSB_CTRL_START_TRANS);
> +       return rsb_await_trans();
> +}
> +
> +int rsb_set_device_address(u16 device_addr, u16 runtime_addr)
> +{
> +       struct sunxi_rsb_reg * const rsb =
> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
> +
> +       writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr) |
> +              RSB_DEVADDR_DEVICE_ADDR(device_addr), &rsb->devaddr);
> +       writel(RSB_CMD_SET_RTSADDR, &rsb->cmd);
> +
> +       return rsb_do_trans();
> +}
> +
> +int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data)
> +{
> +       struct sunxi_rsb_reg * const rsb =
> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
> +
> +       writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr);
> +       writel(reg_addr, &rsb->addr);
> +       writel(data, &rsb->data);
> +       writel(RSB_CMD_BYTE_WRITE, &rsb->cmd);
> +
> +       return rsb_do_trans();
> +}
> +
> +int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data)
> +{
> +       struct sunxi_rsb_reg * const rsb =
> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
> +       int ret;
> +
> +       writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr);
> +       writel(reg_addr, &rsb->addr);
> +       writel(RSB_CMD_BYTE_READ, &rsb->cmd);
> +
> +       ret = rsb_do_trans();
> +       if (ret)
> +               return ret;
> +
> +       *data = readl(&rsb->data) & 0xff;
> +
> +       return 0;
> +}
> diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
> index 9500262..49c1614 100644
> --- a/arch/arm/include/asm/arch-sunxi/cpu.h
> +++ b/arch/arm/include/asm/arch-sunxi/cpu.h
> @@ -128,7 +128,8 @@
>  #define SUN6I_CPUCFG_BASE              0x01f01c00
>  #define SUNXI_R_UART_BASE              0x01f02800
>  #define SUNXI_R_PIO_BASE               0x01f02c00
> -#define SUNXI_P2WI_BASE                        0x01f03400
> +#define SUNXI_P2WI_BASE                        0x01f03400      /* on sun6i */
> +#define SUNXI_RSB_BASE                 0x01f03400      /* on sun8i */

Maybe we just use SUN6I_ SUN8I_ prefixes?
The base address will be different on sun9i.

>
>  /* CoreSight Debug Module */
>  #define SUNXI_CSDM_BASE                        0x3f500000
> diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
> index 9f972ce..6623f15 100644
> --- a/arch/arm/include/asm/arch-sunxi/gpio.h
> +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
> @@ -176,6 +176,8 @@ enum sunxi_gpio_number {
>  #define SUN6I_GPL0_R_P2WI_SCK  3
>  #define SUN6I_GPL1_R_P2WI_SDA  3
>
> +#define SUN8I_GPL0_R_RSB_SCK   2
> +#define SUN8I_GPL1_R_RSB_SDA   2
>  #define SUN8I_GPL2_R_UART_TX   2
>  #define SUN8I_GPL3_R_UART_RX   2
>
> diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
> index 88de1ff..82ed541 100644
> --- a/arch/arm/include/asm/arch-sunxi/prcm.h
> +++ b/arch/arm/include/asm/arch-sunxi/prcm.h
> @@ -50,7 +50,8 @@
>  #define PRCM_APB0_GATE_PIO (0x1 << 0)
>  #define PRCM_APB0_GATE_IR (0x1 << 1)
>  #define PRCM_APB0_GATE_TIMER01 (0x1 << 2)
> -#define PRCM_APB0_GATE_P2WI (0x1 << 3)
> +#define PRCM_APB0_GATE_P2WI (0x1 << 3)         /* sun6i */
> +#define PRCM_APB0_GATE_RSB (0x1 << 3)          /* sun8i */
>  #define PRCM_APB0_GATE_UART (0x1 << 4)
>  #define PRCM_APB0_GATE_1WIRE (0x1 << 5)
>  #define PRCM_APB0_GATE_I2C (0x1 << 6)
> diff --git a/arch/arm/include/asm/arch-sunxi/rsb.h b/arch/arm/include/asm/arch-sunxi/rsb.h
> new file mode 100644
> index 0000000..95a595a
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-sunxi/rsb.h
> @@ -0,0 +1,55 @@
> +/*
> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
> + *
> + * Based on allwinner u-boot sources rsb code which is:
> + * (C) Copyright 2007-2013
> + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
> + * lixiang <lixiang@allwinnertech.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#ifndef __SUNXI_RSB_H
> +#define __SUNXI_RSB_H
> +
> +#include <common.h>
> +#include <asm/io.h>
> +
> +struct sunxi_rsb_reg {
> +       u32 ctrl;       /* 0x00 */
> +       u32 ccr;        /* 0x04 */
> +       u32 inte;       /* 0x08 */
> +       u32 stat;       /* 0x0c */
> +       u32 addr;       /* 0x10 */
> +       u8 res0[8];     /* 0x14 */
> +       u32 data;       /* 0x1c */
> +       u8 res1[4];     /* 0x20 */
> +       u32 lcr;        /* 0x24 */
> +       u32 dmcr;       /* 0x28 */
> +       u32 cmd;        /* 0x2c */
> +       u32 devaddr;    /* 0x30 */
> +};
> +
> +#define RSB_CTRL_SOFT_RST              (1 << 0)
> +#define RSB_CTRL_START_TRANS           (1 << 7)
> +
> +#define RSB_STAT_TOVER_INT             (1 << 0)
> +#define RSB_STAT_TERR_INT              (1 << 1)
> +#define RSB_STAT_LBSY_INT              (1 << 2)
> +
> +#define RSB_DMCR_DEVICE_MODE_START     (1 << 31)
> +
> +#define RSB_CMD_BYTE_WRITE             0x4e
> +#define RSB_CMD_BYTE_READ              0x8b
> +#define RSB_CMD_SET_RTSADDR            0xe8
> +
> +#define RSB_DEVADDR_RUNTIME_ADDR(x)    ((x) << 16)
> +#define RSB_DEVADDR_DEVICE_ADDR(x)     ((x) << 0)
> +
> +void rsb_init(void);
> +int rsb_set_device_mode(u32 device_mode_data);
> +int rsb_set_device_address(u16 device_addr, u16 runtime_addr);
> +int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data);
> +int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data);
> +
> +#endif
> --
> 2.1.0

The rest looks good. Thanks!

ChenYu

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

* [U-Boot] [PATCH 03/14] sunxi: axp221: Add axp223 support
  2014-12-16 20:31 ` [U-Boot] [PATCH 03/14] sunxi: axp221: Add axp223 support Hans de Goede
@ 2014-12-17  2:34   ` Chen-Yu Tsai
  2014-12-18 10:44     ` Hans de Goede
  2014-12-18 19:00   ` Ian Campbell
  1 sibling, 1 reply; 54+ messages in thread
From: Chen-Yu Tsai @ 2014-12-17  2:34 UTC (permalink / raw)
  To: u-boot

On Wed, Dec 17, 2014 at 4:31 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> The axp223 appears to be the same as the axp221, except that it uses the
> rsb to communicate rather then the p2wi. At least all the registers we use
> are 100% the same.
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  arch/arm/cpu/armv7/sunxi/cpu_info.c |  2 +-
>  drivers/power/Kconfig               |  8 ++--
>  drivers/power/axp221.c              | 88 ++++++++++++++++++++++++++++---------
>  include/axp221.h                    |  4 ++
>  4 files changed, 76 insertions(+), 26 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c
> index 7a3a4ca..b6cb9de 100644
> --- a/arch/arm/cpu/armv7/sunxi/cpu_info.c
> +++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c
> @@ -76,7 +76,7 @@ int print_cpuinfo(void)
>
>  int sunxi_get_sid(unsigned int *sid)
>  {
> -#ifdef CONFIG_MACH_SUN6I
> +#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
>  #ifdef CONFIG_AXP221_POWER
>         return axp221_get_sid(sid);
>  #else
> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> index 1ec7c0e..7373a79 100644
> --- a/drivers/power/Kconfig
> +++ b/drivers/power/Kconfig
> @@ -1,10 +1,10 @@
>  config AXP221_POWER
> -       boolean "axp221 pmic support"
> -       depends on MACH_SUN6I
> +       boolean "axp221 / axp223 pmic support"
> +       depends on MACH_SUN6I || MACH_SUN8I
>         default y
>         ---help---
> -       Say y here to enable support for the axp221 pmic found on most sun6i
> -       (A31) boards.
> +       Say y here to enable support for the axp221 / axp223 pmic found on most
> +       sun6i (A31) / sun8i (A23) boards.
>
>  config AXP221_DLDO1_VOLT
>         int "axp221 dldo1 voltage"
> diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c
> index 826567a..717adad 100644
> --- a/drivers/power/axp221.c
> +++ b/drivers/power/axp221.c
> @@ -1,4 +1,10 @@
>  /*
> + * AXP221 and AXP223 driver
> + *
> + * IMPORTANT when making changes to this file check that the registers
> + * used are the same for the axp221 and axp223.
> + *
> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
>   * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
>   *
>   * SPDX-License-Identifier:    GPL-2.0+
> @@ -7,8 +13,50 @@
>  #include <common.h>
>  #include <errno.h>
>  #include <asm/arch/p2wi.h>
> +#include <asm/arch/rsb.h>
>  #include <axp221.h>
>
> +/*
> + * The axp221 uses the p2wi bus, the axp223 is identical (for all registers
> + * used sofar) but uses the rsb bus. These functions abstract this.
> + */
> +static int pmic_bus_init(void)
> +{
> +#ifdef CONFIG_MACH_SUN6I
> +       p2wi_init();
> +       return p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
> +                                       AXP221_INIT_DATA);
> +#else
> +       int ret;
> +
> +       rsb_init();
> +
> +       ret = rsb_set_device_mode(AXP223_DEVICE_MODE_DATA);
> +       if (ret)
> +               return ret;
> +
> +       return rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
> +#endif
> +}
> +
> +static int pmic_bus_read(const u8 addr, u8 *data)
> +{
> +#ifdef CONFIG_MACH_SUN6I
> +       return p2wi_read(addr, data);
> +#else
> +       return rsb_read(AXP223_RUNTIME_ADDR, addr, data);
> +#endif
> +}
> +
> +static int pmic_bus_write(const u8 addr, u8 data)
> +{
> +#ifdef CONFIG_MACH_SUN6I
> +       return p2wi_write(addr, data);
> +#else
> +       return rsb_write(AXP223_RUNTIME_ADDR, addr, data);
> +#endif
> +}
> +
>  static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div)
>  {
>         if (mvolt < min)
> @@ -24,12 +72,12 @@ static int axp221_setbits(u8 reg, u8 bits)
>         int ret;
>         u8 val;
>
> -       ret = p2wi_read(reg, &val);
> +       ret = pmic_bus_read(reg, &val);
>         if (ret)
>                 return ret;
>
>         val |= bits;
> -       return p2wi_write(reg, val);
> +       return pmic_bus_write(reg, val);
>  }
>
>  int axp221_set_dcdc1(unsigned int mvolt)
> @@ -37,7 +85,7 @@ int axp221_set_dcdc1(unsigned int mvolt)
>         int ret;
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
>
> -       ret = p2wi_write(AXP221_DCDC1_CTRL, cfg);
> +       ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
>         if (ret)
>                 return ret;
>
> @@ -49,28 +97,28 @@ int axp221_set_dcdc2(unsigned int mvolt)
>  {
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
>
> -       return p2wi_write(AXP221_DCDC2_CTRL, cfg);
> +       return pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
>  }
>
>  int axp221_set_dcdc3(unsigned int mvolt)
>  {
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
>
> -       return p2wi_write(AXP221_DCDC3_CTRL, cfg);
> +       return pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
>  }
>
>  int axp221_set_dcdc4(unsigned int mvolt)
>  {
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
>
> -       return p2wi_write(AXP221_DCDC4_CTRL, cfg);
> +       return pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
>  }
>
>  int axp221_set_dcdc5(unsigned int mvolt)
>  {
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
>
> -       return p2wi_write(AXP221_DCDC5_CTRL, cfg);
> +       return pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
>  }
>
>  int axp221_set_dldo1(unsigned int mvolt)
> @@ -78,7 +126,7 @@ int axp221_set_dldo1(unsigned int mvolt)
>         int ret;
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>
> -       ret = p2wi_write(AXP221_DLDO1_CTRL, cfg);
> +       ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg);
>         if (ret)
>                 return ret;
>
> @@ -91,7 +139,7 @@ int axp221_set_dldo2(unsigned int mvolt)
>         int ret;
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>
> -       ret = p2wi_write(AXP221_DLDO2_CTRL, cfg);
> +       ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg);
>         if (ret)
>                 return ret;
>
> @@ -104,7 +152,7 @@ int axp221_set_dldo3(unsigned int mvolt)
>         int ret;
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>
> -       ret = p2wi_write(AXP221_DLDO3_CTRL, cfg);
> +       ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg);
>         if (ret)
>                 return ret;
>
> @@ -117,7 +165,7 @@ int axp221_set_dldo4(unsigned int mvolt)
>         int ret;
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>
> -       ret = p2wi_write(AXP221_DLDO4_CTRL, cfg);
> +       ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg);
>         if (ret)
>                 return ret;
>
> @@ -130,7 +178,7 @@ int axp221_set_aldo1(unsigned int mvolt)
>         int ret;
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>
> -       ret = p2wi_write(AXP221_ALDO1_CTRL, cfg);
> +       ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
>         if (ret)
>                 return ret;
>
> @@ -143,7 +191,7 @@ int axp221_set_aldo2(unsigned int mvolt)
>         int ret;
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>
> -       ret = p2wi_write(AXP221_ALDO2_CTRL, cfg);
> +       ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
>         if (ret)
>                 return ret;
>
> @@ -156,7 +204,7 @@ int axp221_set_aldo3(unsigned int mvolt)
>         int ret;
>         u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>
> -       ret = p2wi_write(AXP221_ALDO3_CTRL, cfg);
> +       ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
>         if (ret)
>                 return ret;
>
> @@ -169,13 +217,11 @@ int axp221_init(void)
>         u8 axp_chip_id;
>         int ret;
>
> -       p2wi_init();
> -       ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
> -                                      AXP221_INIT_DATA);
> +       ret = pmic_bus_init();
>         if (ret)
>                 return ret;
>
> -       ret = p2wi_read(AXP221_CHIP_ID, &axp_chip_id);
> +       ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id);
>         if (ret)
>                 return ret;
>
> @@ -194,17 +240,17 @@ int axp221_get_sid(unsigned int *sid)
>         if (ret)
>                 return ret;
>
> -       ret = p2wi_write(AXP221_PAGE, 1);
> +       ret = pmic_bus_write(AXP221_PAGE, 1);
>         if (ret)
>                 return ret;
>
>         for (i = 0; i < 16; i++) {
> -               ret = p2wi_read(AXP221_SID + i, &dest[i]);
> +               ret = pmic_bus_read(AXP221_SID + i, &dest[i]);
>                 if (ret)
>                         return ret;
>         }
>
> -       p2wi_write(AXP221_PAGE, 0);
> +       pmic_bus_write(AXP221_PAGE, 0);
>
>         for (i = 0; i < 4; i++)
>                 sid[i] = be32_to_cpu(sid[i]);
> diff --git a/include/axp221.h b/include/axp221.h
> index db219c6..10d35e1 100644
> --- a/include/axp221.h
> +++ b/include/axp221.h
> @@ -10,6 +10,10 @@
>  #define AXP221_CTRL_ADDR 0x3e
>  #define AXP221_INIT_DATA 0x3e
>
> +#define AXP223_DEVICE_ADDR 0x3a3
> +#define AXP223_RUNTIME_ADDR 0x2d
> +#define AXP223_DEVICE_MODE_DATA 0x7c3e00
> +
>  /* Page 0 addresses */
>  #define AXP221_CHIP_ID         0x03
>  #define AXP221_OUTPUT_CTRL1    0x10
> --
> 2.1.0
>

git am reports:

Applying patch #422068 using 'git am'
Description: [U-Boot,03/14] sunxi: axp221: Add axp223 support
Applying: sunxi: axp221: Add axp223 support
/home/wens/sunxi/u-boot/.git/rebase-apply/patch:50: trailing whitespace.
 *
/home/wens/sunxi/u-boot/.git/rebase-apply/patch:76: trailing whitespace.

warning: 2 lines add whitespace errors.


ChenYu

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

* [U-Boot] [PATCH 02/14] sunxi: Add support for the rsb (Reduced Serial Bus)
  2014-12-17  2:22   ` Chen-Yu Tsai
@ 2014-12-17 12:56     ` Hans de Goede
  2014-12-18 18:57       ` Ian Campbell
  2014-12-18 18:59       ` Ian Campbell
  0 siblings, 2 replies; 54+ messages in thread
From: Hans de Goede @ 2014-12-17 12:56 UTC (permalink / raw)
  To: u-boot

Hi,

On 17-12-14 03:22, Chen-Yu Tsai wrote:
> Hi,
>
> On Wed, Dec 17, 2014 at 4:31 AM, Hans de Goede <hdegoede@redhat.com> wrote:
>> sun8i (A23) introduces a new bus for communicating with the pmic, the rsb,
>> the rsb is also used to communicate with the pmic on the A80, and is
>> documented in the A80 user manual.
>>
>> This commit adds support for this based on the rsb driver from the allwinner
>> u-boot sources.
>>
>> Note: Not yet ready for upstream, code needs some significant cleanups.
>
> Confusing note.

Ugh, I forgot to remove that note after doing the cleanups, I'll remove it
from the version of the patch my personal tree :)

>
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>   arch/arm/cpu/armv7/sunxi/Makefile      |   1 +
>>   arch/arm/cpu/armv7/sunxi/rsb.c         | 158 +++++++++++++++++++++++++++++++++
>>   arch/arm/include/asm/arch-sunxi/cpu.h  |   3 +-
>>   arch/arm/include/asm/arch-sunxi/gpio.h |   2 +
>>   arch/arm/include/asm/arch-sunxi/prcm.h |   3 +-
>>   arch/arm/include/asm/arch-sunxi/rsb.h  |  55 ++++++++++++
>>   6 files changed, 220 insertions(+), 2 deletions(-)
>>   create mode 100644 arch/arm/cpu/armv7/sunxi/rsb.c
>>   create mode 100644 arch/arm/include/asm/arch-sunxi/rsb.h
>>
>> diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
>> index 1337b60..3e8975a 100644
>> --- a/arch/arm/cpu/armv7/sunxi/Makefile
>> +++ b/arch/arm/cpu/armv7/sunxi/Makefile
>> @@ -15,6 +15,7 @@ obj-y += pinmux.o
>>   obj-$(CONFIG_MACH_SUN6I)       += prcm.o
>>   obj-$(CONFIG_MACH_SUN8I)       += prcm.o
>>   obj-$(CONFIG_MACH_SUN6I)       += p2wi.o
>> +obj-$(CONFIG_MACH_SUN8I)       += rsb.o
>>   obj-$(CONFIG_MACH_SUN4I)       += clock_sun4i.o
>>   obj-$(CONFIG_MACH_SUN5I)       += clock_sun4i.o
>>   obj-$(CONFIG_MACH_SUN6I)       += clock_sun6i.o
>> diff --git a/arch/arm/cpu/armv7/sunxi/rsb.c b/arch/arm/cpu/armv7/sunxi/rsb.c
>> new file mode 100644
>> index 0000000..b72bb9d
>> --- /dev/null
>> +++ b/arch/arm/cpu/armv7/sunxi/rsb.c
>> @@ -0,0 +1,158 @@
>> +/*
>> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
>> + *
>> + * Based on allwinner u-boot sources rsb code which is:
>> + * (C) Copyright 2007-2013
>> + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
>> + * lixiang <lixiang@allwinnertech.com>
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <errno.h>
>> +#include <asm/arch/cpu.h>
>> +#include <asm/arch/gpio.h>
>> +#include <asm/arch/prcm.h>
>> +#include <asm/arch/rsb.h>
>> +
>> +static void rsb_cfg_io(void)
>> +{
>> +       sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL0_R_RSB_SCK);
>> +       sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL1_R_RSB_SDA);
>> +       sunxi_gpio_set_pull(SUNXI_GPL(0), 1);
>> +       sunxi_gpio_set_pull(SUNXI_GPL(1), 1);
>> +       sunxi_gpio_set_drv(SUNXI_GPL(0), 2);
>> +       sunxi_gpio_set_drv(SUNXI_GPL(1), 2);
>> +}
>> +
>> +static void rsb_set_clk(void)
>> +{
>> +       struct sunxi_rsb_reg * const rsb =
>> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
>> +       u32 div = 0;
>> +       u32 cd_odly = 0;
>> +
>> +       /* Source is Hosc24M, set RSB clk to 3Mhz */
>> +       div = 24000000 / 3000000 / 2 - 1;
>> +       cd_odly = div >> 1;
>> +       if (!cd_odly)
>> +               cd_odly = 1;
>> +
>> +       writel((cd_odly << 8) | div, &rsb->ccr);
>> +}
>> +
>> +void rsb_init(void)
>> +{
>> +       struct sunxi_rsb_reg * const rsb =
>> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
>> +
>> +       rsb_cfg_io();
>> +
>> +       /* Enable RSB and PIO clk, and de-assert their resets */
>> +       prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB);
>> +
>> +       writel(RSB_CTRL_SOFT_RST, &rsb->ctrl);
>
> Do we need a small delay here for the device to finish reset?

Maybe, this (no delay) is what the allwinner code was doing, and it
seems to work fine ...

>
>> +       rsb_set_clk();
>> +}
>> +
>> +static int rsb_await_trans(void)
>> +{
>> +       struct sunxi_rsb_reg * const rsb =
>> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
>> +       unsigned long tmo = timer_get_us() + 1000000;
>> +       u32 stat;
>> +       int ret;
>> +
>> +       while (1) {
>> +               stat = readl(&rsb->stat);
>> +               if (stat & RSB_STAT_LBSY_INT) {
>> +                       ret = -EBUSY;
>> +                       break;
>> +               }
>> +               if (stat & RSB_STAT_TERR_INT) {
>> +                       ret = -EIO;
>> +                       break;
>> +               }
>> +               if (stat & RSB_STAT_TOVER_INT) {
>> +                       ret = 0;
>> +                       break;
>> +               }
>> +               if (timer_get_us() > tmo) {
>> +                       ret = -ETIME;
>> +                       break;
>> +               }
>> +       }
>> +       writel(stat, &rsb->stat); /* Clear status bits */
>> +
>> +       return ret;
>> +}
>> +
>> +int rsb_set_device_mode(u32 device_mode_data)
>> +{
>> +       struct sunxi_rsb_reg * const rsb =
>> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
>> +       unsigned long tmo = timer_get_us() + 1000000;
>> +
>> +       writel(RSB_DMCR_DEVICE_MODE_START | device_mode_data, &rsb->dmcr);
>> +
>> +       while (readl(&rsb->dmcr) & RSB_DMCR_DEVICE_MODE_START) {
>> +               if (timer_get_us() > tmo)
>> +                       return -ETIME;
>> +       }
>> +
>> +       return rsb_await_trans();
>> +}
>> +
>> +static int rsb_do_trans(void)
>> +{
>> +       struct sunxi_rsb_reg * const rsb =
>> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
>> +
>> +       setbits_le32(&rsb->ctrl, RSB_CTRL_START_TRANS);
>> +       return rsb_await_trans();
>> +}
>> +
>> +int rsb_set_device_address(u16 device_addr, u16 runtime_addr)
>> +{
>> +       struct sunxi_rsb_reg * const rsb =
>> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
>> +
>> +       writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr) |
>> +              RSB_DEVADDR_DEVICE_ADDR(device_addr), &rsb->devaddr);
>> +       writel(RSB_CMD_SET_RTSADDR, &rsb->cmd);
>> +
>> +       return rsb_do_trans();
>> +}
>> +
>> +int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data)
>> +{
>> +       struct sunxi_rsb_reg * const rsb =
>> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
>> +
>> +       writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr);
>> +       writel(reg_addr, &rsb->addr);
>> +       writel(data, &rsb->data);
>> +       writel(RSB_CMD_BYTE_WRITE, &rsb->cmd);
>> +
>> +       return rsb_do_trans();
>> +}
>> +
>> +int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data)
>> +{
>> +       struct sunxi_rsb_reg * const rsb =
>> +               (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;
>> +       int ret;
>> +
>> +       writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr);
>> +       writel(reg_addr, &rsb->addr);
>> +       writel(RSB_CMD_BYTE_READ, &rsb->cmd);
>> +
>> +       ret = rsb_do_trans();
>> +       if (ret)
>> +               return ret;
>> +
>> +       *data = readl(&rsb->data) & 0xff;
>> +
>> +       return 0;
>> +}
>> diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
>> index 9500262..49c1614 100644
>> --- a/arch/arm/include/asm/arch-sunxi/cpu.h
>> +++ b/arch/arm/include/asm/arch-sunxi/cpu.h
>> @@ -128,7 +128,8 @@
>>   #define SUN6I_CPUCFG_BASE              0x01f01c00
>>   #define SUNXI_R_UART_BASE              0x01f02800
>>   #define SUNXI_R_PIO_BASE               0x01f02c00
>> -#define SUNXI_P2WI_BASE                        0x01f03400
>> +#define SUNXI_P2WI_BASE                        0x01f03400      /* on sun6i */
>> +#define SUNXI_RSB_BASE                 0x01f03400      /* on sun8i */
>
> Maybe we just use SUN6I_ SUN8I_ prefixes?
> The base address will be different on sun9i.
>
>>
>>   /* CoreSight Debug Module */
>>   #define SUNXI_CSDM_BASE                        0x3f500000
>> diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
>> index 9f972ce..6623f15 100644
>> --- a/arch/arm/include/asm/arch-sunxi/gpio.h
>> +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
>> @@ -176,6 +176,8 @@ enum sunxi_gpio_number {
>>   #define SUN6I_GPL0_R_P2WI_SCK  3
>>   #define SUN6I_GPL1_R_P2WI_SDA  3
>>
>> +#define SUN8I_GPL0_R_RSB_SCK   2
>> +#define SUN8I_GPL1_R_RSB_SDA   2
>>   #define SUN8I_GPL2_R_UART_TX   2
>>   #define SUN8I_GPL3_R_UART_RX   2
>>
>> diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
>> index 88de1ff..82ed541 100644
>> --- a/arch/arm/include/asm/arch-sunxi/prcm.h
>> +++ b/arch/arm/include/asm/arch-sunxi/prcm.h
>> @@ -50,7 +50,8 @@
>>   #define PRCM_APB0_GATE_PIO (0x1 << 0)
>>   #define PRCM_APB0_GATE_IR (0x1 << 1)
>>   #define PRCM_APB0_GATE_TIMER01 (0x1 << 2)
>> -#define PRCM_APB0_GATE_P2WI (0x1 << 3)
>> +#define PRCM_APB0_GATE_P2WI (0x1 << 3)         /* sun6i */
>> +#define PRCM_APB0_GATE_RSB (0x1 << 3)          /* sun8i */
>>   #define PRCM_APB0_GATE_UART (0x1 << 4)
>>   #define PRCM_APB0_GATE_1WIRE (0x1 << 5)
>>   #define PRCM_APB0_GATE_I2C (0x1 << 6)
>> diff --git a/arch/arm/include/asm/arch-sunxi/rsb.h b/arch/arm/include/asm/arch-sunxi/rsb.h
>> new file mode 100644
>> index 0000000..95a595a
>> --- /dev/null
>> +++ b/arch/arm/include/asm/arch-sunxi/rsb.h
>> @@ -0,0 +1,55 @@
>> +/*
>> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
>> + *
>> + * Based on allwinner u-boot sources rsb code which is:
>> + * (C) Copyright 2007-2013
>> + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
>> + * lixiang <lixiang@allwinnertech.com>
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + */
>> +
>> +#ifndef __SUNXI_RSB_H
>> +#define __SUNXI_RSB_H
>> +
>> +#include <common.h>
>> +#include <asm/io.h>
>> +
>> +struct sunxi_rsb_reg {
>> +       u32 ctrl;       /* 0x00 */
>> +       u32 ccr;        /* 0x04 */
>> +       u32 inte;       /* 0x08 */
>> +       u32 stat;       /* 0x0c */
>> +       u32 addr;       /* 0x10 */
>> +       u8 res0[8];     /* 0x14 */
>> +       u32 data;       /* 0x1c */
>> +       u8 res1[4];     /* 0x20 */
>> +       u32 lcr;        /* 0x24 */
>> +       u32 dmcr;       /* 0x28 */
>> +       u32 cmd;        /* 0x2c */
>> +       u32 devaddr;    /* 0x30 */
>> +};
>> +
>> +#define RSB_CTRL_SOFT_RST              (1 << 0)
>> +#define RSB_CTRL_START_TRANS           (1 << 7)
>> +
>> +#define RSB_STAT_TOVER_INT             (1 << 0)
>> +#define RSB_STAT_TERR_INT              (1 << 1)
>> +#define RSB_STAT_LBSY_INT              (1 << 2)
>> +
>> +#define RSB_DMCR_DEVICE_MODE_START     (1 << 31)
>> +
>> +#define RSB_CMD_BYTE_WRITE             0x4e
>> +#define RSB_CMD_BYTE_READ              0x8b
>> +#define RSB_CMD_SET_RTSADDR            0xe8
>> +
>> +#define RSB_DEVADDR_RUNTIME_ADDR(x)    ((x) << 16)
>> +#define RSB_DEVADDR_DEVICE_ADDR(x)     ((x) << 0)
>> +
>> +void rsb_init(void);
>> +int rsb_set_device_mode(u32 device_mode_data);
>> +int rsb_set_device_address(u16 device_addr, u16 runtime_addr);
>> +int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data);
>> +int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data);
>> +
>> +#endif
>> --
>> 2.1.0
>
> The rest looks good. Thanks!

Regards,

Hans

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

* [U-Boot] [PATCH 03/14] sunxi: axp221: Add axp223 support
  2014-12-17  2:34   ` Chen-Yu Tsai
@ 2014-12-18 10:44     ` Hans de Goede
  0 siblings, 0 replies; 54+ messages in thread
From: Hans de Goede @ 2014-12-18 10:44 UTC (permalink / raw)
  To: u-boot

Hi,

On 17-12-14 03:34, Chen-Yu Tsai wrote:
> On Wed, Dec 17, 2014 at 4:31 AM, Hans de Goede <hdegoede@redhat.com> wrote:
>> The axp223 appears to be the same as the axp221, except that it uses the
>> rsb to communicate rather then the p2wi. At least all the registers we use
>> are 100% the same.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>   arch/arm/cpu/armv7/sunxi/cpu_info.c |  2 +-
>>   drivers/power/Kconfig               |  8 ++--
>>   drivers/power/axp221.c              | 88 ++++++++++++++++++++++++++++---------
>>   include/axp221.h                    |  4 ++
>>   4 files changed, 76 insertions(+), 26 deletions(-)
>>
>> diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c
>> index 7a3a4ca..b6cb9de 100644
>> --- a/arch/arm/cpu/armv7/sunxi/cpu_info.c
>> +++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c
>> @@ -76,7 +76,7 @@ int print_cpuinfo(void)
>>
>>   int sunxi_get_sid(unsigned int *sid)
>>   {
>> -#ifdef CONFIG_MACH_SUN6I
>> +#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
>>   #ifdef CONFIG_AXP221_POWER
>>          return axp221_get_sid(sid);
>>   #else
>> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
>> index 1ec7c0e..7373a79 100644
>> --- a/drivers/power/Kconfig
>> +++ b/drivers/power/Kconfig
>> @@ -1,10 +1,10 @@
>>   config AXP221_POWER
>> -       boolean "axp221 pmic support"
>> -       depends on MACH_SUN6I
>> +       boolean "axp221 / axp223 pmic support"
>> +       depends on MACH_SUN6I || MACH_SUN8I
>>          default y
>>          ---help---
>> -       Say y here to enable support for the axp221 pmic found on most sun6i
>> -       (A31) boards.
>> +       Say y here to enable support for the axp221 / axp223 pmic found on most
>> +       sun6i (A31) / sun8i (A23) boards.
>>
>>   config AXP221_DLDO1_VOLT
>>          int "axp221 dldo1 voltage"
>> diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c
>> index 826567a..717adad 100644
>> --- a/drivers/power/axp221.c
>> +++ b/drivers/power/axp221.c
>> @@ -1,4 +1,10 @@
>>   /*
>> + * AXP221 and AXP223 driver
>> + *
>> + * IMPORTANT when making changes to this file check that the registers
>> + * used are the same for the axp221 and axp223.
>> + *
>> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
>>    * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
>>    *
>>    * SPDX-License-Identifier:    GPL-2.0+
>> @@ -7,8 +13,50 @@
>>   #include <common.h>
>>   #include <errno.h>
>>   #include <asm/arch/p2wi.h>
>> +#include <asm/arch/rsb.h>
>>   #include <axp221.h>
>>
>> +/*
>> + * The axp221 uses the p2wi bus, the axp223 is identical (for all registers
>> + * used sofar) but uses the rsb bus. These functions abstract this.
>> + */
>> +static int pmic_bus_init(void)
>> +{
>> +#ifdef CONFIG_MACH_SUN6I
>> +       p2wi_init();
>> +       return p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
>> +                                       AXP221_INIT_DATA);
>> +#else
>> +       int ret;
>> +
>> +       rsb_init();
>> +
>> +       ret = rsb_set_device_mode(AXP223_DEVICE_MODE_DATA);
>> +       if (ret)
>> +               return ret;
>> +
>> +       return rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
>> +#endif
>> +}
>> +
>> +static int pmic_bus_read(const u8 addr, u8 *data)
>> +{
>> +#ifdef CONFIG_MACH_SUN6I
>> +       return p2wi_read(addr, data);
>> +#else
>> +       return rsb_read(AXP223_RUNTIME_ADDR, addr, data);
>> +#endif
>> +}
>> +
>> +static int pmic_bus_write(const u8 addr, u8 data)
>> +{
>> +#ifdef CONFIG_MACH_SUN6I
>> +       return p2wi_write(addr, data);
>> +#else
>> +       return rsb_write(AXP223_RUNTIME_ADDR, addr, data);
>> +#endif
>> +}
>> +
>>   static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div)
>>   {
>>          if (mvolt < min)
>> @@ -24,12 +72,12 @@ static int axp221_setbits(u8 reg, u8 bits)
>>          int ret;
>>          u8 val;
>>
>> -       ret = p2wi_read(reg, &val);
>> +       ret = pmic_bus_read(reg, &val);
>>          if (ret)
>>                  return ret;
>>
>>          val |= bits;
>> -       return p2wi_write(reg, val);
>> +       return pmic_bus_write(reg, val);
>>   }
>>
>>   int axp221_set_dcdc1(unsigned int mvolt)
>> @@ -37,7 +85,7 @@ int axp221_set_dcdc1(unsigned int mvolt)
>>          int ret;
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100);
>>
>> -       ret = p2wi_write(AXP221_DCDC1_CTRL, cfg);
>> +       ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg);
>>          if (ret)
>>                  return ret;
>>
>> @@ -49,28 +97,28 @@ int axp221_set_dcdc2(unsigned int mvolt)
>>   {
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
>>
>> -       return p2wi_write(AXP221_DCDC2_CTRL, cfg);
>> +       return pmic_bus_write(AXP221_DCDC2_CTRL, cfg);
>>   }
>>
>>   int axp221_set_dcdc3(unsigned int mvolt)
>>   {
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20);
>>
>> -       return p2wi_write(AXP221_DCDC3_CTRL, cfg);
>> +       return pmic_bus_write(AXP221_DCDC3_CTRL, cfg);
>>   }
>>
>>   int axp221_set_dcdc4(unsigned int mvolt)
>>   {
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20);
>>
>> -       return p2wi_write(AXP221_DCDC4_CTRL, cfg);
>> +       return pmic_bus_write(AXP221_DCDC4_CTRL, cfg);
>>   }
>>
>>   int axp221_set_dcdc5(unsigned int mvolt)
>>   {
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50);
>>
>> -       return p2wi_write(AXP221_DCDC5_CTRL, cfg);
>> +       return pmic_bus_write(AXP221_DCDC5_CTRL, cfg);
>>   }
>>
>>   int axp221_set_dldo1(unsigned int mvolt)
>> @@ -78,7 +126,7 @@ int axp221_set_dldo1(unsigned int mvolt)
>>          int ret;
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>>
>> -       ret = p2wi_write(AXP221_DLDO1_CTRL, cfg);
>> +       ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg);
>>          if (ret)
>>                  return ret;
>>
>> @@ -91,7 +139,7 @@ int axp221_set_dldo2(unsigned int mvolt)
>>          int ret;
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>>
>> -       ret = p2wi_write(AXP221_DLDO2_CTRL, cfg);
>> +       ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg);
>>          if (ret)
>>                  return ret;
>>
>> @@ -104,7 +152,7 @@ int axp221_set_dldo3(unsigned int mvolt)
>>          int ret;
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>>
>> -       ret = p2wi_write(AXP221_DLDO3_CTRL, cfg);
>> +       ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg);
>>          if (ret)
>>                  return ret;
>>
>> @@ -117,7 +165,7 @@ int axp221_set_dldo4(unsigned int mvolt)
>>          int ret;
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>>
>> -       ret = p2wi_write(AXP221_DLDO4_CTRL, cfg);
>> +       ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg);
>>          if (ret)
>>                  return ret;
>>
>> @@ -130,7 +178,7 @@ int axp221_set_aldo1(unsigned int mvolt)
>>          int ret;
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>>
>> -       ret = p2wi_write(AXP221_ALDO1_CTRL, cfg);
>> +       ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg);
>>          if (ret)
>>                  return ret;
>>
>> @@ -143,7 +191,7 @@ int axp221_set_aldo2(unsigned int mvolt)
>>          int ret;
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>>
>> -       ret = p2wi_write(AXP221_ALDO2_CTRL, cfg);
>> +       ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg);
>>          if (ret)
>>                  return ret;
>>
>> @@ -156,7 +204,7 @@ int axp221_set_aldo3(unsigned int mvolt)
>>          int ret;
>>          u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100);
>>
>> -       ret = p2wi_write(AXP221_ALDO3_CTRL, cfg);
>> +       ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg);
>>          if (ret)
>>                  return ret;
>>
>> @@ -169,13 +217,11 @@ int axp221_init(void)
>>          u8 axp_chip_id;
>>          int ret;
>>
>> -       p2wi_init();
>> -       ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
>> -                                      AXP221_INIT_DATA);
>> +       ret = pmic_bus_init();
>>          if (ret)
>>                  return ret;
>>
>> -       ret = p2wi_read(AXP221_CHIP_ID, &axp_chip_id);
>> +       ret = pmic_bus_read(AXP221_CHIP_ID, &axp_chip_id);
>>          if (ret)
>>                  return ret;
>>
>> @@ -194,17 +240,17 @@ int axp221_get_sid(unsigned int *sid)
>>          if (ret)
>>                  return ret;
>>
>> -       ret = p2wi_write(AXP221_PAGE, 1);
>> +       ret = pmic_bus_write(AXP221_PAGE, 1);
>>          if (ret)
>>                  return ret;
>>
>>          for (i = 0; i < 16; i++) {
>> -               ret = p2wi_read(AXP221_SID + i, &dest[i]);
>> +               ret = pmic_bus_read(AXP221_SID + i, &dest[i]);
>>                  if (ret)
>>                          return ret;
>>          }
>>
>> -       p2wi_write(AXP221_PAGE, 0);
>> +       pmic_bus_write(AXP221_PAGE, 0);
>>
>>          for (i = 0; i < 4; i++)
>>                  sid[i] = be32_to_cpu(sid[i]);
>> diff --git a/include/axp221.h b/include/axp221.h
>> index db219c6..10d35e1 100644
>> --- a/include/axp221.h
>> +++ b/include/axp221.h
>> @@ -10,6 +10,10 @@
>>   #define AXP221_CTRL_ADDR 0x3e
>>   #define AXP221_INIT_DATA 0x3e
>>
>> +#define AXP223_DEVICE_ADDR 0x3a3
>> +#define AXP223_RUNTIME_ADDR 0x2d
>> +#define AXP223_DEVICE_MODE_DATA 0x7c3e00
>> +
>>   /* Page 0 addresses */
>>   #define AXP221_CHIP_ID         0x03
>>   #define AXP221_OUTPUT_CTRL1    0x10
>> --
>> 2.1.0
>>
>
> git am reports:
>
> Applying patch #422068 using 'git am'
> Description: [U-Boot,03/14] sunxi: axp221: Add axp223 support
> Applying: sunxi: axp221: Add axp223 support
> /home/wens/sunxi/u-boot/.git/rebase-apply/patch:50: trailing whitespace.
>   *
> /home/wens/sunxi/u-boot/.git/rebase-apply/patch:76: trailing whitespace.
>
> warning: 2 lines add whitespace errors.

Fixed in my personal tree.

Regards,

Hans

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

* [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support
  2014-12-16 20:31 ` [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support Hans de Goede
@ 2014-12-18 11:12   ` Chen-Yu Tsai
  2014-12-18 19:17   ` Ian Campbell
  2014-12-19 10:20   ` Siarhei Siamashka
  2 siblings, 0 replies; 54+ messages in thread
From: Chen-Yu Tsai @ 2014-12-18 11:12 UTC (permalink / raw)
  To: u-boot

On Wed, Dec 17, 2014 at 4:31 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> Based on the register / dram_para headers from the Allwinner u-boot / linux
> sources + the init sequences from boot0.
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  arch/arm/cpu/armv7/sunxi/Makefile             |   1 +
>  arch/arm/cpu/armv7/sunxi/board.c              |   3 +-
>  arch/arm/cpu/armv7/sunxi/dram_sun8i.c         | 340 ++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h |   4 +
>  arch/arm/include/asm/arch-sunxi/dram.h        |   2 +
>  arch/arm/include/asm/arch-sunxi/dram_sun8i.h  | 266 ++++++++++++++++++++
>  board/sunxi/Kconfig                           |   3 +-
>  configs/Ippo_q8h_v5_defconfig                 |  17 +-
>  include/configs/sun8i.h                       |   2 +
>  9 files changed, 631 insertions(+), 7 deletions(-)
>  create mode 100644 arch/arm/cpu/armv7/sunxi/dram_sun8i.c
>  create mode 100644 arch/arm/include/asm/arch-sunxi/dram_sun8i.h
>
> diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
> index 3e8975a..1e89937 100644
> --- a/arch/arm/cpu/armv7/sunxi/Makefile
> +++ b/arch/arm/cpu/armv7/sunxi/Makefile
> @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_SUN4I)      += dram_sun4i.o
>  obj-$(CONFIG_MACH_SUN5I)       += dram_sun4i.o
>  obj-$(CONFIG_MACH_SUN6I)       += dram_sun6i.o
>  obj-$(CONFIG_MACH_SUN7I)       += dram_sun4i.o
> +obj-$(CONFIG_MACH_SUN8I)       += dram_sun8i.o
>  ifdef CONFIG_SPL_FEL
>  obj-y  += start.o
>  endif
> diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
> index 9b3e80c..bc98c56 100644
> --- a/arch/arm/cpu/armv7/sunxi/board.c
> +++ b/arch/arm/cpu/armv7/sunxi/board.c
> @@ -114,7 +114,8 @@ void reset_cpu(ulong addr)
>  /* do some early init */
>  void s_init(void)
>  {
> -#if defined CONFIG_SPL_BUILD && defined CONFIG_MACH_SUN6I
> +#if defined CONFIG_SPL_BUILD && \
> +               (defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I)
>         /* Magic (undocmented) value taken from boot0, without this DRAM
>          * access gets messed up (seems cache related) */
>         setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun8i.c b/arch/arm/cpu/armv7/sunxi/dram_sun8i.c
> new file mode 100644
> index 0000000..3736fd1
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun8i.c
> @@ -0,0 +1,340 @@
> +/*
> + * Sun8i platform dram controller init.
> + *
> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +/*
> + * Note this code uses a lot of magic hex values, that is because this code
> + * simply replays the init sequence as done by the Allwinner boot0 code, so
> + * we do not know what these values mean. There are no symbolic constants for
> + * these magic values, since we do not know how to name them and making up
> + * names for them is not useful.
> + */
> +
> +#include <common.h>
> +#include <errno.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/dram.h>
> +#include <asm/arch/prcm.h>
> +
> +static const struct dram_para dram_para = {
> +       .clock = CONFIG_DRAM_CLK,
> +       .type = 3,
> +       .zq = CONFIG_DRAM_ZQ,
> +       .odt_en = 1,
> +       .para1 = 0, /* not used (only used when tpr13 bit 31 is set */
> +       .para2 = 0, /* not used (only used when tpr13 bit 31 is set */
> +       .mr0 = 6736,
> +       .mr1 = 4,
> +       .mr2 = 16,
> +       .mr3 = 0,
> +       /* tpr0 - 10 contain timing constants or-ed together in u32 vals */
> +       .tpr0 = 0x2ab83def,
> +       .tpr1 = 0x18082356,
> +       .tpr2 = 0x00034156,
> +       .tpr3 = 0x448c5533,
> +       .tpr4 = 0x08010d00,
> +       .tpr5 = 0x0340b20f,
> +       .tpr6 = 0x20d118cc,
> +       .tpr7 = 0x14062485,
> +       .tpr8 = 0x220d1d52,
> +       .tpr9 = 0x1e078c22,
> +       .tpr10 = 0x3c,
> +       .tpr11 = 0, /* not used */
> +       .tpr12 = 0, /* not used */
> +       .tpr13 = 0x30000,
> +};
> +
> +static void mctl_sys_init(void)
> +{
> +       struct sunxi_ccm_reg * const ccm =
> +               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> +
> +       /* enable pll5, note the divide by 2 is deliberate! */
> +       clock_set_pll5(dram_para.clock * 1000000 / 2, 1, 2,
> +                      dram_para.tpr13 & 0x40000);
> +
> +       /* deassert ahb mctl reset */
> +       setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
> +
> +       /* enable ahb mctl clock */
> +       setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
> +}
> +
> +static void mctl_apply_odt_correction(u32 *reg, int correction)
> +{
> +       int val;
> +
> +       val = (readl(reg) >> 8) & 0xff;
> +       val += correction;
> +
> +       /* clamp */
> +       if (val < 0)
> +               val = 0;
> +       else if (val > 255)
> +               val = 255;
> +
> +       clrsetbits_le32(reg, 0xff00, val << 8);
> +}
> +
> +static void mctl_init(u32 *bus_width)
> +{
> +       struct sunxi_ccm_reg * const ccm =
> +               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> +       struct sunxi_mctl_com_reg * const mctl_com =
> +               (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
> +       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 correction;
> +
> +       if (dram_para.tpr13 & 0x20)
> +               writel(0x40b, &mctl_phy->dcr);
> +       else
> +               writel(0x1000040b, &mctl_phy->dcr);
> +
> +       if (dram_para.clock >= 480)
> +               writel(0x5c000, &mctl_phy->dllgcr);
> +       else
> +               writel(0xdc000, &mctl_phy->dllgcr);
> +
> +       writel(0x0a003e3f, &mctl_phy->pgcr0);
> +       writel(0x03008421, &mctl_phy->pgcr1);
> +
> +       writel(dram_para.mr0, &mctl_phy->mr0);
> +       writel(dram_para.mr1, &mctl_phy->mr1);
> +       writel(dram_para.mr2, &mctl_phy->mr2);
> +       writel(dram_para.mr3, &mctl_phy->mr3);
> +
> +       if (!(dram_para.tpr13 & 0x10000)) {
> +               clrsetbits_le32(&mctl_phy->dx0gcr, 0x3800, 0x2000);
> +               clrsetbits_le32(&mctl_phy->dx1gcr, 0x3800, 0x2000);
> +       }
> +
> +       /*
> +        * All the masking and shifting below converts what I assume are DDR
> +        * timing constants from Allwinner dram_para tpr format to the actual
> +        * timing registers format.
> +        */
> +
> +       writel((dram_para.tpr0 & 0x000fffff), &mctl_phy->ptr2);
> +       writel((dram_para.tpr1 & 0x1fffffff), &mctl_phy->ptr3);
> +       writel((dram_para.tpr0 & 0x3ff00000) >> 2 |
> +              (dram_para.tpr2 & 0x0003ffff), &mctl_phy->ptr4);
> +
> +       writel(dram_para.tpr3, &mctl_phy->dtpr0);
> +       writel(dram_para.tpr4, &mctl_phy->dtpr2);
> +
> +       writel(0x01000081, &mctl_phy->dtcr);
> +
> +       if (dram_para.clock <= 240 || !(dram_para.odt_en & 0x01)) {
> +               clrbits_le32(&mctl_phy->dx0gcr, 0x600);
> +               clrbits_le32(&mctl_phy->dx1gcr, 0x600);
> +       }
> +       if (dram_para.clock <= 240) {
> +               writel(0, &mctl_phy->odtcr);
> +               writel(0, &mctl_ctl->odtmap);
> +       }
> +
> +       writel(((dram_para.tpr5 & 0x0f00) << 12) |
> +              ((dram_para.tpr5 & 0x00f8) <<  9) |
> +              ((dram_para.tpr5 & 0x0007) <<  8),
> +              &mctl_ctl->rfshctl0);
> +
> +       writel(((dram_para.tpr5 & 0x0003f000) << 12) |
> +              ((dram_para.tpr5 & 0x00fc0000) >>  2) |
> +              ((dram_para.tpr5 & 0x3f000000) >> 16) |
> +              ((dram_para.tpr6 & 0x0000003f) >>  0),
> +              &mctl_ctl->dramtmg0);
> +
> +       writel(((dram_para.tpr6 & 0x000007c0) << 10) |
> +              ((dram_para.tpr6 & 0x0000f800) >> 3) |
> +              ((dram_para.tpr6 & 0x003f0000) >> 16),
> +              &mctl_ctl->dramtmg1);
> +
> +       writel(((dram_para.tpr6 & 0x0fc00000) << 2) |
> +              ((dram_para.tpr7 & 0x0000001f) << 16) |
> +              ((dram_para.tpr7 & 0x000003e0) << 3) |
> +              ((dram_para.tpr7 & 0x0000fc00) >> 10),
> +              &mctl_ctl->dramtmg2);
> +
> +       writel(((dram_para.tpr7 & 0x03ff0000) >> 16) |
> +              ((dram_para.tpr6 & 0xf0000000) >> 16),
> +              &mctl_ctl->dramtmg3);
> +
> +       writel(((dram_para.tpr7 & 0x3c000000) >> 2 ) |
> +              ((dram_para.tpr8 & 0x00000007) << 16) |
> +              ((dram_para.tpr8 & 0x00000038) << 5) |
> +              ((dram_para.tpr8 & 0x000003c0) >> 6),
> +              &mctl_ctl->dramtmg4);
> +
> +       writel(((dram_para.tpr8 & 0x00003c00) << 14) |
> +              ((dram_para.tpr8 & 0x0003c000) <<  2) |
> +              ((dram_para.tpr8 & 0x00fc0000) >> 10) |
> +              ((dram_para.tpr8 & 0x0f000000) >> 24),
> +              &mctl_ctl->dramtmg5);
> +
> +       writel(0x00000008, &mctl_ctl->dramtmg8);
> +
> +       writel(((dram_para.tpr8 & 0xf0000000) >> 4) |
> +              ((dram_para.tpr9 & 0x00007c00) << 6) |
> +              ((dram_para.tpr9 & 0x000003e0) << 3) |
> +              ((dram_para.tpr9 & 0x0000001f) >> 0),
> +              &mctl_ctl->pitmg0);
> +
> +       setbits_le32(&mctl_ctl->pitmg1, 0x80000);
> +
> +       writel(((dram_para.tpr9 & 0x003f8000) << 9) | 0x2001,
> +              &mctl_ctl->sched);
> +
> +       writel((dram_para.mr0 << 16) | dram_para.mr1, &mctl_ctl->init3);
> +       writel((dram_para.mr2 << 16) | dram_para.mr3, &mctl_ctl->init4);
> +
> +       writel(0x00000000, &mctl_ctl->pimisc);
> +       writel(0x80000000, &mctl_ctl->upd0);
> +
> +       writel(((dram_para.tpr9  & 0xffc00000) >> 22) |
> +              ((dram_para.tpr10 & 0x00000fff) << 16),
> +              &mctl_ctl->rfshtmg);
> +
> +       if (dram_para.tpr13 & 0x20)
> +               writel(0x01040001, &mctl_ctl->mstr);
> +       else
> +               writel(0x01040401, &mctl_ctl->mstr);
> +
> +       if (!(dram_para.tpr13 & 0x20000)) {
> +               writel(0x00000002, &mctl_ctl->pwrctl);
> +               writel(0x00008001, &mctl_ctl->pwrtmg);
> +       }
> +
> +       writel(0x00000001, &mctl_ctl->rfshctl3);
> +       writel(0x00000001, &mctl_ctl->pimisc);
> +
> +       /* deassert dram_clk_cfg reset */
> +       setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
> +
> +       setbits_le32(&mctl_com->ccr, 0x80000);
> +
> +       /* zq stuff */
> +       writel((dram_para.zq >> 8) & 0xff, &mctl_phy->zqcr1);
> +
> +       writel(0x00000003, &mctl_phy->pir);
> +       udelay(10);
> +       mctl_await_completion(&mctl_phy->pgsr0, 0x09, 0x09);
> +
> +       writel(readl(&mctl_phy->zqsr0) | 0x10000000, &mctl_phy->zqcr2);
> +       writel(dram_para.zq & 0xff, &mctl_phy->zqcr1);
> +
> +       /* A23-v1.0 SDK uses 0xfdf3, A23-v2.0 SDK uses 0x5f3 */
> +       writel(0x000005f3, &mctl_phy->pir);
> +       udelay(10);
> +       mctl_await_completion(&mctl_phy->pgsr0, 0x03, 0x03);
> +
> +       if (readl(&mctl_phy->dx1gsr0) & 0x1000000) {
> +               *bus_width = 8;
> +               writel(0, &mctl_phy->dx1gcr);
> +               writel(dram_para.zq & 0xff, &mctl_phy->zqcr1);
> +               writel(0x5f3, &mctl_phy->pir);
> +               udelay(10000);
> +               setbits_le32(&mctl_ctl->mstr, 0x1000);
> +       } else
> +               *bus_width = 16;
> +
> +       correction = (dram_para.odt_en >> 8) & 0xff;
> +       if (correction) {
> +               if (dram_para.odt_en & 0x80000000)
> +                       correction = -correction;
> +
> +               mctl_apply_odt_correction(&mctl_phy->dx0lcdlr1, correction);
> +               mctl_apply_odt_correction(&mctl_phy->dx1lcdlr1, correction);
> +       }
> +
> +       mctl_await_completion(&mctl_ctl->statr, 0x01, 0x01);
> +
> +       writel(0x08003e3f, &mctl_phy->pgcr0);
> +       writel(0x00000000, &mctl_ctl->rfshctl3);
> +}
> +
> +unsigned long sunxi_dram_init(void)
> +{
> +       struct sunxi_mctl_com_reg * const mctl_com =
> +               (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
> +       const u32 columns = 13;
> +       u32 bus, bus_width, offset, page_size, rows;
> +
> +       mctl_sys_init();
> +       mctl_init(&bus_width);
> +
> +       if (bus_width == 16) {
> +               page_size = 8;
> +               bus = 1;
> +       } else {
> +               page_size = 7;
> +               bus = 0;
> +       }
> +
> +       if (!(dram_para.tpr13 & 0x80000000)) {
> +               /* Detect and set rows */
> +               writel(0x000310f4 | MCTL_CR_PAGE_SIZE(page_size),
> +                      &mctl_com->cr);
> +               setbits_le32(&mctl_com->swonr, 0x0003ffff);
> +               mctl_mem_fill();
> +               for (rows = 11; rows < 16; rows++) {
> +                       offset = 1 << (rows + columns + bus);
> +                       if (mctl_mem_matches(offset))
> +                               break;
> +               }
> +               clrsetbits_le32(&mctl_com->cr, MCTL_CR_ROW_MASK,
> +                               MCTL_CR_ROW(rows));
> +       } else {
> +               rows = (dram_para.para1 >> 16) & 0xff;
> +               writel(((dram_para.para2 & 0x000000f0) << 11) |
> +                      ((rows - 1) << 4) |
> +                      ((dram_para.para1 & 0x0f000000) >> 22) |
> +                      0x31000 | MCTL_CR_PAGE_SIZE(page_size),
> +                      &mctl_com->cr);
> +               setbits_le32(&mctl_com->swonr, 0x0003ffff);
> +       }
> +
> +       /* Setup DRAM master priority? If this is left out things still work */
> +       writel(0x00000008, &mctl_com->mcr0_0);
> +       writel(0x0001000d, &mctl_com->mcr1_0);
> +       writel(0x00000004, &mctl_com->mcr0_1);
> +       writel(0x00000080, &mctl_com->mcr1_1);
> +       writel(0x00000004, &mctl_com->mcr0_2);
> +       writel(0x00000019, &mctl_com->mcr1_2);
> +       writel(0x00000004, &mctl_com->mcr0_3);
> +       writel(0x00000080, &mctl_com->mcr1_3);
> +       writel(0x00000004, &mctl_com->mcr0_4);
> +       writel(0x01010040, &mctl_com->mcr1_4);
> +       writel(0x00000004, &mctl_com->mcr0_5);
> +       writel(0x0001002f, &mctl_com->mcr1_5);
> +       writel(0x00000004, &mctl_com->mcr0_6);
> +       writel(0x00010020, &mctl_com->mcr1_6);
> +       writel(0x00000004, &mctl_com->mcr0_7);
> +       writel(0x00010020, &mctl_com->mcr1_7);
> +       writel(0x00000008, &mctl_com->mcr0_8);
> +       writel(0x00000001, &mctl_com->mcr1_8);
> +       writel(0x00000008, &mctl_com->mcr0_9);
> +       writel(0x00000005, &mctl_com->mcr1_9);
> +       writel(0x00000008, &mctl_com->mcr0_10);
> +       writel(0x00000003, &mctl_com->mcr1_10);
> +       writel(0x00000008, &mctl_com->mcr0_11);
> +       writel(0x00000005, &mctl_com->mcr1_11);
> +       writel(0x00000008, &mctl_com->mcr0_12);
> +       writel(0x00000003, &mctl_com->mcr1_12);
> +       writel(0x00000008, &mctl_com->mcr0_13);
> +       writel(0x00000004, &mctl_com->mcr1_13);
> +       writel(0x00000008, &mctl_com->mcr0_14);
> +       writel(0x00000002, &mctl_com->mcr1_14);
> +       writel(0x00000008, &mctl_com->mcr0_15);
> +       writel(0x00000003, &mctl_com->mcr1_15);
> +       writel(0x00010138, &mctl_com->bwcr);
> +
> +       return 1 << (rows + columns + bus);
> +}
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> index 7d61216..45a199c 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> @@ -273,7 +273,11 @@ struct sunxi_ccm_reg {
>  #define CCM_HDMI_CTRL_DDC_GATE         (0x1 << 30)
>  #define CCM_HDMI_CTRL_GATE             (0x1 << 31)
>
> +#ifndef CONFIG_MACH_SUN8I
>  #define MBUS_CLK_DEFAULT               0x81000001 /* PLL6 / 2 */
> +#else
> +#define MBUS_CLK_DEFAULT               0x81000003 /* PLL6 / 4 */
> +#endif
>
>  #define CCM_PLL5_PATTERN               0xd1303333
>
> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> index a8a37d5..8d78029 100644
> --- a/arch/arm/include/asm/arch-sunxi/dram.h
> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> @@ -18,6 +18,8 @@
>  /* dram regs definition */
>  #if defined(CONFIG_MACH_SUN6I)
>  #include <asm/arch/dram_sun6i.h>
> +#elif defined(CONFIG_MACH_SUN8I)
> +#include <asm/arch/dram_sun8i.h>
>  #else
>  #include <asm/arch/dram_sun4i.h>
>  #endif
> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i.h
> new file mode 100644
> index 0000000..425cf37
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i.h
> @@ -0,0 +1,266 @@
> +/*
> + * Sun8i platform dram controller register and constant defines
> + *
> + * (C) Copyright 2007-2013
> + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
> + * CPL <cplanxy@allwinnertech.com>
> + * Jerry Wang <wangflord@allwinnertech.com>
> + *
> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#ifndef _SUNXI_DRAM_SUN8I_H
> +#define _SUNXI_DRAM_SUN8I_H
> +
> +struct dram_para {
> +       u32 clock;
> +       u32 type;
> +       u32 zq;
> +       u32 odt_en;
> +       u32 para1;
> +       u32 para2;
> +       u32 mr0;
> +       u32 mr1;
> +       u32 mr2;
> +       u32 mr3;
> +       u32 tpr0;
> +       u32 tpr1;
> +       u32 tpr2;
> +       u32 tpr3;
> +       u32 tpr4;
> +       u32 tpr5;
> +       u32 tpr6;
> +       u32 tpr7;
> +       u32 tpr8;
> +       u32 tpr9;
> +       u32 tpr10;
> +       u32 tpr11;
> +       u32 tpr12;
> +       u32 tpr13;
> +};
> +
> +struct sunxi_mctl_com_reg {
> +       u32 cr;                 /* 0x00 */
> +       u32 ccr;                /* 0x04 controller configuration register */
> +       u32 dbgcr;              /* 0x08 */
> +       u8 res0[0x4];           /* 0x0c */
> +       u32 mcr0_0;             /* 0x10 */
> +       u32 mcr1_0;             /* 0x14 */
> +       u32 mcr0_1;             /* 0x18 */
> +       u32 mcr1_1;             /* 0x1c */
> +       u32 mcr0_2;             /* 0x20 */
> +       u32 mcr1_2;             /* 0x24 */
> +       u32 mcr0_3;             /* 0x28 */
> +       u32 mcr1_3;             /* 0x2c */
> +       u32 mcr0_4;             /* 0x30 */
> +       u32 mcr1_4;             /* 0x34 */
> +       u32 mcr0_5;             /* 0x38 */
> +       u32 mcr1_5;             /* 0x3c */
> +       u32 mcr0_6;             /* 0x40 */
> +       u32 mcr1_6;             /* 0x44 */
> +       u32 mcr0_7;             /* 0x48 */
> +       u32 mcr1_7;             /* 0x4c */
> +       u32 mcr0_8;             /* 0x50 */
> +       u32 mcr1_8;             /* 0x54 */
> +       u32 mcr0_9;             /* 0x58 */
> +       u32 mcr1_9;             /* 0x5c */
> +       u32 mcr0_10;            /* 0x60 */
> +       u32 mcr1_10;            /* 0x64 */
> +       u32 mcr0_11;            /* 0x68 */
> +       u32 mcr1_11;            /* 0x6c */
> +       u32 mcr0_12;            /* 0x70 */
> +       u32 mcr1_12;            /* 0x74 */
> +       u32 mcr0_13;            /* 0x78 */
> +       u32 mcr1_13;            /* 0x7c */
> +       u32 mcr0_14;            /* 0x80 */
> +       u32 mcr1_14;            /* 0x84 */
> +       u32 mcr0_15;            /* 0x88 */
> +       u32 mcr1_15;            /* 0x8c */
> +       u32 bwcr;               /* 0x90 */
> +       u32 maer;               /* 0x94 */
> +       u8 res1[0x4];           /* 0x98 */
> +       u32 mcgcr;              /* 0x9c */
> +       u32 bwctr;              /* 0xa0 */
> +       u8 res2[0x4];           /* 0xa4 */
> +       u32 swonr;              /* 0xa8 */
> +       u32 swoffr;             /* 0xac */
> +};
> +
> +struct sunxi_mctl_ctl_reg {
> +       u32 mstr;               /* 0x00 */
> +       u32 statr;              /* 0x04 */
> +       u8 res0[0x08];          /* 0x08 */
> +       u32 mrctrl0;            /* 0x10 */
> +       u32 mrctrl1;            /* 0x14 */
> +       u32 mrstatr;            /* 0x18 */
> +       u8 res1[0x04];          /* 0x1c */
> +       u32 derateen;           /* 0x20 */
> +       u32 deratenint;         /* 0x24 */
> +       u8 res2[0x08];          /* 0x28 */
> +       u32 pwrctl;             /* 0x30 */
> +       u32 pwrtmg;             /* 0x34 */
> +       u8 res3[0x18];          /* 0x38 */
> +       u32 rfshctl0;           /* 0x50 */
> +       u32 rfshctl1;           /* 0x54 */
> +       u8 res4[0x8];           /* 0x58 */
> +       u32 rfshctl3;           /* 0x60 */
> +       u32 rfshtmg;            /* 0x64 */
> +       u8 res6[0x68];          /* 0x68 */
> +       u32 init0;              /* 0xd0 */
> +       u32 init1;              /* 0xd4 */
> +       u32 init2;              /* 0xd8 */
> +       u32 init3;              /* 0xdc */
> +       u32 init4;              /* 0xe0 */
> +       u32 init5;              /* 0xe4 */
> +       u8 res7[0x0c];          /* 0xe8 */
> +       u32 rankctl;            /* 0xf4 */
> +       u8 res8[0x08];          /* 0xf8 */
> +       u32 dramtmg0;           /* 0x100 */
> +       u32 dramtmg1;           /* 0x104 */
> +       u32 dramtmg2;           /* 0x108 */
> +       u32 dramtmg3;           /* 0x10c */
> +       u32 dramtmg4;           /* 0x110 */
> +       u32 dramtmg5;           /* 0x114 */
> +       u32 dramtmg6;           /* 0x118 */
> +       u32 dramtmg7;           /* 0x11c */
> +       u32 dramtmg8;           /* 0x120 */
> +       u8 res9[0x5c];          /* 0x124 */
> +       u32 zqctl0;             /* 0x180 */
> +       u32 zqctl1;             /* 0x184 */
> +       u32 zqctl2;             /* 0x188 */
> +       u32 zqstat;             /* 0x18c */
> +       u32 pitmg0;             /* 0x190 */
> +       u32 pitmg1;             /* 0x194 */
> +       u32 plpcfg0;            /* 0x198 */
> +       u8 res10[0x04];         /* 0x19c */
> +       u32 upd0;               /* 0x1a0 */
> +       u32 upd1;               /* 0x1a4 */
> +       u32 upd2;               /* 0x1a8 */
> +       u32 upd3;               /* 0x1ac */
> +       u32 pimisc;             /* 0x1b0 */
> +       u8 res11[0x1c];         /* 0x1b4 */
> +       u32 trainctl0;          /* 0x1d0 */
> +       u32 trainctl1;          /* 0x1d4 */
> +       u32 trainctl2;          /* 0x1d8 */
> +       u32 trainstat;          /* 0x1dc */
> +       u8 res12[0x60];         /* 0x1e0 */
> +       u32 odtcfg;             /* 0x240 */
> +       u32 odtmap;             /* 0x244 */
> +       u8 res13[0x08];         /* 0x248 */
> +       u32 sched;              /* 0x250 */
> +       u8 res14[0x04];         /* 0x254 */
> +       u32 perfshpr0;          /* 0x258 */
> +       u32 perfshpr1;          /* 0x25c */
> +       u32 perflpr0;           /* 0x260 */
> +       u32 perflpr1;           /* 0x264 */
> +       u32 perfwr0;            /* 0x268 */
> +       u32 perfwr1;            /* 0x26c */
> +};
> +
> +struct sunxi_mctl_phy_reg {
> +       u8 res0[0x04];          /* 0x00 */
> +       u32 pir;                /* 0x04 */
> +       u32 pgcr0;              /* 0x08 phy general configuration register */
> +       u32 pgcr1;              /* 0x0c phy general configuration register */
> +       u32 pgsr0;              /* 0x10 */
> +       u32 pgsr1;              /* 0x14 */
> +       u32 dllgcr;             /* 0x18 */
> +       u32 ptr0;               /* 0x1c */
> +       u32 ptr1;               /* 0x20 */
> +       u32 ptr2;               /* 0x24 */
> +       u32 ptr3;               /* 0x28 */
> +       u32 ptr4;               /* 0x2c */
> +       u32 acmdlr;             /* 0x30 */
> +       u32 acbdlr;             /* 0x34 */
> +       u32 aciocr;             /* 0x38 */
> +       u32 dxccr;              /* 0x3c DATX8 common configuration register */
> +       u32 dsgcr;              /* 0x40 dram system general config register */
> +       u32 dcr;                /* 0x44 */
> +       u32 dtpr0;              /* 0x48 dram timing parameters register 0 */
> +       u32 dtpr1;              /* 0x4c dram timing parameters register 1 */
> +       u32 dtpr2;              /* 0x50 dram timing parameters register 2 */
> +       u32 mr0;                /* 0x54 mode register 0 */
> +       u32 mr1;                /* 0x58 mode register 1 */
> +       u32 mr2;                /* 0x5c mode register 2 */
> +       u32 mr3;                /* 0x60 mode register 3 */
> +       u32 odtcr;              /* 0x64 */
> +       u32 dtcr;               /* 0x68 */
> +       u32 dtar0;              /* 0x6c data training address register 0 */
> +       u32 dtar1;              /* 0x70 data training address register 1 */
> +       u32 dtar2;              /* 0x74 data training address register 2 */
> +       u32 dtar3;              /* 0x78 data training address register 3 */
> +       u32 dtdr0;              /* 0x7c */
> +       u32 dtdr1;              /* 0x80 */
> +       u32 dtedr0;             /* 0x84 */
> +       u32 dtedr1;             /* 0x88 */
> +       u32 pgcr2;              /* 0x8c */
> +       u8 res1[0x70];          /* 0x90 */
> +       u32 bistrr;             /* 0x100 */
> +       u32 bistwcr;            /* 0x104 */
> +       u32 bistmskr0;          /* 0x108 */
> +       u32 bistmskr1;          /* 0x10c */
> +       u32 bistmskr2;          /* 0x110 */
> +       u32 bistlsr;            /* 0x114 */
> +       u32 bistar0;            /* 0x118 */
> +       u32 bistar1;            /* 0x11c */
> +       u32 bistar2;            /* 0x120 */
> +       u32 bistupdr;           /* 0x124 */
> +       u32 bistgsr;            /* 0x128 */
> +       u32 bistwer;            /* 0x12c */
> +       u32 bistber0;           /* 0x130 */
> +       u32 bistber1;           /* 0x134 */
> +       u32 bistber2;           /* 0x138 */
> +       u32 bistber3;           /* 0x13c */
> +       u32 bistwcsr;           /* 0x140 */
> +       u32 bistfwr0;           /* 0x144 */
> +       u32 bistfwr1;           /* 0x148 */
> +       u32 bistfwr2;           /* 0x14c */
> +       u8 res2[0x30];          /* 0x150 */
> +       u32 zqcr0;              /* 0x180 zq control register 0 */
> +       u32 zqcr1;              /* 0x184 zq control register 1 */
> +       u32 zqsr0;              /* 0x188 zq status register 0 */
> +       u32 zqsr1;              /* 0x18c zq status register 1 */
> +       u32 zqcr2;              /* 0x190 zq control register 2 */
> +       u8 res3[0x2c];          /* 0x194 */
> +       u32 dx0gcr;             /* 0x1c0 */
> +       u32 dx0gsr0;            /* 0x1c4 */
> +       u32 dx0gsr1;            /* 0x1c8 */
> +       u32 dx0bdlr0;           /* 0x1cc */
> +       u32 dx0bdlr1;           /* 0x1d0 */
> +       u32 dx0bdlr2;           /* 0x1d4 */
> +       u32 dx0bdlr3;           /* 0x1d8 */
> +       u32 dx0bdlr4;           /* 0x1dc */
> +       u32 dx0lcdlr0;          /* 0x1e0 */
> +       u32 dx0lcdlr1;          /* 0x1e4 */
> +       u32 dx0lcdlr2;          /* 0x1e8 */
> +       u32 dx0mdlr;            /* 0x1ec */
> +       u32 dx0gtr;             /* 0x1f0 */
> +       u32 dx0gsr2;            /* 0x1f4 */
> +       u8 res4[0x08];          /* 0x1f8 */
> +       u32 dx1gcr;             /* 0x200 */
> +       u32 dx1gsr0;            /* 0x204 */
> +       u32 dx1gsr1;            /* 0x208 */
> +       u32 dx1bdlr0;           /* 0x20c */
> +       u32 dx1bdlr1;           /* 0x210 */
> +       u32 dx1bdlr2;           /* 0x214 */
> +       u32 dx1bdlr3;           /* 0x218 */
> +       u32 dx1bdlr4;           /* 0x21c */
> +       u32 dx1lcdlr0;          /* 0x220 */
> +       u32 dx1lcdlr1;          /* 0x224 */
> +       u32 dx1lcdlr2;          /* 0x228 */
> +       u32 dx1mdlr;            /* 0x22c */
> +       u32 dx1gtr;             /* 0x230 */
> +       u32 dx1gsr2;            /* 0x234 */
> +};
> +
> +/*
> + * DRAM common (sunxi_mctl_com_reg) register constants.
> + */
> +#define MCTL_CR_ROW_MASK               (0xf << 4)
> +#define MCTL_CR_ROW(x)                 (((x) - 1) << 4)
> +#define MCTL_CR_PAGE_SIZE_MASK         (0xf << 8)
> +#define MCTL_CR_PAGE_SIZE(x)           ((x) << 8)
> +
> +#endif /* _SUNXI_DRAM_SUN8I_H */
> diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
> index 5bb2f58..5a88ba0 100644
> --- a/board/sunxi/Kconfig
> +++ b/board/sunxi/Kconfig
> @@ -29,10 +29,11 @@ config MACH_SUN7I
>  config MACH_SUN8I
>         bool "sun8i (Allwinner A23)"
>         select CPU_V7
> +       select SUPPORT_SPL
>
>  endchoice
>
> -if MACH_SUN6I
> +if MACH_SUN6I || MACH_SUN8I
>
>  config DRAM_CLK
>         int "sun6i dram clock speed"
> diff --git a/configs/Ippo_q8h_v5_defconfig b/configs/Ippo_q8h_v5_defconfig
> index 50c2f93..37aa46d 100644
> --- a/configs/Ippo_q8h_v5_defconfig
> +++ b/configs/Ippo_q8h_v5_defconfig
> @@ -1,8 +1,15 @@
> +CONFIG_SPL=y
>  CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=5"
> -CONFIG_ARM=y
> -CONFIG_ARCH_SUNXI=y
> -CONFIG_MACH_SUN8I=y
> -CONFIG_TARGET_IPPO_Q8H_V5=y
> -CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-ippo-q8h-v5.dtb"
> +CONFIG_FDTFILE="sun8i-a23-ippo-q8h-v5.dtb"
>  CONFIG_VIDEO=n
>  CONFIG_USB_KEYBOARD=n
> ++S:CONFIG_ARM=y
> ++S:CONFIG_ARCH_SUNXI=y
> ++S:CONFIG_MACH_SUN8I=y
> ++S:CONFIG_DRAM_CLK=480
> +# zq = 0xf777
> ++S:CONFIG_DRAM_ZQ=63351
> +# Wifi power
> ++S:CONFIG_AXP221_DLDO1_VOLT=3300
> +# aldo1 is connected to VCC-IO, VCC-PD, VCC-USB and VCC-HP
> ++S:CONFIG_AXP221_ALDO1_VOLT=3000
> diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h
> index 6f1fc48..792422d 100644
> --- a/include/configs/sun8i.h
> +++ b/include/configs/sun8i.h
> @@ -12,6 +12,8 @@
>  /*
>   * A23 specific configuration
>   */
> +#define CONFIG_CLK_FULL_SPEED  1008000000
> +
>  #define CONFIG_SYS_PROMPT      "sun8i# "
>
>  /*
> --
> 2.1.0

git am reports:

Applying patch #422080 using 'git am'
Description: [U-Boot,13/14] sun8i: Add dram initialization support
Applying: sun8i: Add dram initialization support
/home/wens/sunxi/u-boot/.git/rebase-apply/patch:201: trailing whitespace.
        writel(((dram_para.tpr6 & 0x000007c0) << 10) |
/home/wens/sunxi/u-boot/.git/rebase-apply/patch:455: space before tab in indent.
        u32 tpr6;
warning: 2 lines add whitespace errors.

---

I forgot to send out this one. Anyway, I've tested the series on
my A23 tablet and it's working fine. Something in linux-next broke
my system though.


ChenYu

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

* [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/
  2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
                   ` (12 preceding siblings ...)
  2014-12-16 20:31 ` [U-Boot] [PATCH 14/14] sun8i: Add defconfig for Ippo_q8h v1.2 Hans de Goede
@ 2014-12-18 18:56 ` Ian Campbell
  13 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 18:56 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> The p2wi interface is only available on sun6i, adjust the gpio pinmux defines
> for it to reflect this.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-by: Ian Campbell <ijc@hellion.org.uk>

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

* [U-Boot] [PATCH 02/14] sunxi: Add support for the rsb (Reduced Serial Bus)
  2014-12-17 12:56     ` Hans de Goede
@ 2014-12-18 18:57       ` Ian Campbell
  2014-12-18 18:59       ` Ian Campbell
  1 sibling, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 18:57 UTC (permalink / raw)
  To: u-boot

On Wed, 2014-12-17 at 13:56 +0100, Hans de Goede wrote:
> Hi,
> 
> On 17-12-14 03:22, Chen-Yu Tsai wrote:
> > Hi,
> >
> > On Wed, Dec 17, 2014 at 4:31 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> >> sun8i (A23) introduces a new bus for communicating with the pmic, the rsb,
> >> the rsb is also used to communicate with the pmic on the A80, and is
> >> documented in the A80 user manual.
> >>
> >> This commit adds support for this based on the rsb driver from the allwinner
> >> u-boot sources.
> >>
> >> Note: Not yet ready for upstream, code needs some significant cleanups.
> >
> > Confusing note.
> 
> Ugh, I forgot to remove that note after doing the cleanups, I'll remove it
> from the version of the patch my personal tree :)

I'll stop ignoring this patch then ;-)

Ian.

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

* [U-Boot] [PATCH 02/14] sunxi: Add support for the rsb (Reduced Serial Bus)
  2014-12-17 12:56     ` Hans de Goede
  2014-12-18 18:57       ` Ian Campbell
@ 2014-12-18 18:59       ` Ian Campbell
  2014-12-19 15:26         ` Hans de Goede
  1 sibling, 1 reply; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 18:59 UTC (permalink / raw)
  To: u-boot

On Wed, 2014-12-17 at 13:56 +0100, Hans de Goede wrote:
> >> @@ -128,7 +128,8 @@
> >>   #define SUN6I_CPUCFG_BASE              0x01f01c00
> >>   #define SUNXI_R_UART_BASE              0x01f02800
> >>   #define SUNXI_R_PIO_BASE               0x01f02c00
> >> -#define SUNXI_P2WI_BASE                        0x01f03400
> >> +#define SUNXI_P2WI_BASE                        0x01f03400      /* on sun6i */
> >> +#define SUNXI_RSB_BASE                 0x01f03400      /* on sun8i */
> >
> > Maybe we just use SUN6I_ SUN8I_ prefixes?
> > The base address will be different on sun9i.

Did you miss this suggestions from Chen-Yu? Seems like a good one.

I don't have any other comments.

Ian.

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

* [U-Boot] [PATCH 03/14] sunxi: axp221: Add axp223 support
  2014-12-16 20:31 ` [U-Boot] [PATCH 03/14] sunxi: axp221: Add axp223 support Hans de Goede
  2014-12-17  2:34   ` Chen-Yu Tsai
@ 2014-12-18 19:00   ` Ian Campbell
  1 sibling, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:00 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> The axp223 appears to be the same as the axp221, except that it uses the
> rsb to communicate rather then the p2wi. At least all the registers we use
> are 100% the same.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

With the whitespace fixed:
Acked-by: Ian Campbell <ijc@hellion.org.uk>

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

* [U-Boot] [PATCH 04/14] sunxi: axp221: Add Kconfig help and sane defaults for typical ldo usage
  2014-12-16 20:31 ` [U-Boot] [PATCH 04/14] sunxi: axp221: Add Kconfig help and sane defaults for typical ldo usage Hans de Goede
@ 2014-12-18 19:02   ` Ian Campbell
  0 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:02 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> Some of the ldo-s of the axp221 are used in the same way on most boards, add
> comments to the Kconfig help text to reflect this, and give them defaults
> matching their typical usage.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-by: Ian Campbell <ijc@hellion.org.uk>

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

* [U-Boot] [PATCH 05/14] sunxi: axp221: Make dcdc1 voltage configurable
  2014-12-16 20:31 ` [U-Boot] [PATCH 05/14] sunxi: axp221: Make dcdc1 voltage configurable Hans de Goede
@ 2014-12-18 19:03   ` Ian Campbell
  0 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:03 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> The dcdc1 voltage is typically used as generic 3.3V IO voltage for things like
> GPIO-s, sdcard interfaces, etc. On most boards this is undervolted to 3.0V to
> safe battery, but not on all, make it configurable so that we can use the
> same settings as the original firmware on all boards.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-by: Ian Campbell <ijc@hellion.org.uk>

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

* [U-Boot] [PATCH 06/14] sunxi: axp221: Explicitly turn off unused voltages
  2014-12-16 20:31 ` [U-Boot] [PATCH 06/14] sunxi: axp221: Explicitly turn off unused voltages Hans de Goede
@ 2014-12-18 19:04   ` Ian Campbell
  0 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:04 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> Explicitly turn off unused voltages, rather then leaving them as is. Likewise
> explictly enabled the dcdc convertors, rather then assuming they are already
> enabled at boot.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-by: Ian Campbell <ijc@hellion.org.uk>

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

* [U-Boot] [PATCH 07/14] sunxi: axp221: Disable dcdc4 on sun8i (A23)
  2014-12-16 20:31 ` [U-Boot] [PATCH 07/14] sunxi: axp221: Disable dcdc4 on sun8i (A23) Hans de Goede
@ 2014-12-18 19:05   ` Ian Campbell
  0 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:05 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> dcdc4 is not used on sun8i, disable it.
> 
> While at it also add comments to the other fixed voltages to document what
> they are used for.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-by: Ian Campbell <ijc@hellion.org.uk>

(although I'm wondering if it might have been better to make this
Kconfigurable...)

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

* [U-Boot] [PATCH 08/14] sun6i: Add a sigma_delta_enable paramter to clock_set_pll5()
  2014-12-16 20:31 ` [U-Boot] [PATCH 08/14] sun6i: Add a sigma_delta_enable paramter to clock_set_pll5() Hans de Goede
@ 2014-12-18 19:07   ` Ian Campbell
  2014-12-19 10:02   ` Siarhei Siamashka
  1 sibling, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:07 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> The sun8i dram code sometimes wants to enable sigma delta mode,
> add a parameter to allow this.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-by: Ian Campbell <ijc@hellion.org.uk>

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

* [U-Boot] [PATCH 09/14] sun6i: Add k and m parameters to clock_set_pll5()
  2014-12-16 20:31 ` [U-Boot] [PATCH 09/14] sun6i: Add k and m parameters " Hans de Goede
@ 2014-12-18 19:07   ` Ian Campbell
  2014-12-19 10:03   ` Siarhei Siamashka
  1 sibling, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:07 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> The A23 (sun8i) requires different values for these then sun6i, so make them
> function parameters.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-by: Ian Campbell <ijc@hellion.org.uk>

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

* [U-Boot] [PATCH 10/14] sunxi: Move await_completion dram helper to dram.h
  2014-12-16 20:31 ` [U-Boot] [PATCH 10/14] sunxi: Move await_completion dram helper to dram.h Hans de Goede
@ 2014-12-18 19:08   ` Ian Campbell
  2014-12-19 10:06   ` Siarhei Siamashka
  1 sibling, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:08 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> The await_completion helper is already copy pasted between the sun4i and sun6i
> dram code, and we need it for sun8i too, so lets make it an inline helper in
> dram.h, rather then adding yet another copy.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-by: Ian Campbell <ijc@hellion.org.uk>

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

* [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i
  2014-12-16 20:31 ` [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i Hans de Goede
@ 2014-12-18 19:12   ` Ian Campbell
  2014-12-19 10:08     ` Siarhei Siamashka
  2014-12-19 16:55     ` Hans de Goede
  0 siblings, 2 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:12 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> The sun8i boot0 code fills the DRAM with a "random" pattern before comparing
> it at different offsets to do columns, etc. detection. The sun6i boot0 code
> does not do it, but it seems like a good idea to do this regardless.

Is this the right way round? The existing sun6i code (which you are
moving here) seems to _rely_ on something having written a useful
pattern, which I would have assumed to have been boot0. Or else how does
it work now? Chance?

> The new mctl_mem_fill function this introduces is added as an inline helper
> in dram.h, so that it can be shared with the sun8i dram code.
> 
> While at it move mctl_mem_matches to dram.h for re-use in sun8i too.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  arch/arm/cpu/armv7/sunxi/dram_sun6i.c  | 15 +--------------
>  arch/arm/include/asm/arch-sunxi/dram.h | 29 +++++++++++++++++++++++++++++
>  2 files changed, 30 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> index e1670e5..4675c48 100644
> --- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> @@ -326,20 +326,6 @@ static void mctl_port_cfg(void)
>  	writel(0x00000307, &mctl_com->mbagcr[5]);
>  }
>  
> -static bool mctl_mem_matches(u32 offset)
> -{
> -	const int match_count = 64;
> -	int i, matches = 0;
> -
> -	for (i = 0; i < match_count; i++) {
> -		if (readl(CONFIG_SYS_SDRAM_BASE + i * 4) ==
> -		    readl(CONFIG_SYS_SDRAM_BASE + offset + i * 4))
> -			matches++;
> -	}
> -
> -	return matches == match_count;
> -}
> -
>  unsigned long sunxi_dram_init(void)
>  {
>  	struct sunxi_mctl_com_reg * const mctl_com =
> @@ -391,6 +377,7 @@ unsigned long sunxi_dram_init(void)
>  		    MCTL_CR_BANK(1) | MCTL_CR_RANK(1));
>  
>  	/* Detect and set page size */
> +	mctl_mem_fill();
>  	for (columns = 7; columns < 20; columns++) {
>  		if (mctl_mem_matches(1 << columns))
>  			break;
> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> index 18924f5..0bf718c 100644
> --- a/arch/arm/include/asm/arch-sunxi/dram.h
> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> @@ -22,6 +22,8 @@
>  #include <asm/arch/dram_sun4i.h>
>  #endif
>  
> +#define MCTL_MEM_FILL_MATCH_COUNT 64
> +
>  unsigned long sunxi_dram_init(void);
>  
>  /*
> @@ -37,4 +39,31 @@ static inline void mctl_await_completion(u32 *reg, u32 mask, u32 val)
>  	}
>  }
>  
> +/*
> + * Fill beginning of DRAM with "random" data for mctl_mem_matches()
> + */
> +static inline void mctl_mem_fill(void)
> +{
> +	int i;
> +
> +	for (i = 0; i < MCTL_MEM_FILL_MATCH_COUNT; i++)
> +		writel(0xaa55aa55 + i, CONFIG_SYS_SDRAM_BASE + i * 4);
> +}
> +
> +/*
> + * Test if memory at offset offset matches memory at begin of DRAM
> + */
> +static inline bool mctl_mem_matches(u32 offset)
> +{
> +	int i, matches = 0;
> +
> +	for (i = 0; i < MCTL_MEM_FILL_MATCH_COUNT; i++) {
> +		if (readl(CONFIG_SYS_SDRAM_BASE + i * 4) ==
> +		    readl(CONFIG_SYS_SDRAM_BASE + offset + i * 4))
> +			matches++;
> +	}
> +
> +	return matches == MCTL_MEM_FILL_MATCH_COUNT;
> +}
> +
>  #endif /* _SUNXI_DRAM_H */

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

* [U-Boot] [PATCH 12/14] sunxi: Use memcmp for mctl_mem_matches
  2014-12-16 20:31 ` [U-Boot] [PATCH 12/14] sunxi: Use memcmp for mctl_mem_matches Hans de Goede
@ 2014-12-18 19:13   ` Ian Campbell
  0 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:13 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> Use memcmp for mctl_mem_matches instead of DIY.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-by: Ian Campbell <ijc@hellion.org.uk>

Ian.

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

* [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support
  2014-12-16 20:31 ` [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support Hans de Goede
  2014-12-18 11:12   ` Chen-Yu Tsai
@ 2014-12-18 19:17   ` Ian Campbell
  2014-12-19 16:51     ` Hans de Goede
  2014-12-19 10:20   ` Siarhei Siamashka
  2 siblings, 1 reply; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:17 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> Based on the register / dram_para headers from the Allwinner u-boot / linux
> sources + the init sequences from boot0.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> +/*
> + * Note this code uses a lot of magic hex values, that is because this code
> + * simply replays the init sequence as done by the Allwinner boot0 code, so
> + * we do not know what these values mean. There are no symbolic constants for
> + * these magic values, since we do not know how to name them and making up
> + * names for them is not useful.

On that basis I've only really given this a quick glance. I've no
problem with it.

Couple of queries about the defconfig changes:

> diff --git a/configs/Ippo_q8h_v5_defconfig b/configs/Ippo_q8h_v5_defconfig
> index 50c2f93..37aa46d 100644
> --- a/configs/Ippo_q8h_v5_defconfig
> +++ b/configs/Ippo_q8h_v5_defconfig
> @@ -1,8 +1,15 @@
> +CONFIG_SPL=y
>  CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=5"
> -CONFIG_ARM=y
> -CONFIG_ARCH_SUNXI=y
> -CONFIG_MACH_SUN8I=y
> -CONFIG_TARGET_IPPO_Q8H_V5=y

Not replaced with a S: variant? I know you want CONFIG_TARGET to go, but
I don't think that was part of what you intended in this patch.

> -CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-ippo-q8h-v5.dtb"
> +CONFIG_FDTFILE="sun8i-a23-ippo-q8h-v5.dtb"

The switch from CONFIG_DEFAULT_DEVICE_TREE to CONFIG_FDTFILE conversion
seems a little out of place too.

Ian.

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

* [U-Boot] [PATCH 14/14] sun8i: Add defconfig for Ippo_q8h v1.2
  2014-12-16 20:31 ` [U-Boot] [PATCH 14/14] sun8i: Add defconfig for Ippo_q8h v1.2 Hans de Goede
@ 2014-12-18 19:19   ` Ian Campbell
  0 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-18 19:19 UTC (permalink / raw)
  To: u-boot

On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> We need separate defconfigs for the v5 and v1.2 versions of this board, as
> they use different DRAM parameters.
> 
> Note they also use different dtb files, as the wifi is different too.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Acked-by: Ian Campbell <ijc@hellion.org.uk>

(I think this is the patch you mentioned just now WRT having added a
MAINTAINERS entry, so I won't mention it again ;-))

> diff --git a/configs/Ippo_q8h_v1.2_defconfig b/configs/Ippo_q8h_v1.2_defconfig
> new file mode 100644
> index 0000000..fefed32
> --- /dev/null
> +++ b/configs/Ippo_q8h_v1.2_defconfig
> @@ -0,0 +1,15 @@
> +CONFIG_SPL=y
> +CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=5"
> +CONFIG_FDTFILE="sun8i-a23-ippo-q8h-v1.2.dtb"
> +CONFIG_VIDEO=n
> +CONFIG_USB_KEYBOARD=n
> ++S:CONFIG_ARM=y
> ++S:CONFIG_ARCH_SUNXI=y
> ++S:CONFIG_MACH_SUN8I=y

No CONFIG_TARGET? Do you want to send a patch to nuke them all, better
than having a mixture IMHO.

Ian.

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

* [U-Boot] [PATCH 08/14] sun6i: Add a sigma_delta_enable paramter to clock_set_pll5()
  2014-12-16 20:31 ` [U-Boot] [PATCH 08/14] sun6i: Add a sigma_delta_enable paramter to clock_set_pll5() Hans de Goede
  2014-12-18 19:07   ` Ian Campbell
@ 2014-12-19 10:02   ` Siarhei Siamashka
  1 sibling, 0 replies; 54+ messages in thread
From: Siarhei Siamashka @ 2014-12-19 10:02 UTC (permalink / raw)
  To: u-boot

On Tue, 16 Dec 2014 21:31:33 +0100
Hans de Goede <hdegoede@redhat.com> wrote:

> The sun8i dram code sometimes wants to enable sigma delta mode,
> add a parameter to allow this.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  arch/arm/cpu/armv7/sunxi/clock_sun6i.c        | 9 +++++++--
>  arch/arm/cpu/armv7/sunxi/dram_sun6i.c         | 2 +-
>  arch/arm/include/asm/arch-sunxi/clock.h       | 1 -
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 5 +++++
>  4 files changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
> index 8e949c6..193e314 100644
> --- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
> +++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
> @@ -144,15 +144,20 @@ void clock_set_pll3(unsigned int clk)
>  	       &ccm->pll3_cfg);
>  }
>  
> -void clock_set_pll5(unsigned int clk)
> +void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
>  {
>  	struct sunxi_ccm_reg * const ccm =
>  		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>  	const int k = 2;
>  	const int m = 1;
>  
> +	if (sigma_delta_enable)
> +		writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg);
> +
>  	/* PLL5 rate = 24000000 * n * k / m */
> -	writel(CCM_PLL5_CTRL_EN | CCM_PLL5_CTRL_UPD |
> +	writel(CCM_PLL5_CTRL_EN |
> +	       (sigma_delta_enable ? CCM_PLL5_CTRL_SIGMA_DELTA_EN : 0) |
> +	       CCM_PLL5_CTRL_UPD |
>  	       CCM_PLL5_CTRL_N(clk / (24000000 * k / m)) |
>  	       CCM_PLL5_CTRL_K(k) | CCM_PLL5_CTRL_M(m), &ccm->pll5_cfg);
>  
> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> index 61bb8d4..bc6428a 100644
> --- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> @@ -46,7 +46,7 @@ static void mctl_sys_init(void)
>  		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>  	const int dram_clk_div = 2;
>  
> -	clock_set_pll5(DRAM_CLK * dram_clk_div);
> +	clock_set_pll5(DRAM_CLK * dram_clk_div, false);

Would it make the code a bit more readable to have a named constant
here (with SIGMA_DELTA as part of its name) instead of just true/false? 

The "foobar(true, true, false, true)" style is not exactly informative.

I'm not insisting on this though.

>  	clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV0_MASK,
>  		CCM_DRAMCLK_CFG_DIV0(dram_clk_div) | CCM_DRAMCLK_CFG_RST |
> diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
> index 64acff3..505c363 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock.h
> @@ -26,7 +26,6 @@ int clock_init(void);
>  int clock_twi_onoff(int port, int state);
>  void clock_set_pll1(unsigned int hz);
>  void clock_set_pll3(unsigned int hz);
> -void clock_set_pll5(unsigned int hz);
>  unsigned int clock_get_pll5p(void);
>  unsigned int clock_get_pll6(void);
>  void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz);
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> index 3d4fcd1..f807af3 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> @@ -185,6 +185,7 @@ struct sunxi_ccm_reg {
>  #define CCM_PLL5_CTRL_K(n)		((((n) - 1) & 0x3) << 4)
>  #define CCM_PLL5_CTRL_N(n)		((((n) - 1) & 0x1f) << 8)
>  #define CCM_PLL5_CTRL_UPD		(0x1 << 20)
> +#define CCM_PLL5_CTRL_SIGMA_DELTA_EN	(0x1 << 24)
>  #define CCM_PLL5_CTRL_EN		(0x1 << 31)
>  
>  #define PLL6_CFG_DEFAULT		0x90041811 /* 600 MHz */
> @@ -274,6 +275,8 @@ struct sunxi_ccm_reg {
>  
>  #define MBUS_CLK_DEFAULT		0x81000001 /* PLL6 / 2 */
>  
> +#define CCM_PLL5_PATTERN		0xd1303333
> +
>  /* ahb_reset0 offsets */
>  #define AHB_RESET_OFFSET_GMAC		17
>  #define AHB_RESET_OFFSET_MCTL		14
> @@ -308,4 +311,6 @@ struct sunxi_ccm_reg {
>  #define CCM_DE_CTRL_PLL10		(5 << 24)
>  #define CCM_DE_CTRL_GATE		(1 << 31)
>  
> +void clock_set_pll5(unsigned int clk, bool sigma_delta_enable);
> +
>  #endif /* _SUNXI_CLOCK_SUN6I_H */



-- 
Best regards,
Siarhei Siamashka

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

* [U-Boot] [PATCH 09/14] sun6i: Add k and m parameters to clock_set_pll5()
  2014-12-16 20:31 ` [U-Boot] [PATCH 09/14] sun6i: Add k and m parameters " Hans de Goede
  2014-12-18 19:07   ` Ian Campbell
@ 2014-12-19 10:03   ` Siarhei Siamashka
  2014-12-19 16:40     ` Hans de Goede
  1 sibling, 1 reply; 54+ messages in thread
From: Siarhei Siamashka @ 2014-12-19 10:03 UTC (permalink / raw)
  To: u-boot

On Tue, 16 Dec 2014 21:31:34 +0100
Hans de Goede <hdegoede@redhat.com> wrote:

> The A23 (sun8i) requires different values for these then sun6i, so make them
> function parameters.
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

What happens if A23 does not get these special k and m parameters, but
the 'clock_set_pll5' function picks some other values for them (with
the same resulting target clock speed)?

And if they are really required for A23, then why exposing them as the
function arguments instead of hiding this implementation detail inside
of the 'clock_set_pll5' function?

> ---
>  arch/arm/cpu/armv7/sunxi/clock_sun6i.c        | 4 +---
>  arch/arm/cpu/armv7/sunxi/dram_sun6i.c         | 2 +-
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 +-
>  3 files changed, 3 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
> index 193e314..8ef19df 100644
> --- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
> +++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
> @@ -144,12 +144,10 @@ void clock_set_pll3(unsigned int clk)
>  	       &ccm->pll3_cfg);
>  }
>  
> -void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
> +void clock_set_pll5(unsigned int clk, int k, int m, bool sigma_delta_enable)
>  {
>  	struct sunxi_ccm_reg * const ccm =
>  		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> -	const int k = 2;
> -	const int m = 1;
>  
>  	if (sigma_delta_enable)
>  		writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg);
> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> index bc6428a..a8bbdfd 100644
> --- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> @@ -46,7 +46,7 @@ static void mctl_sys_init(void)
>  		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>  	const int dram_clk_div = 2;
>  
> -	clock_set_pll5(DRAM_CLK * dram_clk_div, false);
> +	clock_set_pll5(DRAM_CLK * dram_clk_div, 2, 1, false);
>  
>  	clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV0_MASK,
>  		CCM_DRAMCLK_CFG_DIV0(dram_clk_div) | CCM_DRAMCLK_CFG_RST |
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> index f807af3..7d61216 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> @@ -311,6 +311,6 @@ struct sunxi_ccm_reg {
>  #define CCM_DE_CTRL_PLL10		(5 << 24)
>  #define CCM_DE_CTRL_GATE		(1 << 31)
>  
> -void clock_set_pll5(unsigned int clk, bool sigma_delta_enable);
> +void clock_set_pll5(unsigned int clk, int k, int m, bool sigma_delta_enable);
>  
>  #endif /* _SUNXI_CLOCK_SUN6I_H */



-- 
Best regards,
Siarhei Siamashka

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

* [U-Boot] [PATCH 10/14] sunxi: Move await_completion dram helper to dram.h
  2014-12-16 20:31 ` [U-Boot] [PATCH 10/14] sunxi: Move await_completion dram helper to dram.h Hans de Goede
  2014-12-18 19:08   ` Ian Campbell
@ 2014-12-19 10:06   ` Siarhei Siamashka
  2014-12-19 16:42     ` Hans de Goede
  1 sibling, 1 reply; 54+ messages in thread
From: Siarhei Siamashka @ 2014-12-19 10:06 UTC (permalink / raw)
  To: u-boot

On Tue, 16 Dec 2014 21:31:35 +0100
Hans de Goede <hdegoede@redhat.com> wrote:

> The await_completion helper is already copy pasted between the sun4i and sun6i
> dram code, and we need it for sun8i too, so lets make it an inline helper in
> dram.h, rather then adding yet another copy.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Making this function "static inline" and placing it into a header file
encourages the compiler to actually inline it. Which is not great for
code size:


== Before the patch and using gcc version 4.8.3 ==

$ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun4i.o
 text    data     bss     dec     hex filename
 1731       0       0    1731     6c3

$ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun6i.o
 text    data     bss     dec     hex filename
 1841       0       0    1841     731

== After the patch and using gcc version 4.8.3 ==

$ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun4i.o
 text    data     bss     dec     hex filename
 1763       0       0    1763     6e3

$ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun6i.o
 text    data     bss     dec     hex filename
 1983       0       0    1983     7bf


Could we perhaps just introduce something like a new source file
"dram_common.c" or even "dram.c"?

> ---
>  arch/arm/cpu/armv7/sunxi/dram_sun4i.c  | 17 ++---------------
>  arch/arm/cpu/armv7/sunxi/dram_sun6i.c  | 31 +++++++++----------------------
>  arch/arm/include/asm/arch-sunxi/dram.h | 14 ++++++++++++++
>  3 files changed, 25 insertions(+), 37 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun4i.c b/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
> index ec8aaa7..c736fa3 100644
> --- a/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
> @@ -36,24 +36,11 @@
>  #define CPU_CFG_CHIP_REV_B 0x3
>  
>  /*
> - * Wait up to 1s for value to be set in given part of reg.
> - */
> -static void await_completion(u32 *reg, u32 mask, u32 val)
> -{
> -	unsigned long tmo = timer_get_us() + 1000000;
> -
> -	while ((readl(reg) & mask) != val) {
> -		if (timer_get_us() > tmo)
> -			panic("Timeout initialising DRAM\n");
> -	}
> -}
> -
> -/*
>   * Wait up to 1s for mask to be clear in given reg.
>   */
>  static inline void await_bits_clear(u32 *reg, u32 mask)
>  {
> -	await_completion(reg, mask, 0);
> +	mctl_await_completion(reg, mask, 0);
>  }
>  
>  /*
> @@ -61,7 +48,7 @@ static inline void await_bits_clear(u32 *reg, u32 mask)
>   */
>  static inline void await_bits_set(u32 *reg, u32 mask)
>  {
> -	await_completion(reg, mask, mask);
> +	mctl_await_completion(reg, mask, mask);
>  }
>  
>  /*
> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> index a8bbdfd..e1670e5 100644
> --- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> @@ -27,19 +27,6 @@ struct dram_sun6i_para {
>  	u16 page_size;
>  };
>  
> -/*
> - * Wait up to 1s for value to be set in given part of reg.
> - */
> -static void await_completion(u32 *reg, u32 mask, u32 val)
> -{
> -	unsigned long tmo = timer_get_us() + 1000000;
> -
> -	while ((readl(reg) & mask) != val) {
> -		if (timer_get_us() > tmo)
> -			panic("Timeout initialising DRAM\n");
> -	}
> -}
> -
>  static void mctl_sys_init(void)
>  {
>  	struct sunxi_ccm_reg * const ccm =
> @@ -51,7 +38,7 @@ static void mctl_sys_init(void)
>  	clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV0_MASK,
>  		CCM_DRAMCLK_CFG_DIV0(dram_clk_div) | CCM_DRAMCLK_CFG_RST |
>  		CCM_DRAMCLK_CFG_UPD);
> -	await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
> +	mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);

As an additional observation, moving await_bits_clear/await_bits_set
functions into a common header file and using them in the sun6i dram
code might improve readability.
  
>  	writel(MDFS_CLK_DEFAULT, &ccm->mdfs_clk_cfg);
>  
> @@ -107,8 +94,8 @@ static bool mctl_rank_detect(u32 *gsr0, int rank)
>  	const u32 done = MCTL_DX_GSR0_RANK0_TRAIN_DONE << rank;
>  	const u32 err = MCTL_DX_GSR0_RANK0_TRAIN_ERR << rank;
>  
> -	await_completion(gsr0, done, done);
> -	await_completion(gsr0 + 0x10, done, done);
> +	mctl_await_completion(gsr0, done, done);
> +	mctl_await_completion(gsr0 + 0x10, done, done);
>  
>  	return !(readl(gsr0) & err) && !(readl(gsr0 + 0x10) & err);
>  }
> @@ -129,7 +116,7 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
>  	}
>  
>  	writel(MCTL_MCMD_NOP, &mctl_ctl->mcmd);
> -	await_completion(&mctl_ctl->mcmd, MCTL_MCMD_BUSY, 0);
> +	mctl_await_completion(&mctl_ctl->mcmd, MCTL_MCMD_BUSY, 0);
>  
>  	/* PHY initialization */
>  	writel(MCTL_PGCR, &mctl_phy->pgcr);
> @@ -166,14 +153,14 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
>  	writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx2gcr);
>  	writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx3gcr);
>  
> -	await_completion(&mctl_phy->pgsr, 0x03, 0x03);
> +	mctl_await_completion(&mctl_phy->pgsr, 0x03, 0x03);
>  
>  	writel(CONFIG_DRAM_ZQ, &mctl_phy->zq0cr1);
>  
>  	setbits_le32(&mctl_phy->pir, MCTL_PIR_CLEAR_STATUS);
>  	writel(MCTL_PIR_STEP1, &mctl_phy->pir);
>  	udelay(10);
> -	await_completion(&mctl_phy->pgsr, 0x1f, 0x1f);
> +	mctl_await_completion(&mctl_phy->pgsr, 0x1f, 0x1f);
>  
>  	/* rank detect */
>  	if (!mctl_rank_detect(&mctl_phy->dx0gsr0, 1)) {
> @@ -204,14 +191,14 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
>  	setbits_le32(&mctl_phy->pir, MCTL_PIR_CLEAR_STATUS);
>  	writel(MCTL_PIR_STEP2, &mctl_phy->pir);
>  	udelay(10);
> -	await_completion(&mctl_phy->pgsr, 0x11, 0x11);
> +	mctl_await_completion(&mctl_phy->pgsr, 0x11, 0x11);
>  
>  	if (readl(&mctl_phy->pgsr) & MCTL_PGSR_TRAIN_ERR_MASK)
>  		panic("Training error initialising DRAM\n");
>  
>  	/* Move to configure state */
>  	writel(MCTL_SCTL_CONFIG, &mctl_ctl->sctl);
> -	await_completion(&mctl_ctl->sstat, 0x07, 0x01);
> +	mctl_await_completion(&mctl_ctl->sstat, 0x07, 0x01);
>  
>  	/* Set number of clks per micro-second */
>  	writel(DRAM_CLK / 1000000, &mctl_ctl->togcnt1u);
> @@ -270,7 +257,7 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
>  
>  	/* Move to access state */
>  	writel(MCTL_SCTL_ACCESS, &mctl_ctl->sctl);
> -	await_completion(&mctl_ctl->sstat, 0x07, 0x03);
> +	mctl_await_completion(&mctl_ctl->sstat, 0x07, 0x03);
>  }
>  
>  static void mctl_com_init(struct dram_sun6i_para *para)
> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> index 9072e68..18924f5 100644
> --- a/arch/arm/include/asm/arch-sunxi/dram.h
> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> @@ -12,6 +12,7 @@
>  #ifndef _SUNXI_DRAM_H
>  #define _SUNXI_DRAM_H
>  
> +#include <asm/io.h>
>  #include <linux/types.h>
>  
>  /* dram regs definition */
> @@ -23,4 +24,17 @@
>  
>  unsigned long sunxi_dram_init(void);
>  
> +/*
> + * Wait up to 1s for value to be set in given part of reg.
> + */
> +static inline void mctl_await_completion(u32 *reg, u32 mask, u32 val)
> +{
> +	unsigned long tmo = timer_get_us() + 1000000;
> +
> +	while ((readl(reg) & mask) != val) {
> +		if (timer_get_us() > tmo)
> +			panic("Timeout initialising DRAM\n");
> +	}
> +}
> +
>  #endif /* _SUNXI_DRAM_H */



-- 
Best regards,
Siarhei Siamashka

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

* [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i
  2014-12-18 19:12   ` Ian Campbell
@ 2014-12-19 10:08     ` Siarhei Siamashka
  2014-12-19 16:56       ` Hans de Goede
  2014-12-19 16:55     ` Hans de Goede
  1 sibling, 1 reply; 54+ messages in thread
From: Siarhei Siamashka @ 2014-12-19 10:08 UTC (permalink / raw)
  To: u-boot

On Thu, 18 Dec 2014 19:12:13 +0000
Ian Campbell <ijc@hellion.org.uk> wrote:

> On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> > The sun8i boot0 code fills the DRAM with a "random" pattern before comparing
> > it at different offsets to do columns, etc. detection. The sun6i boot0 code
> > does not do it, but it seems like a good idea to do this regardless.
> 
> Is this the right way round? The existing sun6i code (which you are
> moving here) seems to _rely_ on something having written a useful
> pattern, which I would have assumed to have been boot0. Or else how does
> it work now? Chance?

It appears that this code is just trying to find the first address line,
which is not connected anywhere. If the address line is not connected,
then having the corresponding bit set or clear in the memory address
does not matter and we are effectively accessing the same location.

Both sun6i and sun8i code is incorrect and only works because of relying
on luck.

The sun6i code is incorrect because it is just reading memory without
initializing it at all. Probably relying on having some unique garbage
there in a natural way.

The newer sun8i code is still incorrect because it is not safeguarding
against accidentally encountering the same test pattern at an unrelated
memory location. Yes, the probability is extremely low, but still not
zero. 

It's a good idea to have a look at the 'get_ram_size' function for
the inspiration.


> > The new mctl_mem_fill function this introduces is added as an inline helper
> > in dram.h, so that it can be shared with the sun8i dram code.
> > 
> > While at it move mctl_mem_matches to dram.h for re-use in sun8i too.
> > 
> > Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> > ---
> >  arch/arm/cpu/armv7/sunxi/dram_sun6i.c  | 15 +--------------
> >  arch/arm/include/asm/arch-sunxi/dram.h | 29 +++++++++++++++++++++++++++++
> >  2 files changed, 30 insertions(+), 14 deletions(-)
> > 
> > diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> > index e1670e5..4675c48 100644
> > --- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> > +++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> > @@ -326,20 +326,6 @@ static void mctl_port_cfg(void)
> >  	writel(0x00000307, &mctl_com->mbagcr[5]);
> >  }
> >  
> > -static bool mctl_mem_matches(u32 offset)
> > -{
> > -	const int match_count = 64;
> > -	int i, matches = 0;
> > -
> > -	for (i = 0; i < match_count; i++) {
> > -		if (readl(CONFIG_SYS_SDRAM_BASE + i * 4) ==
> > -		    readl(CONFIG_SYS_SDRAM_BASE + offset + i * 4))
> > -			matches++;
> > -	}
> > -
> > -	return matches == match_count;
> > -}
> > -
> >  unsigned long sunxi_dram_init(void)
> >  {
> >  	struct sunxi_mctl_com_reg * const mctl_com =
> > @@ -391,6 +377,7 @@ unsigned long sunxi_dram_init(void)
> >  		    MCTL_CR_BANK(1) | MCTL_CR_RANK(1));
> >  
> >  	/* Detect and set page size */
> > +	mctl_mem_fill();
> >  	for (columns = 7; columns < 20; columns++) {
> >  		if (mctl_mem_matches(1 << columns))
> >  			break;
> > diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> > index 18924f5..0bf718c 100644
> > --- a/arch/arm/include/asm/arch-sunxi/dram.h
> > +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> > @@ -22,6 +22,8 @@
> >  #include <asm/arch/dram_sun4i.h>
> >  #endif
> >  
> > +#define MCTL_MEM_FILL_MATCH_COUNT 64
> > +
> >  unsigned long sunxi_dram_init(void);
> >  
> >  /*
> > @@ -37,4 +39,31 @@ static inline void mctl_await_completion(u32 *reg, u32 mask, u32 val)
> >  	}
> >  }
> >  
> > +/*
> > + * Fill beginning of DRAM with "random" data for mctl_mem_matches()
> > + */
> > +static inline void mctl_mem_fill(void)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < MCTL_MEM_FILL_MATCH_COUNT; i++)
> > +		writel(0xaa55aa55 + i, CONFIG_SYS_SDRAM_BASE + i * 4);
> > +}
> > +
> > +/*
> > + * Test if memory at offset offset matches memory at begin of DRAM
> > + */
> > +static inline bool mctl_mem_matches(u32 offset)
> > +{
> > +	int i, matches = 0;
> > +
> > +	for (i = 0; i < MCTL_MEM_FILL_MATCH_COUNT; i++) {
> > +		if (readl(CONFIG_SYS_SDRAM_BASE + i * 4) ==
> > +		    readl(CONFIG_SYS_SDRAM_BASE + offset + i * 4))
> > +			matches++;
> > +	}
> > +
> > +	return matches == MCTL_MEM_FILL_MATCH_COUNT;
> > +}
> > +
> >  #endif /* _SUNXI_DRAM_H */

-- 
Best regards,
Siarhei Siamashka

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

* [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support
  2014-12-16 20:31 ` [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support Hans de Goede
  2014-12-18 11:12   ` Chen-Yu Tsai
  2014-12-18 19:17   ` Ian Campbell
@ 2014-12-19 10:20   ` Siarhei Siamashka
  2014-12-19 17:05     ` Hans de Goede
  2 siblings, 1 reply; 54+ messages in thread
From: Siarhei Siamashka @ 2014-12-19 10:20 UTC (permalink / raw)
  To: u-boot

On Tue, 16 Dec 2014 21:31:38 +0100
Hans de Goede <hdegoede@redhat.com> wrote:

> Based on the register / dram_para headers from the Allwinner u-boot / linux
> sources + the init sequences from boot0.

Can the commit message have more detailed information about the precise
location of the original Allwinner code, which was used as the
reference?

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  arch/arm/cpu/armv7/sunxi/Makefile             |   1 +
>  arch/arm/cpu/armv7/sunxi/board.c              |   3 +-
>  arch/arm/cpu/armv7/sunxi/dram_sun8i.c         | 340 ++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h |   4 +
>  arch/arm/include/asm/arch-sunxi/dram.h        |   2 +
>  arch/arm/include/asm/arch-sunxi/dram_sun8i.h  | 266 ++++++++++++++++++++
>  board/sunxi/Kconfig                           |   3 +-
>  configs/Ippo_q8h_v5_defconfig                 |  17 +-
>  include/configs/sun8i.h                       |   2 +
>  9 files changed, 631 insertions(+), 7 deletions(-)
>  create mode 100644 arch/arm/cpu/armv7/sunxi/dram_sun8i.c
>  create mode 100644 arch/arm/include/asm/arch-sunxi/dram_sun8i.h
> 
> diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
> index 3e8975a..1e89937 100644
> --- a/arch/arm/cpu/armv7/sunxi/Makefile
> +++ b/arch/arm/cpu/armv7/sunxi/Makefile
> @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_SUN4I)	+= dram_sun4i.o
>  obj-$(CONFIG_MACH_SUN5I)	+= dram_sun4i.o
>  obj-$(CONFIG_MACH_SUN6I)	+= dram_sun6i.o
>  obj-$(CONFIG_MACH_SUN7I)	+= dram_sun4i.o
> +obj-$(CONFIG_MACH_SUN8I)	+= dram_sun8i.o
>  ifdef CONFIG_SPL_FEL
>  obj-y	+= start.o
>  endif
> diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
> index 9b3e80c..bc98c56 100644
> --- a/arch/arm/cpu/armv7/sunxi/board.c
> +++ b/arch/arm/cpu/armv7/sunxi/board.c
> @@ -114,7 +114,8 @@ void reset_cpu(ulong addr)
>  /* do some early init */
>  void s_init(void)
>  {
> -#if defined CONFIG_SPL_BUILD && defined CONFIG_MACH_SUN6I
> +#if defined CONFIG_SPL_BUILD && \
> +		(defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I)
>  	/* Magic (undocmented) value taken from boot0, without this DRAM
>  	 * access gets messed up (seems cache related) */
>  	setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun8i.c b/arch/arm/cpu/armv7/sunxi/dram_sun8i.c
> new file mode 100644
> index 0000000..3736fd1
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun8i.c
> @@ -0,0 +1,340 @@
> +/*
> + * Sun8i platform dram controller init.
> + *
> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>

Is Allwinner copyright really not necessary here?

> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +/*
> + * Note this code uses a lot of magic hex values, that is because this code
> + * simply replays the init sequence as done by the Allwinner boot0 code, so
> + * we do not know what these values mean. There are no symbolic constants for
> + * these magic values, since we do not know how to name them and making up
> + * names for them is not useful.
> + */

You are well aware of this documentation since a long time ago, right?
   http://www.ti.com/lit/ug/spruhn7a/spruhn7a.pdf

Please open it and find "Table4-2 DDR3 PHY Registers". Then have a
look at the "sunxi_mctl_phy_reg" struct from your patch. Compare
the register names and their offsets. Looks like we are reasonably
lucky again.

Just as an example, I have commented about a few hardware registers
at different locations in the code.

> +#include <common.h>
> +#include <errno.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/dram.h>
> +#include <asm/arch/prcm.h>
> +
> +static const struct dram_para dram_para = {
> +	.clock = CONFIG_DRAM_CLK,
> +	.type = 3,
> +	.zq = CONFIG_DRAM_ZQ,
> +	.odt_en = 1,
> +	.para1 = 0, /* not used (only used when tpr13 bit 31 is set */
> +	.para2 = 0, /* not used (only used when tpr13 bit 31 is set */
> +	.mr0 = 6736,
> +	.mr1 = 4,
> +	.mr2 = 16,
> +	.mr3 = 0,
> +	/* tpr0 - 10 contain timing constants or-ed together in u32 vals */
> +	.tpr0 = 0x2ab83def,
> +	.tpr1 = 0x18082356,
> +	.tpr2 = 0x00034156,
> +	.tpr3 = 0x448c5533,
> +	.tpr4 = 0x08010d00,
> +	.tpr5 = 0x0340b20f,
> +	.tpr6 = 0x20d118cc,
> +	.tpr7 = 0x14062485,
> +	.tpr8 = 0x220d1d52,
> +	.tpr9 = 0x1e078c22,
> +	.tpr10 = 0x3c,
> +	.tpr11 = 0, /* not used */
> +	.tpr12 = 0, /* not used */
> +	.tpr13 = 0x30000,
> +};
> +
> +static void mctl_sys_init(void)
> +{
> +	struct sunxi_ccm_reg * const ccm =
> +		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> +
> +	/* enable pll5, note the divide by 2 is deliberate! */
> +	clock_set_pll5(dram_para.clock * 1000000 / 2, 1, 2,
> +		       dram_para.tpr13 & 0x40000);

Is it really necessary to have the PLL5 setup so complicated and full
of magic?

> +
> +	/* deassert ahb mctl reset */
> +	setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
> +
> +	/* enable ahb mctl clock */
> +	setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
> +}
> +
> +static void mctl_apply_odt_correction(u32 *reg, int correction)
> +{
> +	int val;
> +
> +	val = (readl(reg) >> 8) & 0xff;
> +	val += correction;
> +
> +	/* clamp */
> +	if (val < 0)
> +		val = 0;
> +	else if (val > 255)
> +		val = 255;
> +
> +	clrsetbits_le32(reg, 0xff00, val << 8);
> +}
> +
> +static void mctl_init(u32 *bus_width)
> +{
> +	struct sunxi_ccm_reg * const ccm =
> +		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> +	struct sunxi_mctl_com_reg * const mctl_com =
> +		(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
> +	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 correction;
> +
> +	if (dram_para.tpr13 & 0x20)
> +		writel(0x40b, &mctl_phy->dcr);

The bits 2-0 are DDRMR (DDR Mode), and the value 3 means DDR3.
And 0x40b is actually the default reset value of this register
according to the TI Keystone2 documentation.

> +	else
> +		writel(0x1000040b, &mctl_phy->dcr);

The bit 28 is marked as reserved and "Reads return zeros" in the
TI Keystone2 documentation. It's a nice chance to test whether
this write has any effect and whether it does modify the register.

> +
> +	if (dram_para.clock >= 480)
> +		writel(0x5c000, &mctl_phy->dllgcr);

0x5c000 = (1 << 18) | (0xE << 13)

> +	else
> +		writel(0xdc000, &mctl_phy->dllgcr);

0xdc000 = (3 << 18) | (0xE << 13)

The 'dllgcr' has the same offset as "4.40 PLL Control Register (PLLCR)"
in the TI Keystone2 documentation.

Bits 16-13 are CPPC (Charge Pump Proportional Current Control) with the
default value 0xE, which matches what we see here.

Bits 19-18 are FRQSEL:
 01 = PLL reference clock (ctl_clk/REF_CLK) ranges from 225MHz to 385MHz
 11 = PLL reference clock (ctl_clk/REF_CLK) ranges from 166MHz to 275MHz

> +
> +	writel(0x0a003e3f, &mctl_phy->pgcr0);
> +	writel(0x03008421, &mctl_phy->pgcr1);
> +
> +	writel(dram_para.mr0, &mctl_phy->mr0);
> +	writel(dram_para.mr1, &mctl_phy->mr1);
> +	writel(dram_para.mr2, &mctl_phy->mr2);
> +	writel(dram_para.mr3, &mctl_phy->mr3);
> +
> +	if (!(dram_para.tpr13 & 0x10000)) {
> +		clrsetbits_le32(&mctl_phy->dx0gcr, 0x3800, 0x2000);
> +		clrsetbits_le32(&mctl_phy->dx1gcr, 0x3800, 0x2000);
> +	}
> +
> +	/*
> +	 * All the masking and shifting below converts what I assume are DDR
> +	 * timing constants from Allwinner dram_para tpr format to the actual
> +	 * timing registers format.
> +	 */
> +
> +	writel((dram_para.tpr0 & 0x000fffff), &mctl_phy->ptr2);
> +	writel((dram_para.tpr1 & 0x1fffffff), &mctl_phy->ptr3);
> +	writel((dram_para.tpr0 & 0x3ff00000) >> 2 |
> +	       (dram_para.tpr2 & 0x0003ffff), &mctl_phy->ptr4);
> +
> +	writel(dram_para.tpr3, &mctl_phy->dtpr0);
> +	writel(dram_para.tpr4, &mctl_phy->dtpr2);
> +
> +	writel(0x01000081, &mctl_phy->dtcr);
> +
> +	if (dram_para.clock <= 240 || !(dram_para.odt_en & 0x01)) {
> +		clrbits_le32(&mctl_phy->dx0gcr, 0x600);
> +		clrbits_le32(&mctl_phy->dx1gcr, 0x600);
> +	}
> +	if (dram_para.clock <= 240) {
> +		writel(0, &mctl_phy->odtcr);
> +		writel(0, &mctl_ctl->odtmap);
> +	}
> +
> +	writel(((dram_para.tpr5 & 0x0f00) << 12) |
> +	       ((dram_para.tpr5 & 0x00f8) <<  9) |
> +	       ((dram_para.tpr5 & 0x0007) <<  8),
> +	       &mctl_ctl->rfshctl0);
> +
> +	writel(((dram_para.tpr5 & 0x0003f000) << 12) |
> +	       ((dram_para.tpr5 & 0x00fc0000) >>  2) |
> +	       ((dram_para.tpr5 & 0x3f000000) >> 16) |
> +	       ((dram_para.tpr6 & 0x0000003f) >>  0),
> +	       &mctl_ctl->dramtmg0);
> +
> +	writel(((dram_para.tpr6 & 0x000007c0) << 10) | 
> +	       ((dram_para.tpr6 & 0x0000f800) >> 3) |
> +	       ((dram_para.tpr6 & 0x003f0000) >> 16),
> +	       &mctl_ctl->dramtmg1);
> +
> +	writel(((dram_para.tpr6 & 0x0fc00000) << 2) |
> +	       ((dram_para.tpr7 & 0x0000001f) << 16) |
> +	       ((dram_para.tpr7 & 0x000003e0) << 3) |
> +	       ((dram_para.tpr7 & 0x0000fc00) >> 10),
> +	       &mctl_ctl->dramtmg2);
> +
> +	writel(((dram_para.tpr7 & 0x03ff0000) >> 16) |
> +	       ((dram_para.tpr6 & 0xf0000000) >> 16),
> +	       &mctl_ctl->dramtmg3);
> +
> +	writel(((dram_para.tpr7 & 0x3c000000) >> 2 ) |
> +	       ((dram_para.tpr8 & 0x00000007) << 16) |
> +	       ((dram_para.tpr8 & 0x00000038) << 5) |
> +	       ((dram_para.tpr8 & 0x000003c0) >> 6),
> +	       &mctl_ctl->dramtmg4);
> +
> +	writel(((dram_para.tpr8 & 0x00003c00) << 14) |
> +	       ((dram_para.tpr8 & 0x0003c000) <<  2) |
> +	       ((dram_para.tpr8 & 0x00fc0000) >> 10) |
> +	       ((dram_para.tpr8 & 0x0f000000) >> 24),
> +	       &mctl_ctl->dramtmg5);
> +
> +	writel(0x00000008, &mctl_ctl->dramtmg8);
> +
> +	writel(((dram_para.tpr8 & 0xf0000000) >> 4) |
> +	       ((dram_para.tpr9 & 0x00007c00) << 6) |
> +	       ((dram_para.tpr9 & 0x000003e0) << 3) |
> +	       ((dram_para.tpr9 & 0x0000001f) >> 0),
> +	       &mctl_ctl->pitmg0);

Could there be any purpose for this other than obfuscation? Looks
really strange.

> +
> +	setbits_le32(&mctl_ctl->pitmg1, 0x80000);
> +
> +	writel(((dram_para.tpr9 & 0x003f8000) << 9) | 0x2001,
> +	       &mctl_ctl->sched);
> +
> +	writel((dram_para.mr0 << 16) | dram_para.mr1, &mctl_ctl->init3);
> +	writel((dram_para.mr2 << 16) | dram_para.mr3, &mctl_ctl->init4);
> +
> +	writel(0x00000000, &mctl_ctl->pimisc);
> +	writel(0x80000000, &mctl_ctl->upd0);
> +
> +	writel(((dram_para.tpr9  & 0xffc00000) >> 22) |
> +	       ((dram_para.tpr10 & 0x00000fff) << 16),
> +	       &mctl_ctl->rfshtmg);
> +
> +	if (dram_para.tpr13 & 0x20)
> +		writel(0x01040001, &mctl_ctl->mstr);
> +	else
> +		writel(0x01040401, &mctl_ctl->mstr);
> +
> +	if (!(dram_para.tpr13 & 0x20000)) {
> +		writel(0x00000002, &mctl_ctl->pwrctl);
> +		writel(0x00008001, &mctl_ctl->pwrtmg);
> +	}
> +
> +	writel(0x00000001, &mctl_ctl->rfshctl3);
> +	writel(0x00000001, &mctl_ctl->pimisc);
> +
> +	/* deassert dram_clk_cfg reset */
> +	setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
> +
> +	setbits_le32(&mctl_com->ccr, 0x80000);
> +
> +	/* zq stuff */
> +	writel((dram_para.zq >> 8) & 0xff, &mctl_phy->zqcr1);

4.59 Impedance Control Register 1 (ZQnCR1)

Bits 7-0 - ZPROG (Impedance Divide Ratio), reset value 0x7B

> +	writel(0x00000003, &mctl_phy->pir);

4.34 PHY Initialization Register (PIR)

Bit 0 - INIT
Bit 1 - ZCAL

> +	udelay(10);
> +	mctl_await_completion(&mctl_phy->pgsr0, 0x09, 0x09);

4.38 PHY General Status Register 0 (PGSR0)

Bit 0 - IDONE (Initialization Done)
Bit 3 - ZCDONE (Impedance Calibration Done)

> +	writel(readl(&mctl_phy->zqsr0) | 0x10000000, &mctl_phy->zqcr2);
> +	writel(dram_para.zq & 0xff, &mctl_phy->zqcr1);

Overwriting ZPROG again? Is it doing something reasonable?
Or might it be an attempt to hide data from the tools like
a10-meminfo (which can dump the DRAM setting via /dev/mem)?

> +	/* A23-v1.0 SDK uses 0xfdf3, A23-v2.0 SDK uses 0x5f3 */
> +	writel(0x000005f3, &mctl_phy->pir);
> +	udelay(10);
> +	mctl_await_completion(&mctl_phy->pgsr0, 0x03, 0x03);
> +
> +	if (readl(&mctl_phy->dx1gsr0) & 0x1000000) {
> +		*bus_width = 8;
> +		writel(0, &mctl_phy->dx1gcr);
> +		writel(dram_para.zq & 0xff, &mctl_phy->zqcr1);
> +		writel(0x5f3, &mctl_phy->pir);
> +		udelay(10000);
> +		setbits_le32(&mctl_ctl->mstr, 0x1000);
> +	} else
> +		*bus_width = 16;
> +
> +	correction = (dram_para.odt_en >> 8) & 0xff;
> +	if (correction) {
> +		if (dram_para.odt_en & 0x80000000)
> +			correction = -correction;
> +
> +		mctl_apply_odt_correction(&mctl_phy->dx0lcdlr1, correction);
> +		mctl_apply_odt_correction(&mctl_phy->dx1lcdlr1, correction);
> +	}
> +
> +	mctl_await_completion(&mctl_ctl->statr, 0x01, 0x01);
> +
> +	writel(0x08003e3f, &mctl_phy->pgcr0);
> +	writel(0x00000000, &mctl_ctl->rfshctl3);
> +}
> +
> +unsigned long sunxi_dram_init(void)
> +{
> +	struct sunxi_mctl_com_reg * const mctl_com =
> +		(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
> +	const u32 columns = 13;
> +	u32 bus, bus_width, offset, page_size, rows;
> +
> +	mctl_sys_init();
> +	mctl_init(&bus_width);
> +
> +	if (bus_width == 16) {
> +		page_size = 8;
> +		bus = 1;
> +	} else {
> +		page_size = 7;
> +		bus = 0;
> +	}
> +
> +	if (!(dram_para.tpr13 & 0x80000000)) {
> +		/* Detect and set rows */
> +		writel(0x000310f4 | MCTL_CR_PAGE_SIZE(page_size),
> +		       &mctl_com->cr);
> +		setbits_le32(&mctl_com->swonr, 0x0003ffff);
> +		mctl_mem_fill();
> +		for (rows = 11; rows < 16; rows++) {
> +			offset = 1 << (rows + columns + bus);
> +			if (mctl_mem_matches(offset))
> +				break;
> +		}
> +		clrsetbits_le32(&mctl_com->cr, MCTL_CR_ROW_MASK,
> +				MCTL_CR_ROW(rows));
> +	} else {
> +		rows = (dram_para.para1 >> 16) & 0xff;
> +		writel(((dram_para.para2 & 0x000000f0) << 11) |
> +		       ((rows - 1) << 4) |
> +		       ((dram_para.para1 & 0x0f000000) >> 22) |
> +		       0x31000 | MCTL_CR_PAGE_SIZE(page_size),
> +		       &mctl_com->cr);
> +		setbits_le32(&mctl_com->swonr, 0x0003ffff);
> +	}
> +
> +	/* Setup DRAM master priority? If this is left out things still work */
> +	writel(0x00000008, &mctl_com->mcr0_0);
> +	writel(0x0001000d, &mctl_com->mcr1_0);
> +	writel(0x00000004, &mctl_com->mcr0_1);
> +	writel(0x00000080, &mctl_com->mcr1_1);
> +	writel(0x00000004, &mctl_com->mcr0_2);
> +	writel(0x00000019, &mctl_com->mcr1_2);
> +	writel(0x00000004, &mctl_com->mcr0_3);
> +	writel(0x00000080, &mctl_com->mcr1_3);
> +	writel(0x00000004, &mctl_com->mcr0_4);
> +	writel(0x01010040, &mctl_com->mcr1_4);
> +	writel(0x00000004, &mctl_com->mcr0_5);
> +	writel(0x0001002f, &mctl_com->mcr1_5);
> +	writel(0x00000004, &mctl_com->mcr0_6);
> +	writel(0x00010020, &mctl_com->mcr1_6);
> +	writel(0x00000004, &mctl_com->mcr0_7);
> +	writel(0x00010020, &mctl_com->mcr1_7);
> +	writel(0x00000008, &mctl_com->mcr0_8);
> +	writel(0x00000001, &mctl_com->mcr1_8);
> +	writel(0x00000008, &mctl_com->mcr0_9);
> +	writel(0x00000005, &mctl_com->mcr1_9);
> +	writel(0x00000008, &mctl_com->mcr0_10);
> +	writel(0x00000003, &mctl_com->mcr1_10);
> +	writel(0x00000008, &mctl_com->mcr0_11);
> +	writel(0x00000005, &mctl_com->mcr1_11);
> +	writel(0x00000008, &mctl_com->mcr0_12);
> +	writel(0x00000003, &mctl_com->mcr1_12);
> +	writel(0x00000008, &mctl_com->mcr0_13);
> +	writel(0x00000004, &mctl_com->mcr1_13);
> +	writel(0x00000008, &mctl_com->mcr0_14);
> +	writel(0x00000002, &mctl_com->mcr1_14);
> +	writel(0x00000008, &mctl_com->mcr0_15);
> +	writel(0x00000003, &mctl_com->mcr1_15);
> +	writel(0x00010138, &mctl_com->bwcr);
> +
> +	return 1 << (rows + columns + bus);
> +}
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> index 7d61216..45a199c 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> @@ -273,7 +273,11 @@ struct sunxi_ccm_reg {
>  #define CCM_HDMI_CTRL_DDC_GATE		(0x1 << 30)
>  #define CCM_HDMI_CTRL_GATE		(0x1 << 31)
>  
> +#ifndef CONFIG_MACH_SUN8I
>  #define MBUS_CLK_DEFAULT		0x81000001 /* PLL6 / 2 */
> +#else
> +#define MBUS_CLK_DEFAULT		0x81000003 /* PLL6 / 4 */
> +#endif
>  
>  #define CCM_PLL5_PATTERN		0xd1303333
>  
> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> index a8a37d5..8d78029 100644
> --- a/arch/arm/include/asm/arch-sunxi/dram.h
> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> @@ -18,6 +18,8 @@
>  /* dram regs definition */
>  #if defined(CONFIG_MACH_SUN6I)
>  #include <asm/arch/dram_sun6i.h>
> +#elif defined(CONFIG_MACH_SUN8I)
> +#include <asm/arch/dram_sun8i.h>
>  #else
>  #include <asm/arch/dram_sun4i.h>
>  #endif
> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i.h
> new file mode 100644
> index 0000000..425cf37
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i.h
> @@ -0,0 +1,266 @@
> +/*
> + * Sun8i platform dram controller register and constant defines
> + *
> + * (C) Copyright 2007-2013
> + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
> + * CPL <cplanxy@allwinnertech.com>
> + * Jerry Wang <wangflord@allwinnertech.com>
> + *
> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef _SUNXI_DRAM_SUN8I_H
> +#define _SUNXI_DRAM_SUN8I_H
> +
> +struct dram_para {
> +	u32 clock;
> +	u32 type;
> +	u32 zq;
> +	u32 odt_en;
> +	u32 para1;
> +	u32 para2;
> +	u32 mr0;
> +	u32 mr1;
> +	u32 mr2;
> +	u32 mr3;
> +	u32 tpr0;
> +	u32 tpr1;
> +	u32 tpr2;
> +	u32 tpr3;
> +	u32 tpr4;
> +	u32 tpr5;
> +   	u32 tpr6;
> +	u32 tpr7;
> +	u32 tpr8;
> +	u32 tpr9;
> +	u32 tpr10;
> +	u32 tpr11;
> +	u32 tpr12;
> +	u32 tpr13;
> +};
> +
> +struct sunxi_mctl_com_reg {
> +	u32 cr;			/* 0x00 */
> +	u32 ccr;		/* 0x04 controller configuration register */
> +	u32 dbgcr;		/* 0x08 */
> +	u8 res0[0x4];		/* 0x0c */
> +	u32 mcr0_0;		/* 0x10 */
> +	u32 mcr1_0;		/* 0x14 */
> +	u32 mcr0_1;		/* 0x18 */
> +	u32 mcr1_1;		/* 0x1c */
> +	u32 mcr0_2;		/* 0x20 */
> +	u32 mcr1_2;		/* 0x24 */
> +	u32 mcr0_3;		/* 0x28 */
> +	u32 mcr1_3;		/* 0x2c */
> +	u32 mcr0_4;		/* 0x30 */
> +	u32 mcr1_4;		/* 0x34 */
> +	u32 mcr0_5;		/* 0x38 */
> +	u32 mcr1_5;		/* 0x3c */
> +	u32 mcr0_6;		/* 0x40 */
> +	u32 mcr1_6;		/* 0x44 */
> +	u32 mcr0_7;		/* 0x48 */
> +	u32 mcr1_7;		/* 0x4c */
> +	u32 mcr0_8;		/* 0x50 */
> +	u32 mcr1_8;		/* 0x54 */
> +	u32 mcr0_9;		/* 0x58 */
> +	u32 mcr1_9;		/* 0x5c */
> +	u32 mcr0_10;		/* 0x60 */
> +	u32 mcr1_10;		/* 0x64 */
> +	u32 mcr0_11;		/* 0x68 */
> +	u32 mcr1_11;		/* 0x6c */
> +	u32 mcr0_12;		/* 0x70 */
> +	u32 mcr1_12;		/* 0x74 */
> +	u32 mcr0_13;		/* 0x78 */
> +	u32 mcr1_13;		/* 0x7c */
> +	u32 mcr0_14;		/* 0x80 */
> +	u32 mcr1_14;		/* 0x84 */
> +	u32 mcr0_15;		/* 0x88 */
> +	u32 mcr1_15;		/* 0x8c */
> +	u32 bwcr;		/* 0x90 */
> +	u32 maer;		/* 0x94 */
> +	u8 res1[0x4];		/* 0x98 */
> +	u32 mcgcr;		/* 0x9c */
> +	u32 bwctr;		/* 0xa0 */
> +	u8 res2[0x4];		/* 0xa4 */
> +	u32 swonr;		/* 0xa8 */
> +	u32 swoffr;		/* 0xac */
> +};
> +
> +struct sunxi_mctl_ctl_reg {
> +	u32 mstr;		/* 0x00 */
> +	u32 statr;		/* 0x04 */
> +	u8 res0[0x08];		/* 0x08 */
> +	u32 mrctrl0;		/* 0x10 */
> +	u32 mrctrl1;		/* 0x14 */
> +	u32 mrstatr;		/* 0x18 */
> +	u8 res1[0x04];		/* 0x1c */
> +	u32 derateen;		/* 0x20 */
> +	u32 deratenint;		/* 0x24 */
> +	u8 res2[0x08];		/* 0x28 */
> +	u32 pwrctl;		/* 0x30 */
> +	u32 pwrtmg;		/* 0x34 */
> +	u8 res3[0x18];		/* 0x38 */
> +	u32 rfshctl0;		/* 0x50 */
> +	u32 rfshctl1;		/* 0x54 */
> +	u8 res4[0x8];		/* 0x58 */
> +	u32 rfshctl3;		/* 0x60 */
> +	u32 rfshtmg;		/* 0x64 */
> +	u8 res6[0x68];		/* 0x68 */
> +	u32 init0;		/* 0xd0 */
> +	u32 init1;		/* 0xd4 */
> +	u32 init2;		/* 0xd8 */
> +	u32 init3;		/* 0xdc */
> +	u32 init4;		/* 0xe0 */
> +	u32 init5;		/* 0xe4 */
> +	u8 res7[0x0c];		/* 0xe8 */
> +	u32 rankctl;		/* 0xf4 */
> +	u8 res8[0x08];		/* 0xf8 */
> +	u32 dramtmg0;		/* 0x100 */
> +	u32 dramtmg1;		/* 0x104 */
> +	u32 dramtmg2;		/* 0x108 */
> +	u32 dramtmg3;		/* 0x10c */
> +	u32 dramtmg4;		/* 0x110 */
> +	u32 dramtmg5;		/* 0x114 */
> +	u32 dramtmg6;		/* 0x118 */
> +	u32 dramtmg7;		/* 0x11c */
> +	u32 dramtmg8;		/* 0x120 */
> +	u8 res9[0x5c];		/* 0x124 */
> +	u32 zqctl0;		/* 0x180 */
> +	u32 zqctl1;		/* 0x184 */
> +	u32 zqctl2;		/* 0x188 */
> +	u32 zqstat;		/* 0x18c */
> +	u32 pitmg0;		/* 0x190 */
> +	u32 pitmg1;		/* 0x194 */
> +	u32 plpcfg0;		/* 0x198 */
> +	u8 res10[0x04];		/* 0x19c */
> +	u32 upd0;		/* 0x1a0 */
> +	u32 upd1;		/* 0x1a4 */
> +	u32 upd2;		/* 0x1a8 */
> +	u32 upd3;		/* 0x1ac */
> +	u32 pimisc;		/* 0x1b0 */
> +	u8 res11[0x1c];		/* 0x1b4 */
> +	u32 trainctl0;		/* 0x1d0 */
> +	u32 trainctl1;		/* 0x1d4 */
> +	u32 trainctl2;		/* 0x1d8 */
> +	u32 trainstat;		/* 0x1dc */
> +	u8 res12[0x60];		/* 0x1e0 */
> +	u32 odtcfg;		/* 0x240 */
> +	u32 odtmap;		/* 0x244 */
> +	u8 res13[0x08];		/* 0x248 */
> +	u32 sched;		/* 0x250 */
> +	u8 res14[0x04];		/* 0x254 */
> +	u32 perfshpr0;		/* 0x258 */
> +	u32 perfshpr1;		/* 0x25c */
> +	u32 perflpr0;		/* 0x260 */
> +	u32 perflpr1;		/* 0x264 */
> +	u32 perfwr0;		/* 0x268 */
> +	u32 perfwr1;		/* 0x26c */
> +};
> +
> +struct sunxi_mctl_phy_reg {
> +	u8 res0[0x04];		/* 0x00 */
> +	u32 pir;		/* 0x04 */
> +	u32 pgcr0;		/* 0x08 phy general configuration register */
> +	u32 pgcr1;		/* 0x0c phy general configuration register */
> +	u32 pgsr0;		/* 0x10 */
> +	u32 pgsr1;		/* 0x14 */
> +	u32 dllgcr;		/* 0x18 */
> +	u32 ptr0;		/* 0x1c */
> +	u32 ptr1;		/* 0x20 */
> +	u32 ptr2;		/* 0x24 */
> +	u32 ptr3;		/* 0x28 */
> +	u32 ptr4;		/* 0x2c */
> +	u32 acmdlr;		/* 0x30 */
> +	u32 acbdlr;		/* 0x34 */
> +	u32 aciocr;		/* 0x38 */
> +	u32 dxccr;		/* 0x3c DATX8 common configuration register */
> +	u32 dsgcr;		/* 0x40 dram system general config register */
> +	u32 dcr;		/* 0x44 */
> +	u32 dtpr0;		/* 0x48 dram timing parameters register 0 */
> +	u32 dtpr1;		/* 0x4c dram timing parameters register 1 */
> +	u32 dtpr2;		/* 0x50 dram timing parameters register 2 */
> +	u32 mr0;		/* 0x54 mode register 0 */
> +	u32 mr1;		/* 0x58 mode register 1 */
> +	u32 mr2;		/* 0x5c mode register 2 */
> +	u32 mr3;		/* 0x60 mode register 3 */
> +	u32 odtcr;		/* 0x64 */
> +	u32 dtcr;		/* 0x68 */
> +	u32 dtar0;		/* 0x6c data training address register 0 */
> +	u32 dtar1;		/* 0x70 data training address register 1 */
> +	u32 dtar2;		/* 0x74 data training address register 2 */
> +	u32 dtar3;		/* 0x78 data training address register 3 */
> +	u32 dtdr0;		/* 0x7c */
> +	u32 dtdr1;		/* 0x80 */
> +	u32 dtedr0;		/* 0x84 */
> +	u32 dtedr1;		/* 0x88 */
> +	u32 pgcr2;		/* 0x8c */
> +	u8 res1[0x70];		/* 0x90 */
> +	u32 bistrr;		/* 0x100 */
> +	u32 bistwcr;		/* 0x104 */
> +	u32 bistmskr0;		/* 0x108 */
> +	u32 bistmskr1;		/* 0x10c */
> +	u32 bistmskr2;		/* 0x110 */
> +	u32 bistlsr;		/* 0x114 */
> +	u32 bistar0;		/* 0x118 */
> +	u32 bistar1;		/* 0x11c */
> +	u32 bistar2;		/* 0x120 */
> +	u32 bistupdr;		/* 0x124 */
> +	u32 bistgsr;		/* 0x128 */
> +	u32 bistwer;		/* 0x12c */
> +	u32 bistber0;		/* 0x130 */
> +	u32 bistber1;		/* 0x134 */
> +	u32 bistber2;		/* 0x138 */
> +	u32 bistber3;		/* 0x13c */
> +	u32 bistwcsr;		/* 0x140 */
> +	u32 bistfwr0;		/* 0x144 */
> +	u32 bistfwr1;		/* 0x148 */
> +	u32 bistfwr2;		/* 0x14c */
> +	u8 res2[0x30];		/* 0x150 */
> +	u32 zqcr0;		/* 0x180 zq control register 0 */
> +	u32 zqcr1;		/* 0x184 zq control register 1 */
> +	u32 zqsr0;		/* 0x188 zq status register 0 */
> +	u32 zqsr1;		/* 0x18c zq status register 1 */
> +	u32 zqcr2;		/* 0x190 zq control register 2 */
> +	u8 res3[0x2c];		/* 0x194 */
> +	u32 dx0gcr;		/* 0x1c0 */
> +	u32 dx0gsr0;		/* 0x1c4 */
> +	u32 dx0gsr1;		/* 0x1c8 */
> +	u32 dx0bdlr0;		/* 0x1cc */
> +	u32 dx0bdlr1;		/* 0x1d0 */
> +	u32 dx0bdlr2;		/* 0x1d4 */
> +	u32 dx0bdlr3;		/* 0x1d8 */
> +	u32 dx0bdlr4;		/* 0x1dc */
> +	u32 dx0lcdlr0;		/* 0x1e0 */
> +	u32 dx0lcdlr1;		/* 0x1e4 */
> +	u32 dx0lcdlr2;		/* 0x1e8 */
> +	u32 dx0mdlr;		/* 0x1ec */
> +	u32 dx0gtr;		/* 0x1f0 */
> +	u32 dx0gsr2;		/* 0x1f4 */
> +	u8 res4[0x08];		/* 0x1f8 */
> +	u32 dx1gcr;		/* 0x200 */
> +	u32 dx1gsr0;		/* 0x204 */
> +	u32 dx1gsr1;		/* 0x208 */
> +	u32 dx1bdlr0;		/* 0x20c */
> +	u32 dx1bdlr1;		/* 0x210 */
> +	u32 dx1bdlr2;		/* 0x214 */
> +	u32 dx1bdlr3;		/* 0x218 */
> +	u32 dx1bdlr4;		/* 0x21c */
> +	u32 dx1lcdlr0;		/* 0x220 */
> +	u32 dx1lcdlr1;		/* 0x224 */
> +	u32 dx1lcdlr2;		/* 0x228 */
> +	u32 dx1mdlr;		/* 0x22c */
> +	u32 dx1gtr;		/* 0x230 */
> +	u32 dx1gsr2;		/* 0x234 */
> +};
> +
> +/*
> + * DRAM common (sunxi_mctl_com_reg) register constants.
> + */
> +#define MCTL_CR_ROW_MASK		(0xf << 4)
> +#define MCTL_CR_ROW(x)			(((x) - 1) << 4)
> +#define MCTL_CR_PAGE_SIZE_MASK		(0xf << 8)
> +#define MCTL_CR_PAGE_SIZE(x)		((x) << 8)
> +
> +#endif /* _SUNXI_DRAM_SUN8I_H */
> diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
> index 5bb2f58..5a88ba0 100644
> --- a/board/sunxi/Kconfig
> +++ b/board/sunxi/Kconfig
> @@ -29,10 +29,11 @@ config MACH_SUN7I
>  config MACH_SUN8I
>  	bool "sun8i (Allwinner A23)"
>  	select CPU_V7
> +	select SUPPORT_SPL
>  
>  endchoice
>  
> -if MACH_SUN6I
> +if MACH_SUN6I || MACH_SUN8I
>  
>  config DRAM_CLK
>  	int "sun6i dram clock speed"
> diff --git a/configs/Ippo_q8h_v5_defconfig b/configs/Ippo_q8h_v5_defconfig
> index 50c2f93..37aa46d 100644
> --- a/configs/Ippo_q8h_v5_defconfig
> +++ b/configs/Ippo_q8h_v5_defconfig
> @@ -1,8 +1,15 @@
> +CONFIG_SPL=y
>  CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=5"
> -CONFIG_ARM=y
> -CONFIG_ARCH_SUNXI=y
> -CONFIG_MACH_SUN8I=y
> -CONFIG_TARGET_IPPO_Q8H_V5=y
> -CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-ippo-q8h-v5.dtb"
> +CONFIG_FDTFILE="sun8i-a23-ippo-q8h-v5.dtb"
>  CONFIG_VIDEO=n
>  CONFIG_USB_KEYBOARD=n
> ++S:CONFIG_ARM=y
> ++S:CONFIG_ARCH_SUNXI=y
> ++S:CONFIG_MACH_SUN8I=y
> ++S:CONFIG_DRAM_CLK=480
> +# zq = 0xf777
> ++S:CONFIG_DRAM_ZQ=63351
> +# Wifi power
> ++S:CONFIG_AXP221_DLDO1_VOLT=3300
> +# aldo1 is connected to VCC-IO, VCC-PD, VCC-USB and VCC-HP
> ++S:CONFIG_AXP221_ALDO1_VOLT=3000
> diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h
> index 6f1fc48..792422d 100644
> --- a/include/configs/sun8i.h
> +++ b/include/configs/sun8i.h
> @@ -12,6 +12,8 @@
>  /*
>   * A23 specific configuration
>   */
> +#define CONFIG_CLK_FULL_SPEED	1008000000
> +
>  #define CONFIG_SYS_PROMPT	"sun8i# "
>  
>  /*



-- 
Best regards,
Siarhei Siamashka

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

* [U-Boot] [PATCH 02/14] sunxi: Add support for the rsb (Reduced Serial Bus)
  2014-12-18 18:59       ` Ian Campbell
@ 2014-12-19 15:26         ` Hans de Goede
  0 siblings, 0 replies; 54+ messages in thread
From: Hans de Goede @ 2014-12-19 15:26 UTC (permalink / raw)
  To: u-boot

Hi,

On 18-12-14 19:59, Ian Campbell wrote:
> On Wed, 2014-12-17 at 13:56 +0100, Hans de Goede wrote:
>>>> @@ -128,7 +128,8 @@
>>>>    #define SUN6I_CPUCFG_BASE              0x01f01c00
>>>>    #define SUNXI_R_UART_BASE              0x01f02800
>>>>    #define SUNXI_R_PIO_BASE               0x01f02c00
>>>> -#define SUNXI_P2WI_BASE                        0x01f03400
>>>> +#define SUNXI_P2WI_BASE                        0x01f03400      /* on sun6i */
>>>> +#define SUNXI_RSB_BASE                 0x01f03400      /* on sun8i */
>>>
>>> Maybe we just use SUN6I_ SUN8I_ prefixes?
>>> The base address will be different on sun9i.
>
> Did you miss this suggestions from Chen-Yu? Seems like a good one.

Yes I missed that (must have read over it). That will work for P2Wi,
but not for RSB, as RSB is used on the A80 too AFAIK, but I guess having
P2WI as SUN6I and RSB as SUNXI makes it clear what is used where, so
I'll update the patch with that change.

Regards,

Hans

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

* [U-Boot] [PATCH 09/14] sun6i: Add k and m parameters to clock_set_pll5()
  2014-12-19 10:03   ` Siarhei Siamashka
@ 2014-12-19 16:40     ` Hans de Goede
  2014-12-22  7:25       ` Siarhei Siamashka
  0 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-19 16:40 UTC (permalink / raw)
  To: u-boot

Hi,

On 19-12-14 11:03, Siarhei Siamashka wrote:
> On Tue, 16 Dec 2014 21:31:34 +0100
> Hans de Goede <hdegoede@redhat.com> wrote:
>
>> The A23 (sun8i) requires different values for these then sun6i, so make them
>> function parameters.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>
> What happens if A23 does not get these special k and m parameters, but
> the 'clock_set_pll5' function picks some other values for them (with
> the same resulting target clock speed)?

The major difference is that on the A23 pll5 must be set to dram_clk / 2,
where as on A31 it needs to be set to dram_clk * 2. By codifying k and m
so that they do the * 2 on A31 and / 2 on A23 we can make any multiple of
24 MHz as DRAM clk without needing any other code to figure out the optimal
k and m. AFAIK using other k and m factors with the same end-result should
work fine. But doing things this way follows the KISS principle and I'm
a great fan of KISS.

Regards,

Hans



>
> And if they are really required for A23, then why exposing them as the
> function arguments instead of hiding this implementation detail inside
> of the 'clock_set_pll5' function?
>
>> ---
>>   arch/arm/cpu/armv7/sunxi/clock_sun6i.c        | 4 +---
>>   arch/arm/cpu/armv7/sunxi/dram_sun6i.c         | 2 +-
>>   arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 +-
>>   3 files changed, 3 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
>> index 193e314..8ef19df 100644
>> --- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
>> +++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
>> @@ -144,12 +144,10 @@ void clock_set_pll3(unsigned int clk)
>>   	       &ccm->pll3_cfg);
>>   }
>>
>> -void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
>> +void clock_set_pll5(unsigned int clk, int k, int m, bool sigma_delta_enable)
>>   {
>>   	struct sunxi_ccm_reg * const ccm =
>>   		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>> -	const int k = 2;
>> -	const int m = 1;
>>
>>   	if (sigma_delta_enable)
>>   		writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg);
>> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
>> index bc6428a..a8bbdfd 100644
>> --- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
>> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
>> @@ -46,7 +46,7 @@ static void mctl_sys_init(void)
>>   		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>>   	const int dram_clk_div = 2;
>>
>> -	clock_set_pll5(DRAM_CLK * dram_clk_div, false);
>> +	clock_set_pll5(DRAM_CLK * dram_clk_div, 2, 1, false);
>>
>>   	clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV0_MASK,
>>   		CCM_DRAMCLK_CFG_DIV0(dram_clk_div) | CCM_DRAMCLK_CFG_RST |
>> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> index f807af3..7d61216 100644
>> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> @@ -311,6 +311,6 @@ struct sunxi_ccm_reg {
>>   #define CCM_DE_CTRL_PLL10		(5 << 24)
>>   #define CCM_DE_CTRL_GATE		(1 << 31)
>>
>> -void clock_set_pll5(unsigned int clk, bool sigma_delta_enable);
>> +void clock_set_pll5(unsigned int clk, int k, int m, bool sigma_delta_enable);
>>
>>   #endif /* _SUNXI_CLOCK_SUN6I_H */
>
>
>

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

* [U-Boot] [PATCH 10/14] sunxi: Move await_completion dram helper to dram.h
  2014-12-19 10:06   ` Siarhei Siamashka
@ 2014-12-19 16:42     ` Hans de Goede
  2014-12-22  7:28       ` Siarhei Siamashka
  0 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-19 16:42 UTC (permalink / raw)
  To: u-boot

Hi,

On 19-12-14 11:06, Siarhei Siamashka wrote:
> On Tue, 16 Dec 2014 21:31:35 +0100
> Hans de Goede <hdegoede@redhat.com> wrote:
>
>> The await_completion helper is already copy pasted between the sun4i and sun6i
>> dram code, and we need it for sun8i too, so lets make it an inline helper in
>> dram.h, rather then adding yet another copy.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>
> Making this function "static inline" and placing it into a header file
> encourages the compiler to actually inline it. Which is not great for
> code size:
>
>
> == Before the patch and using gcc version 4.8.3 ==
>
> $ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun4i.o
>   text    data     bss     dec     hex filename
>   1731       0       0    1731     6c3
>
> $ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun6i.o
>   text    data     bss     dec     hex filename
>   1841       0       0    1841     731
>
> == After the patch and using gcc version 4.8.3 ==
>
> $ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun4i.o
>   text    data     bss     dec     hex filename
>   1763       0       0    1763     6e3
>
> $ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun6i.o
>   text    data     bss     dec     hex filename
>   1983       0       0    1983     7bf

Ah, thanks for catching that, the size increase does not seem to be a problem
right now, but it certainly is something to keep in mind.

> Could we perhaps just introduce something like a new source file
> "dram_common.c" or even "dram.c"?

Sounds like a good idea, patches welcome.

> As an additional observation, moving await_bits_clear/await_bits_set
> functions into a common header file and using them in the sun6i dram
> code might improve readability.

Sounds like another good idea, patches welcome.

Regards,

Hans

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

* [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support
  2014-12-18 19:17   ` Ian Campbell
@ 2014-12-19 16:51     ` Hans de Goede
  0 siblings, 0 replies; 54+ messages in thread
From: Hans de Goede @ 2014-12-19 16:51 UTC (permalink / raw)
  To: u-boot

Hi,

On 18-12-14 20:17, Ian Campbell wrote:
> On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
>> Based on the register / dram_para headers from the Allwinner u-boot / linux
>> sources + the init sequences from boot0.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> +/*
>> + * Note this code uses a lot of magic hex values, that is because this code
>> + * simply replays the init sequence as done by the Allwinner boot0 code, so
>> + * we do not know what these values mean. There are no symbolic constants for
>> + * these magic values, since we do not know how to name them and making up
>> + * names for them is not useful.
>
> On that basis I've only really given this a quick glance. I've no
> problem with it.
>
> Couple of queries about the defconfig changes:
>
>> diff --git a/configs/Ippo_q8h_v5_defconfig b/configs/Ippo_q8h_v5_defconfig
>> index 50c2f93..37aa46d 100644
>> --- a/configs/Ippo_q8h_v5_defconfig
>> +++ b/configs/Ippo_q8h_v5_defconfig
>> @@ -1,8 +1,15 @@
>> +CONFIG_SPL=y
>>   CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=5"
>> -CONFIG_ARM=y
>> -CONFIG_ARCH_SUNXI=y
>> -CONFIG_MACH_SUN8I=y
>> -CONFIG_TARGET_IPPO_Q8H_V5=y
>
> Not replaced with a S: variant? I know you want CONFIG_TARGET to go, but
> I don't think that was part of what you intended in this patch.

Right, I'll add that back.

>
>> -CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-ippo-q8h-v5.dtb"
>> +CONFIG_FDTFILE="sun8i-a23-ippo-q8h-v5.dtb"
>
> The switch from CONFIG_DEFAULT_DEVICE_TREE to CONFIG_FDTFILE conversion
> seems a little out of place too.

That was deliberate, the CONFIG_DEFAULT_DEVICE_TREE is the wrong CONFIG
define to use to set the dtb for the kernel. I'll split the Ippo_q8h_v5_defconfig
changes out into a separate patch and mention this in the commit message.

Regards,

Hans

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

* [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i
  2014-12-18 19:12   ` Ian Campbell
  2014-12-19 10:08     ` Siarhei Siamashka
@ 2014-12-19 16:55     ` Hans de Goede
  2014-12-22 14:19       ` Ian Campbell
  1 sibling, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-19 16:55 UTC (permalink / raw)
  To: u-boot

Hi,

On 18-12-14 20:12, Ian Campbell wrote:
> On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
>> The sun8i boot0 code fills the DRAM with a "random" pattern before comparing
>> it at different offsets to do columns, etc. detection. The sun6i boot0 code
>> does not do it, but it seems like a good idea to do this regardless.
>
> Is this the right way round?

Yes, while working on the sun8i code I noticed that it was prefilling memory
before doing wrap-around checks like the sun6i code is doing too, and then I
realized that the sun6i code was relying on whatever is in DRAM being random
enough for its wrap-around tests to work, without ensuring it is random
enough.

> The existing sun6i code (which you are
> moving here) seems to _rely_ on something having written a useful
> pattern, which I would have assumed to have been boot0. Or else how does
> it work now? Chance?

Yep, it purely works by chance so far.

Regards,

Hans


>
>> The new mctl_mem_fill function this introduces is added as an inline helper
>> in dram.h, so that it can be shared with the sun8i dram code.
>>
>> While at it move mctl_mem_matches to dram.h for re-use in sun8i too.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>   arch/arm/cpu/armv7/sunxi/dram_sun6i.c  | 15 +--------------
>>   arch/arm/include/asm/arch-sunxi/dram.h | 29 +++++++++++++++++++++++++++++
>>   2 files changed, 30 insertions(+), 14 deletions(-)
>>
>> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
>> index e1670e5..4675c48 100644
>> --- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
>> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
>> @@ -326,20 +326,6 @@ static void mctl_port_cfg(void)
>>   	writel(0x00000307, &mctl_com->mbagcr[5]);
>>   }
>>
>> -static bool mctl_mem_matches(u32 offset)
>> -{
>> -	const int match_count = 64;
>> -	int i, matches = 0;
>> -
>> -	for (i = 0; i < match_count; i++) {
>> -		if (readl(CONFIG_SYS_SDRAM_BASE + i * 4) ==
>> -		    readl(CONFIG_SYS_SDRAM_BASE + offset + i * 4))
>> -			matches++;
>> -	}
>> -
>> -	return matches == match_count;
>> -}
>> -
>>   unsigned long sunxi_dram_init(void)
>>   {
>>   	struct sunxi_mctl_com_reg * const mctl_com =
>> @@ -391,6 +377,7 @@ unsigned long sunxi_dram_init(void)
>>   		    MCTL_CR_BANK(1) | MCTL_CR_RANK(1));
>>
>>   	/* Detect and set page size */
>> +	mctl_mem_fill();
>>   	for (columns = 7; columns < 20; columns++) {
>>   		if (mctl_mem_matches(1 << columns))
>>   			break;
>> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
>> index 18924f5..0bf718c 100644
>> --- a/arch/arm/include/asm/arch-sunxi/dram.h
>> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
>> @@ -22,6 +22,8 @@
>>   #include <asm/arch/dram_sun4i.h>
>>   #endif
>>
>> +#define MCTL_MEM_FILL_MATCH_COUNT 64
>> +
>>   unsigned long sunxi_dram_init(void);
>>
>>   /*
>> @@ -37,4 +39,31 @@ static inline void mctl_await_completion(u32 *reg, u32 mask, u32 val)
>>   	}
>>   }
>>
>> +/*
>> + * Fill beginning of DRAM with "random" data for mctl_mem_matches()
>> + */
>> +static inline void mctl_mem_fill(void)
>> +{
>> +	int i;
>> +
>> +	for (i = 0; i < MCTL_MEM_FILL_MATCH_COUNT; i++)
>> +		writel(0xaa55aa55 + i, CONFIG_SYS_SDRAM_BASE + i * 4);
>> +}
>> +
>> +/*
>> + * Test if memory at offset offset matches memory at begin of DRAM
>> + */
>> +static inline bool mctl_mem_matches(u32 offset)
>> +{
>> +	int i, matches = 0;
>> +
>> +	for (i = 0; i < MCTL_MEM_FILL_MATCH_COUNT; i++) {
>> +		if (readl(CONFIG_SYS_SDRAM_BASE + i * 4) ==
>> +		    readl(CONFIG_SYS_SDRAM_BASE + offset + i * 4))
>> +			matches++;
>> +	}
>> +
>> +	return matches == MCTL_MEM_FILL_MATCH_COUNT;
>> +}
>> +
>>   #endif /* _SUNXI_DRAM_H */
>
>

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

* [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i
  2014-12-19 10:08     ` Siarhei Siamashka
@ 2014-12-19 16:56       ` Hans de Goede
  2014-12-22  7:39         ` Siarhei Siamashka
  0 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-19 16:56 UTC (permalink / raw)
  To: u-boot

Hi,

On 19-12-14 11:08, Siarhei Siamashka wrote:
> On Thu, 18 Dec 2014 19:12:13 +0000
> Ian Campbell <ijc@hellion.org.uk> wrote:
>
>> On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
>>> The sun8i boot0 code fills the DRAM with a "random" pattern before comparing
>>> it at different offsets to do columns, etc. detection. The sun6i boot0 code
>>> does not do it, but it seems like a good idea to do this regardless.
>>
>> Is this the right way round? The existing sun6i code (which you are
>> moving here) seems to _rely_ on something having written a useful
>> pattern, which I would have assumed to have been boot0. Or else how does
>> it work now? Chance?
>
> It appears that this code is just trying to find the first address line,
> which is not connected anywhere. If the address line is not connected,
> then having the corresponding bit set or clear in the memory address
> does not matter and we are effectively accessing the same location.

Correct.

> Both sun6i and sun8i code is incorrect and only works because of relying
> on luck.
>
> The sun6i code is incorrect because it is just reading memory without
> initializing it at all. Probably relying on having some unique garbage
> there in a natural way.
>
> The newer sun8i code is still incorrect because it is not safeguarding
> against accidentally encountering the same test pattern at an unrelated
> memory location. Yes, the probability is extremely low, but still not
> zero.

The probability is so low that it really does not matter, so I've no intention
to fix this.

Regards,

Hans

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

* [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support
  2014-12-19 10:20   ` Siarhei Siamashka
@ 2014-12-19 17:05     ` Hans de Goede
  2014-12-22  7:43       ` Siarhei Siamashka
  0 siblings, 1 reply; 54+ messages in thread
From: Hans de Goede @ 2014-12-19 17:05 UTC (permalink / raw)
  To: u-boot

Hi,

On 19-12-14 11:20, Siarhei Siamashka wrote:
> On Tue, 16 Dec 2014 21:31:38 +0100
> Hans de Goede <hdegoede@redhat.com> wrote:
>
>> Based on the register / dram_para headers from the Allwinner u-boot / linux
>> sources + the init sequences from boot0.
>
> Can the commit message have more detailed information about the precise
> location of the original Allwinner code, which was used as the
> reference?

No, it cannot because no code was referenced, I traced the boot0 binary to
figure out what was needed to get dram going on the A23.


>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>   arch/arm/cpu/armv7/sunxi/Makefile             |   1 +
>>   arch/arm/cpu/armv7/sunxi/board.c              |   3 +-
>>   arch/arm/cpu/armv7/sunxi/dram_sun8i.c         | 340 ++++++++++++++++++++++++++
>>   arch/arm/include/asm/arch-sunxi/clock_sun6i.h |   4 +
>>   arch/arm/include/asm/arch-sunxi/dram.h        |   2 +
>>   arch/arm/include/asm/arch-sunxi/dram_sun8i.h  | 266 ++++++++++++++++++++
>>   board/sunxi/Kconfig                           |   3 +-
>>   configs/Ippo_q8h_v5_defconfig                 |  17 +-
>>   include/configs/sun8i.h                       |   2 +
>>   9 files changed, 631 insertions(+), 7 deletions(-)
>>   create mode 100644 arch/arm/cpu/armv7/sunxi/dram_sun8i.c
>>   create mode 100644 arch/arm/include/asm/arch-sunxi/dram_sun8i.h
>>
>> diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
>> index 3e8975a..1e89937 100644
>> --- a/arch/arm/cpu/armv7/sunxi/Makefile
>> +++ b/arch/arm/cpu/armv7/sunxi/Makefile
>> @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_SUN4I)	+= dram_sun4i.o
>>   obj-$(CONFIG_MACH_SUN5I)	+= dram_sun4i.o
>>   obj-$(CONFIG_MACH_SUN6I)	+= dram_sun6i.o
>>   obj-$(CONFIG_MACH_SUN7I)	+= dram_sun4i.o
>> +obj-$(CONFIG_MACH_SUN8I)	+= dram_sun8i.o
>>   ifdef CONFIG_SPL_FEL
>>   obj-y	+= start.o
>>   endif
>> diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
>> index 9b3e80c..bc98c56 100644
>> --- a/arch/arm/cpu/armv7/sunxi/board.c
>> +++ b/arch/arm/cpu/armv7/sunxi/board.c
>> @@ -114,7 +114,8 @@ void reset_cpu(ulong addr)
>>   /* do some early init */
>>   void s_init(void)
>>   {
>> -#if defined CONFIG_SPL_BUILD && defined CONFIG_MACH_SUN6I
>> +#if defined CONFIG_SPL_BUILD && \
>> +		(defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I)
>>   	/* Magic (undocmented) value taken from boot0, without this DRAM
>>   	 * access gets messed up (seems cache related) */
>>   	setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800);
>> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun8i.c b/arch/arm/cpu/armv7/sunxi/dram_sun8i.c
>> new file mode 100644
>> index 0000000..3736fd1
>> --- /dev/null
>> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun8i.c
>> @@ -0,0 +1,340 @@
>> +/*
>> + * Sun8i platform dram controller init.
>> + *
>> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
>
> Is Allwinner copyright really not necessary here?
>
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + */
>> +
>> +/*
>> + * Note this code uses a lot of magic hex values, that is because this code
>> + * simply replays the init sequence as done by the Allwinner boot0 code, so
>> + * we do not know what these values mean. There are no symbolic constants for
>> + * these magic values, since we do not know how to name them and making up
>> + * names for them is not useful.
>> + */
>
> You are well aware of this documentation since a long time ago, right?
>     http://www.ti.com/lit/ug/spruhn7a/spruhn7a.pdf

I'm aware you've used various sources to figure out more about the A10
dram controller, since this DRAM controller seems significantly different
I assumed your sources would not apply, it is good to hear that they do.

I'll add a comment to the next version of this patch referencing that
document.

>
> Please open it and find "Table4-2 DDR3 PHY Registers". Then have a
> look at the "sunxi_mctl_phy_reg" struct from your patch. Compare
> the register names and their offsets. Looks like we are reasonably
> lucky again.
>
> Just as an example, I have commented about a few hardware registers
> at different locations in the code.
>
>> +#include <common.h>
>> +#include <errno.h>
>> +#include <asm/io.h>
>> +#include <asm/arch/clock.h>
>> +#include <asm/arch/dram.h>
>> +#include <asm/arch/prcm.h>
>> +
>> +static const struct dram_para dram_para = {
>> +	.clock = CONFIG_DRAM_CLK,
>> +	.type = 3,
>> +	.zq = CONFIG_DRAM_ZQ,
>> +	.odt_en = 1,
>> +	.para1 = 0, /* not used (only used when tpr13 bit 31 is set */
>> +	.para2 = 0, /* not used (only used when tpr13 bit 31 is set */
>> +	.mr0 = 6736,
>> +	.mr1 = 4,
>> +	.mr2 = 16,
>> +	.mr3 = 0,
>> +	/* tpr0 - 10 contain timing constants or-ed together in u32 vals */
>> +	.tpr0 = 0x2ab83def,
>> +	.tpr1 = 0x18082356,
>> +	.tpr2 = 0x00034156,
>> +	.tpr3 = 0x448c5533,
>> +	.tpr4 = 0x08010d00,
>> +	.tpr5 = 0x0340b20f,
>> +	.tpr6 = 0x20d118cc,
>> +	.tpr7 = 0x14062485,
>> +	.tpr8 = 0x220d1d52,
>> +	.tpr9 = 0x1e078c22,
>> +	.tpr10 = 0x3c,
>> +	.tpr11 = 0, /* not used */
>> +	.tpr12 = 0, /* not used */
>> +	.tpr13 = 0x30000,
>> +};
>> +
>> +static void mctl_sys_init(void)
>> +{
>> +	struct sunxi_ccm_reg * const ccm =
>> +		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>> +
>> +	/* enable pll5, note the divide by 2 is deliberate! */
>> +	clock_set_pll5(dram_para.clock * 1000000 / 2, 1, 2,
>> +		       dram_para.tpr13 & 0x40000);
>
> Is it really necessary to have the PLL5 setup so complicated and full
> of magic?
>
>> +
>> +	/* deassert ahb mctl reset */
>> +	setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
>> +
>> +	/* enable ahb mctl clock */
>> +	setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
>> +}
>> +
>> +static void mctl_apply_odt_correction(u32 *reg, int correction)
>> +{
>> +	int val;
>> +
>> +	val = (readl(reg) >> 8) & 0xff;
>> +	val += correction;
>> +
>> +	/* clamp */
>> +	if (val < 0)
>> +		val = 0;
>> +	else if (val > 255)
>> +		val = 255;
>> +
>> +	clrsetbits_le32(reg, 0xff00, val << 8);
>> +}
>> +
>> +static void mctl_init(u32 *bus_width)
>> +{
>> +	struct sunxi_ccm_reg * const ccm =
>> +		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>> +	struct sunxi_mctl_com_reg * const mctl_com =
>> +		(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
>> +	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 correction;
>> +
>> +	if (dram_para.tpr13 & 0x20)
>> +		writel(0x40b, &mctl_phy->dcr);
>
> The bits 2-0 are DDRMR (DDR Mode), and the value 3 means DDR3.
> And 0x40b is actually the default reset value of this register
> according to the TI Keystone2 documentation.
>
>> +	else
>> +		writel(0x1000040b, &mctl_phy->dcr);
>
> The bit 28 is marked as reserved and "Reads return zeros" in the
> TI Keystone2 documentation. It's a nice chance to test whether
> this write has any effect and whether it does modify the register.

It modifies the register, so that means that at least that bit does
not match the TI Keystone2 documentation.

>
>> +
>> +	if (dram_para.clock >= 480)
>> +		writel(0x5c000, &mctl_phy->dllgcr);
>
> 0x5c000 = (1 << 18) | (0xE << 13)
>
>> +	else
>> +		writel(0xdc000, &mctl_phy->dllgcr);
>
> 0xdc000 = (3 << 18) | (0xE << 13)
>
> The 'dllgcr' has the same offset as "4.40 PLL Control Register (PLLCR)"
> in the TI Keystone2 documentation.
>
> Bits 16-13 are CPPC (Charge Pump Proportional Current Control) with the
> default value 0xE, which matches what we see here.
>
> Bits 19-18 are FRQSEL:
>   01 = PLL reference clock (ctl_clk/REF_CLK) ranges from 225MHz to 385MHz
>   11 = PLL reference clock (ctl_clk/REF_CLK) ranges from 166MHz to 275MHz

That seems to match nicely, as said pll5 is set to dram_clk / 2. which
puts the cut over point at 240 MHz

>
>> +
>> +	writel(0x0a003e3f, &mctl_phy->pgcr0);
>> +	writel(0x03008421, &mctl_phy->pgcr1);
>> +
>> +	writel(dram_para.mr0, &mctl_phy->mr0);
>> +	writel(dram_para.mr1, &mctl_phy->mr1);
>> +	writel(dram_para.mr2, &mctl_phy->mr2);
>> +	writel(dram_para.mr3, &mctl_phy->mr3);
>> +
>> +	if (!(dram_para.tpr13 & 0x10000)) {
>> +		clrsetbits_le32(&mctl_phy->dx0gcr, 0x3800, 0x2000);
>> +		clrsetbits_le32(&mctl_phy->dx1gcr, 0x3800, 0x2000);
>> +	}
>> +
>> +	/*
>> +	 * All the masking and shifting below converts what I assume are DDR
>> +	 * timing constants from Allwinner dram_para tpr format to the actual
>> +	 * timing registers format.
>> +	 */
>> +
>> +	writel((dram_para.tpr0 & 0x000fffff), &mctl_phy->ptr2);
>> +	writel((dram_para.tpr1 & 0x1fffffff), &mctl_phy->ptr3);
>> +	writel((dram_para.tpr0 & 0x3ff00000) >> 2 |
>> +	       (dram_para.tpr2 & 0x0003ffff), &mctl_phy->ptr4);
>> +
>> +	writel(dram_para.tpr3, &mctl_phy->dtpr0);
>> +	writel(dram_para.tpr4, &mctl_phy->dtpr2);
>> +
>> +	writel(0x01000081, &mctl_phy->dtcr);
>> +
>> +	if (dram_para.clock <= 240 || !(dram_para.odt_en & 0x01)) {
>> +		clrbits_le32(&mctl_phy->dx0gcr, 0x600);
>> +		clrbits_le32(&mctl_phy->dx1gcr, 0x600);
>> +	}
>> +	if (dram_para.clock <= 240) {
>> +		writel(0, &mctl_phy->odtcr);
>> +		writel(0, &mctl_ctl->odtmap);
>> +	}
>> +
>> +	writel(((dram_para.tpr5 & 0x0f00) << 12) |
>> +	       ((dram_para.tpr5 & 0x00f8) <<  9) |
>> +	       ((dram_para.tpr5 & 0x0007) <<  8),
>> +	       &mctl_ctl->rfshctl0);
>> +
>> +	writel(((dram_para.tpr5 & 0x0003f000) << 12) |
>> +	       ((dram_para.tpr5 & 0x00fc0000) >>  2) |
>> +	       ((dram_para.tpr5 & 0x3f000000) >> 16) |
>> +	       ((dram_para.tpr6 & 0x0000003f) >>  0),
>> +	       &mctl_ctl->dramtmg0);
>> +
>> +	writel(((dram_para.tpr6 & 0x000007c0) << 10) |
>> +	       ((dram_para.tpr6 & 0x0000f800) >> 3) |
>> +	       ((dram_para.tpr6 & 0x003f0000) >> 16),
>> +	       &mctl_ctl->dramtmg1);
>> +
>> +	writel(((dram_para.tpr6 & 0x0fc00000) << 2) |
>> +	       ((dram_para.tpr7 & 0x0000001f) << 16) |
>> +	       ((dram_para.tpr7 & 0x000003e0) << 3) |
>> +	       ((dram_para.tpr7 & 0x0000fc00) >> 10),
>> +	       &mctl_ctl->dramtmg2);
>> +
>> +	writel(((dram_para.tpr7 & 0x03ff0000) >> 16) |
>> +	       ((dram_para.tpr6 & 0xf0000000) >> 16),
>> +	       &mctl_ctl->dramtmg3);
>> +
>> +	writel(((dram_para.tpr7 & 0x3c000000) >> 2 ) |
>> +	       ((dram_para.tpr8 & 0x00000007) << 16) |
>> +	       ((dram_para.tpr8 & 0x00000038) << 5) |
>> +	       ((dram_para.tpr8 & 0x000003c0) >> 6),
>> +	       &mctl_ctl->dramtmg4);
>> +
>> +	writel(((dram_para.tpr8 & 0x00003c00) << 14) |
>> +	       ((dram_para.tpr8 & 0x0003c000) <<  2) |
>> +	       ((dram_para.tpr8 & 0x00fc0000) >> 10) |
>> +	       ((dram_para.tpr8 & 0x0f000000) >> 24),
>> +	       &mctl_ctl->dramtmg5);
>> +
>> +	writel(0x00000008, &mctl_ctl->dramtmg8);
>> +
>> +	writel(((dram_para.tpr8 & 0xf0000000) >> 4) |
>> +	       ((dram_para.tpr9 & 0x00007c00) << 6) |
>> +	       ((dram_para.tpr9 & 0x000003e0) << 3) |
>> +	       ((dram_para.tpr9 & 0x0000001f) >> 0),
>> +	       &mctl_ctl->pitmg0);
>
> Could there be any purpose for this other than obfuscation? Looks
> really strange.

I think the purpose is to keep the dram_para.tpr? values the same
as with sun6i, so that they can be copy pasted between designs ...


>
>> +
>> +	setbits_le32(&mctl_ctl->pitmg1, 0x80000);
>> +
>> +	writel(((dram_para.tpr9 & 0x003f8000) << 9) | 0x2001,
>> +	       &mctl_ctl->sched);
>> +
>> +	writel((dram_para.mr0 << 16) | dram_para.mr1, &mctl_ctl->init3);
>> +	writel((dram_para.mr2 << 16) | dram_para.mr3, &mctl_ctl->init4);
>> +
>> +	writel(0x00000000, &mctl_ctl->pimisc);
>> +	writel(0x80000000, &mctl_ctl->upd0);
>> +
>> +	writel(((dram_para.tpr9  & 0xffc00000) >> 22) |
>> +	       ((dram_para.tpr10 & 0x00000fff) << 16),
>> +	       &mctl_ctl->rfshtmg);
>> +
>> +	if (dram_para.tpr13 & 0x20)
>> +		writel(0x01040001, &mctl_ctl->mstr);
>> +	else
>> +		writel(0x01040401, &mctl_ctl->mstr);
>> +
>> +	if (!(dram_para.tpr13 & 0x20000)) {
>> +		writel(0x00000002, &mctl_ctl->pwrctl);
>> +		writel(0x00008001, &mctl_ctl->pwrtmg);
>> +	}
>> +
>> +	writel(0x00000001, &mctl_ctl->rfshctl3);
>> +	writel(0x00000001, &mctl_ctl->pimisc);
>> +
>> +	/* deassert dram_clk_cfg reset */
>> +	setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
>> +
>> +	setbits_le32(&mctl_com->ccr, 0x80000);
>> +
>> +	/* zq stuff */
>> +	writel((dram_para.zq >> 8) & 0xff, &mctl_phy->zqcr1);
>
> 4.59 Impedance Control Register 1 (ZQnCR1)
>
> Bits 7-0 - ZPROG (Impedance Divide Ratio), reset value 0x7B
>
>> +	writel(0x00000003, &mctl_phy->pir);
>
> 4.34 PHY Initialization Register (PIR)
>
> Bit 0 - INIT
> Bit 1 - ZCAL
>
>> +	udelay(10);
>> +	mctl_await_completion(&mctl_phy->pgsr0, 0x09, 0x09);
>
> 4.38 PHY General Status Register 0 (PGSR0)
>
> Bit 0 - IDONE (Initialization Done)
> Bit 3 - ZCDONE (Impedance Calibration Done)
>
>> +	writel(readl(&mctl_phy->zqsr0) | 0x10000000, &mctl_phy->zqcr2);
>> +	writel(dram_para.zq & 0xff, &mctl_phy->zqcr1);
>
> Overwriting ZPROG again? Is it doing something reasonable?
> Or might it be an attempt to hide data from the tools like
> a10-meminfo (which can dump the DRAM setting via /dev/mem)?

I've no clue.

Regards,

Hans



>
>> +	/* A23-v1.0 SDK uses 0xfdf3, A23-v2.0 SDK uses 0x5f3 */
>> +	writel(0x000005f3, &mctl_phy->pir);
>> +	udelay(10);
>> +	mctl_await_completion(&mctl_phy->pgsr0, 0x03, 0x03);
>> +
>> +	if (readl(&mctl_phy->dx1gsr0) & 0x1000000) {
>> +		*bus_width = 8;
>> +		writel(0, &mctl_phy->dx1gcr);
>> +		writel(dram_para.zq & 0xff, &mctl_phy->zqcr1);
>> +		writel(0x5f3, &mctl_phy->pir);
>> +		udelay(10000);
>> +		setbits_le32(&mctl_ctl->mstr, 0x1000);
>> +	} else
>> +		*bus_width = 16;
>> +
>> +	correction = (dram_para.odt_en >> 8) & 0xff;
>> +	if (correction) {
>> +		if (dram_para.odt_en & 0x80000000)
>> +			correction = -correction;
>> +
>> +		mctl_apply_odt_correction(&mctl_phy->dx0lcdlr1, correction);
>> +		mctl_apply_odt_correction(&mctl_phy->dx1lcdlr1, correction);
>> +	}
>> +
>> +	mctl_await_completion(&mctl_ctl->statr, 0x01, 0x01);
>> +
>> +	writel(0x08003e3f, &mctl_phy->pgcr0);
>> +	writel(0x00000000, &mctl_ctl->rfshctl3);
>> +}
>> +
>> +unsigned long sunxi_dram_init(void)
>> +{
>> +	struct sunxi_mctl_com_reg * const mctl_com =
>> +		(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
>> +	const u32 columns = 13;
>> +	u32 bus, bus_width, offset, page_size, rows;
>> +
>> +	mctl_sys_init();
>> +	mctl_init(&bus_width);
>> +
>> +	if (bus_width == 16) {
>> +		page_size = 8;
>> +		bus = 1;
>> +	} else {
>> +		page_size = 7;
>> +		bus = 0;
>> +	}
>> +
>> +	if (!(dram_para.tpr13 & 0x80000000)) {
>> +		/* Detect and set rows */
>> +		writel(0x000310f4 | MCTL_CR_PAGE_SIZE(page_size),
>> +		       &mctl_com->cr);
>> +		setbits_le32(&mctl_com->swonr, 0x0003ffff);
>> +		mctl_mem_fill();
>> +		for (rows = 11; rows < 16; rows++) {
>> +			offset = 1 << (rows + columns + bus);
>> +			if (mctl_mem_matches(offset))
>> +				break;
>> +		}
>> +		clrsetbits_le32(&mctl_com->cr, MCTL_CR_ROW_MASK,
>> +				MCTL_CR_ROW(rows));
>> +	} else {
>> +		rows = (dram_para.para1 >> 16) & 0xff;
>> +		writel(((dram_para.para2 & 0x000000f0) << 11) |
>> +		       ((rows - 1) << 4) |
>> +		       ((dram_para.para1 & 0x0f000000) >> 22) |
>> +		       0x31000 | MCTL_CR_PAGE_SIZE(page_size),
>> +		       &mctl_com->cr);
>> +		setbits_le32(&mctl_com->swonr, 0x0003ffff);
>> +	}
>> +
>> +	/* Setup DRAM master priority? If this is left out things still work */
>> +	writel(0x00000008, &mctl_com->mcr0_0);
>> +	writel(0x0001000d, &mctl_com->mcr1_0);
>> +	writel(0x00000004, &mctl_com->mcr0_1);
>> +	writel(0x00000080, &mctl_com->mcr1_1);
>> +	writel(0x00000004, &mctl_com->mcr0_2);
>> +	writel(0x00000019, &mctl_com->mcr1_2);
>> +	writel(0x00000004, &mctl_com->mcr0_3);
>> +	writel(0x00000080, &mctl_com->mcr1_3);
>> +	writel(0x00000004, &mctl_com->mcr0_4);
>> +	writel(0x01010040, &mctl_com->mcr1_4);
>> +	writel(0x00000004, &mctl_com->mcr0_5);
>> +	writel(0x0001002f, &mctl_com->mcr1_5);
>> +	writel(0x00000004, &mctl_com->mcr0_6);
>> +	writel(0x00010020, &mctl_com->mcr1_6);
>> +	writel(0x00000004, &mctl_com->mcr0_7);
>> +	writel(0x00010020, &mctl_com->mcr1_7);
>> +	writel(0x00000008, &mctl_com->mcr0_8);
>> +	writel(0x00000001, &mctl_com->mcr1_8);
>> +	writel(0x00000008, &mctl_com->mcr0_9);
>> +	writel(0x00000005, &mctl_com->mcr1_9);
>> +	writel(0x00000008, &mctl_com->mcr0_10);
>> +	writel(0x00000003, &mctl_com->mcr1_10);
>> +	writel(0x00000008, &mctl_com->mcr0_11);
>> +	writel(0x00000005, &mctl_com->mcr1_11);
>> +	writel(0x00000008, &mctl_com->mcr0_12);
>> +	writel(0x00000003, &mctl_com->mcr1_12);
>> +	writel(0x00000008, &mctl_com->mcr0_13);
>> +	writel(0x00000004, &mctl_com->mcr1_13);
>> +	writel(0x00000008, &mctl_com->mcr0_14);
>> +	writel(0x00000002, &mctl_com->mcr1_14);
>> +	writel(0x00000008, &mctl_com->mcr0_15);
>> +	writel(0x00000003, &mctl_com->mcr1_15);
>> +	writel(0x00010138, &mctl_com->bwcr);
>> +
>> +	return 1 << (rows + columns + bus);
>> +}
>> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> index 7d61216..45a199c 100644
>> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> @@ -273,7 +273,11 @@ struct sunxi_ccm_reg {
>>   #define CCM_HDMI_CTRL_DDC_GATE		(0x1 << 30)
>>   #define CCM_HDMI_CTRL_GATE		(0x1 << 31)
>>
>> +#ifndef CONFIG_MACH_SUN8I
>>   #define MBUS_CLK_DEFAULT		0x81000001 /* PLL6 / 2 */
>> +#else
>> +#define MBUS_CLK_DEFAULT		0x81000003 /* PLL6 / 4 */
>> +#endif
>>
>>   #define CCM_PLL5_PATTERN		0xd1303333
>>
>> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
>> index a8a37d5..8d78029 100644
>> --- a/arch/arm/include/asm/arch-sunxi/dram.h
>> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
>> @@ -18,6 +18,8 @@
>>   /* dram regs definition */
>>   #if defined(CONFIG_MACH_SUN6I)
>>   #include <asm/arch/dram_sun6i.h>
>> +#elif defined(CONFIG_MACH_SUN8I)
>> +#include <asm/arch/dram_sun8i.h>
>>   #else
>>   #include <asm/arch/dram_sun4i.h>
>>   #endif
>> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i.h
>> new file mode 100644
>> index 0000000..425cf37
>> --- /dev/null
>> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i.h
>> @@ -0,0 +1,266 @@
>> +/*
>> + * Sun8i platform dram controller register and constant defines
>> + *
>> + * (C) Copyright 2007-2013
>> + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
>> + * CPL <cplanxy@allwinnertech.com>
>> + * Jerry Wang <wangflord@allwinnertech.com>
>> + *
>> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + */
>> +
>> +#ifndef _SUNXI_DRAM_SUN8I_H
>> +#define _SUNXI_DRAM_SUN8I_H
>> +
>> +struct dram_para {
>> +	u32 clock;
>> +	u32 type;
>> +	u32 zq;
>> +	u32 odt_en;
>> +	u32 para1;
>> +	u32 para2;
>> +	u32 mr0;
>> +	u32 mr1;
>> +	u32 mr2;
>> +	u32 mr3;
>> +	u32 tpr0;
>> +	u32 tpr1;
>> +	u32 tpr2;
>> +	u32 tpr3;
>> +	u32 tpr4;
>> +	u32 tpr5;
>> +   	u32 tpr6;
>> +	u32 tpr7;
>> +	u32 tpr8;
>> +	u32 tpr9;
>> +	u32 tpr10;
>> +	u32 tpr11;
>> +	u32 tpr12;
>> +	u32 tpr13;
>> +};
>> +
>> +struct sunxi_mctl_com_reg {
>> +	u32 cr;			/* 0x00 */
>> +	u32 ccr;		/* 0x04 controller configuration register */
>> +	u32 dbgcr;		/* 0x08 */
>> +	u8 res0[0x4];		/* 0x0c */
>> +	u32 mcr0_0;		/* 0x10 */
>> +	u32 mcr1_0;		/* 0x14 */
>> +	u32 mcr0_1;		/* 0x18 */
>> +	u32 mcr1_1;		/* 0x1c */
>> +	u32 mcr0_2;		/* 0x20 */
>> +	u32 mcr1_2;		/* 0x24 */
>> +	u32 mcr0_3;		/* 0x28 */
>> +	u32 mcr1_3;		/* 0x2c */
>> +	u32 mcr0_4;		/* 0x30 */
>> +	u32 mcr1_4;		/* 0x34 */
>> +	u32 mcr0_5;		/* 0x38 */
>> +	u32 mcr1_5;		/* 0x3c */
>> +	u32 mcr0_6;		/* 0x40 */
>> +	u32 mcr1_6;		/* 0x44 */
>> +	u32 mcr0_7;		/* 0x48 */
>> +	u32 mcr1_7;		/* 0x4c */
>> +	u32 mcr0_8;		/* 0x50 */
>> +	u32 mcr1_8;		/* 0x54 */
>> +	u32 mcr0_9;		/* 0x58 */
>> +	u32 mcr1_9;		/* 0x5c */
>> +	u32 mcr0_10;		/* 0x60 */
>> +	u32 mcr1_10;		/* 0x64 */
>> +	u32 mcr0_11;		/* 0x68 */
>> +	u32 mcr1_11;		/* 0x6c */
>> +	u32 mcr0_12;		/* 0x70 */
>> +	u32 mcr1_12;		/* 0x74 */
>> +	u32 mcr0_13;		/* 0x78 */
>> +	u32 mcr1_13;		/* 0x7c */
>> +	u32 mcr0_14;		/* 0x80 */
>> +	u32 mcr1_14;		/* 0x84 */
>> +	u32 mcr0_15;		/* 0x88 */
>> +	u32 mcr1_15;		/* 0x8c */
>> +	u32 bwcr;		/* 0x90 */
>> +	u32 maer;		/* 0x94 */
>> +	u8 res1[0x4];		/* 0x98 */
>> +	u32 mcgcr;		/* 0x9c */
>> +	u32 bwctr;		/* 0xa0 */
>> +	u8 res2[0x4];		/* 0xa4 */
>> +	u32 swonr;		/* 0xa8 */
>> +	u32 swoffr;		/* 0xac */
>> +};
>> +
>> +struct sunxi_mctl_ctl_reg {
>> +	u32 mstr;		/* 0x00 */
>> +	u32 statr;		/* 0x04 */
>> +	u8 res0[0x08];		/* 0x08 */
>> +	u32 mrctrl0;		/* 0x10 */
>> +	u32 mrctrl1;		/* 0x14 */
>> +	u32 mrstatr;		/* 0x18 */
>> +	u8 res1[0x04];		/* 0x1c */
>> +	u32 derateen;		/* 0x20 */
>> +	u32 deratenint;		/* 0x24 */
>> +	u8 res2[0x08];		/* 0x28 */
>> +	u32 pwrctl;		/* 0x30 */
>> +	u32 pwrtmg;		/* 0x34 */
>> +	u8 res3[0x18];		/* 0x38 */
>> +	u32 rfshctl0;		/* 0x50 */
>> +	u32 rfshctl1;		/* 0x54 */
>> +	u8 res4[0x8];		/* 0x58 */
>> +	u32 rfshctl3;		/* 0x60 */
>> +	u32 rfshtmg;		/* 0x64 */
>> +	u8 res6[0x68];		/* 0x68 */
>> +	u32 init0;		/* 0xd0 */
>> +	u32 init1;		/* 0xd4 */
>> +	u32 init2;		/* 0xd8 */
>> +	u32 init3;		/* 0xdc */
>> +	u32 init4;		/* 0xe0 */
>> +	u32 init5;		/* 0xe4 */
>> +	u8 res7[0x0c];		/* 0xe8 */
>> +	u32 rankctl;		/* 0xf4 */
>> +	u8 res8[0x08];		/* 0xf8 */
>> +	u32 dramtmg0;		/* 0x100 */
>> +	u32 dramtmg1;		/* 0x104 */
>> +	u32 dramtmg2;		/* 0x108 */
>> +	u32 dramtmg3;		/* 0x10c */
>> +	u32 dramtmg4;		/* 0x110 */
>> +	u32 dramtmg5;		/* 0x114 */
>> +	u32 dramtmg6;		/* 0x118 */
>> +	u32 dramtmg7;		/* 0x11c */
>> +	u32 dramtmg8;		/* 0x120 */
>> +	u8 res9[0x5c];		/* 0x124 */
>> +	u32 zqctl0;		/* 0x180 */
>> +	u32 zqctl1;		/* 0x184 */
>> +	u32 zqctl2;		/* 0x188 */
>> +	u32 zqstat;		/* 0x18c */
>> +	u32 pitmg0;		/* 0x190 */
>> +	u32 pitmg1;		/* 0x194 */
>> +	u32 plpcfg0;		/* 0x198 */
>> +	u8 res10[0x04];		/* 0x19c */
>> +	u32 upd0;		/* 0x1a0 */
>> +	u32 upd1;		/* 0x1a4 */
>> +	u32 upd2;		/* 0x1a8 */
>> +	u32 upd3;		/* 0x1ac */
>> +	u32 pimisc;		/* 0x1b0 */
>> +	u8 res11[0x1c];		/* 0x1b4 */
>> +	u32 trainctl0;		/* 0x1d0 */
>> +	u32 trainctl1;		/* 0x1d4 */
>> +	u32 trainctl2;		/* 0x1d8 */
>> +	u32 trainstat;		/* 0x1dc */
>> +	u8 res12[0x60];		/* 0x1e0 */
>> +	u32 odtcfg;		/* 0x240 */
>> +	u32 odtmap;		/* 0x244 */
>> +	u8 res13[0x08];		/* 0x248 */
>> +	u32 sched;		/* 0x250 */
>> +	u8 res14[0x04];		/* 0x254 */
>> +	u32 perfshpr0;		/* 0x258 */
>> +	u32 perfshpr1;		/* 0x25c */
>> +	u32 perflpr0;		/* 0x260 */
>> +	u32 perflpr1;		/* 0x264 */
>> +	u32 perfwr0;		/* 0x268 */
>> +	u32 perfwr1;		/* 0x26c */
>> +};
>> +
>> +struct sunxi_mctl_phy_reg {
>> +	u8 res0[0x04];		/* 0x00 */
>> +	u32 pir;		/* 0x04 */
>> +	u32 pgcr0;		/* 0x08 phy general configuration register */
>> +	u32 pgcr1;		/* 0x0c phy general configuration register */
>> +	u32 pgsr0;		/* 0x10 */
>> +	u32 pgsr1;		/* 0x14 */
>> +	u32 dllgcr;		/* 0x18 */
>> +	u32 ptr0;		/* 0x1c */
>> +	u32 ptr1;		/* 0x20 */
>> +	u32 ptr2;		/* 0x24 */
>> +	u32 ptr3;		/* 0x28 */
>> +	u32 ptr4;		/* 0x2c */
>> +	u32 acmdlr;		/* 0x30 */
>> +	u32 acbdlr;		/* 0x34 */
>> +	u32 aciocr;		/* 0x38 */
>> +	u32 dxccr;		/* 0x3c DATX8 common configuration register */
>> +	u32 dsgcr;		/* 0x40 dram system general config register */
>> +	u32 dcr;		/* 0x44 */
>> +	u32 dtpr0;		/* 0x48 dram timing parameters register 0 */
>> +	u32 dtpr1;		/* 0x4c dram timing parameters register 1 */
>> +	u32 dtpr2;		/* 0x50 dram timing parameters register 2 */
>> +	u32 mr0;		/* 0x54 mode register 0 */
>> +	u32 mr1;		/* 0x58 mode register 1 */
>> +	u32 mr2;		/* 0x5c mode register 2 */
>> +	u32 mr3;		/* 0x60 mode register 3 */
>> +	u32 odtcr;		/* 0x64 */
>> +	u32 dtcr;		/* 0x68 */
>> +	u32 dtar0;		/* 0x6c data training address register 0 */
>> +	u32 dtar1;		/* 0x70 data training address register 1 */
>> +	u32 dtar2;		/* 0x74 data training address register 2 */
>> +	u32 dtar3;		/* 0x78 data training address register 3 */
>> +	u32 dtdr0;		/* 0x7c */
>> +	u32 dtdr1;		/* 0x80 */
>> +	u32 dtedr0;		/* 0x84 */
>> +	u32 dtedr1;		/* 0x88 */
>> +	u32 pgcr2;		/* 0x8c */
>> +	u8 res1[0x70];		/* 0x90 */
>> +	u32 bistrr;		/* 0x100 */
>> +	u32 bistwcr;		/* 0x104 */
>> +	u32 bistmskr0;		/* 0x108 */
>> +	u32 bistmskr1;		/* 0x10c */
>> +	u32 bistmskr2;		/* 0x110 */
>> +	u32 bistlsr;		/* 0x114 */
>> +	u32 bistar0;		/* 0x118 */
>> +	u32 bistar1;		/* 0x11c */
>> +	u32 bistar2;		/* 0x120 */
>> +	u32 bistupdr;		/* 0x124 */
>> +	u32 bistgsr;		/* 0x128 */
>> +	u32 bistwer;		/* 0x12c */
>> +	u32 bistber0;		/* 0x130 */
>> +	u32 bistber1;		/* 0x134 */
>> +	u32 bistber2;		/* 0x138 */
>> +	u32 bistber3;		/* 0x13c */
>> +	u32 bistwcsr;		/* 0x140 */
>> +	u32 bistfwr0;		/* 0x144 */
>> +	u32 bistfwr1;		/* 0x148 */
>> +	u32 bistfwr2;		/* 0x14c */
>> +	u8 res2[0x30];		/* 0x150 */
>> +	u32 zqcr0;		/* 0x180 zq control register 0 */
>> +	u32 zqcr1;		/* 0x184 zq control register 1 */
>> +	u32 zqsr0;		/* 0x188 zq status register 0 */
>> +	u32 zqsr1;		/* 0x18c zq status register 1 */
>> +	u32 zqcr2;		/* 0x190 zq control register 2 */
>> +	u8 res3[0x2c];		/* 0x194 */
>> +	u32 dx0gcr;		/* 0x1c0 */
>> +	u32 dx0gsr0;		/* 0x1c4 */
>> +	u32 dx0gsr1;		/* 0x1c8 */
>> +	u32 dx0bdlr0;		/* 0x1cc */
>> +	u32 dx0bdlr1;		/* 0x1d0 */
>> +	u32 dx0bdlr2;		/* 0x1d4 */
>> +	u32 dx0bdlr3;		/* 0x1d8 */
>> +	u32 dx0bdlr4;		/* 0x1dc */
>> +	u32 dx0lcdlr0;		/* 0x1e0 */
>> +	u32 dx0lcdlr1;		/* 0x1e4 */
>> +	u32 dx0lcdlr2;		/* 0x1e8 */
>> +	u32 dx0mdlr;		/* 0x1ec */
>> +	u32 dx0gtr;		/* 0x1f0 */
>> +	u32 dx0gsr2;		/* 0x1f4 */
>> +	u8 res4[0x08];		/* 0x1f8 */
>> +	u32 dx1gcr;		/* 0x200 */
>> +	u32 dx1gsr0;		/* 0x204 */
>> +	u32 dx1gsr1;		/* 0x208 */
>> +	u32 dx1bdlr0;		/* 0x20c */
>> +	u32 dx1bdlr1;		/* 0x210 */
>> +	u32 dx1bdlr2;		/* 0x214 */
>> +	u32 dx1bdlr3;		/* 0x218 */
>> +	u32 dx1bdlr4;		/* 0x21c */
>> +	u32 dx1lcdlr0;		/* 0x220 */
>> +	u32 dx1lcdlr1;		/* 0x224 */
>> +	u32 dx1lcdlr2;		/* 0x228 */
>> +	u32 dx1mdlr;		/* 0x22c */
>> +	u32 dx1gtr;		/* 0x230 */
>> +	u32 dx1gsr2;		/* 0x234 */
>> +};
>> +
>> +/*
>> + * DRAM common (sunxi_mctl_com_reg) register constants.
>> + */
>> +#define MCTL_CR_ROW_MASK		(0xf << 4)
>> +#define MCTL_CR_ROW(x)			(((x) - 1) << 4)
>> +#define MCTL_CR_PAGE_SIZE_MASK		(0xf << 8)
>> +#define MCTL_CR_PAGE_SIZE(x)		((x) << 8)
>> +
>> +#endif /* _SUNXI_DRAM_SUN8I_H */
>> diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
>> index 5bb2f58..5a88ba0 100644
>> --- a/board/sunxi/Kconfig
>> +++ b/board/sunxi/Kconfig
>> @@ -29,10 +29,11 @@ config MACH_SUN7I
>>   config MACH_SUN8I
>>   	bool "sun8i (Allwinner A23)"
>>   	select CPU_V7
>> +	select SUPPORT_SPL
>>
>>   endchoice
>>
>> -if MACH_SUN6I
>> +if MACH_SUN6I || MACH_SUN8I
>>
>>   config DRAM_CLK
>>   	int "sun6i dram clock speed"
>> diff --git a/configs/Ippo_q8h_v5_defconfig b/configs/Ippo_q8h_v5_defconfig
>> index 50c2f93..37aa46d 100644
>> --- a/configs/Ippo_q8h_v5_defconfig
>> +++ b/configs/Ippo_q8h_v5_defconfig
>> @@ -1,8 +1,15 @@
>> +CONFIG_SPL=y
>>   CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=5"
>> -CONFIG_ARM=y
>> -CONFIG_ARCH_SUNXI=y
>> -CONFIG_MACH_SUN8I=y
>> -CONFIG_TARGET_IPPO_Q8H_V5=y
>> -CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-ippo-q8h-v5.dtb"
>> +CONFIG_FDTFILE="sun8i-a23-ippo-q8h-v5.dtb"
>>   CONFIG_VIDEO=n
>>   CONFIG_USB_KEYBOARD=n
>> ++S:CONFIG_ARM=y
>> ++S:CONFIG_ARCH_SUNXI=y
>> ++S:CONFIG_MACH_SUN8I=y
>> ++S:CONFIG_DRAM_CLK=480
>> +# zq = 0xf777
>> ++S:CONFIG_DRAM_ZQ=63351
>> +# Wifi power
>> ++S:CONFIG_AXP221_DLDO1_VOLT=3300
>> +# aldo1 is connected to VCC-IO, VCC-PD, VCC-USB and VCC-HP
>> ++S:CONFIG_AXP221_ALDO1_VOLT=3000
>> diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h
>> index 6f1fc48..792422d 100644
>> --- a/include/configs/sun8i.h
>> +++ b/include/configs/sun8i.h
>> @@ -12,6 +12,8 @@
>>   /*
>>    * A23 specific configuration
>>    */
>> +#define CONFIG_CLK_FULL_SPEED	1008000000
>> +
>>   #define CONFIG_SYS_PROMPT	"sun8i# "
>>
>>   /*
>
>
>

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

* [U-Boot] [PATCH 09/14] sun6i: Add k and m parameters to clock_set_pll5()
  2014-12-19 16:40     ` Hans de Goede
@ 2014-12-22  7:25       ` Siarhei Siamashka
  0 siblings, 0 replies; 54+ messages in thread
From: Siarhei Siamashka @ 2014-12-22  7:25 UTC (permalink / raw)
  To: u-boot

On Fri, 19 Dec 2014 17:40:27 +0100
Hans de Goede <hdegoede@redhat.com> wrote:

> Hi,
> 
> On 19-12-14 11:03, Siarhei Siamashka wrote:
> > On Tue, 16 Dec 2014 21:31:34 +0100
> > Hans de Goede <hdegoede@redhat.com> wrote:
> >
> >> The A23 (sun8i) requires different values for these then sun6i, so make them
> >> function parameters.
> >>
> >> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> >
> > What happens if A23 does not get these special k and m parameters, but
> > the 'clock_set_pll5' function picks some other values for them (with
> > the same resulting target clock speed)?
> 
> The major difference is that on the A23 pll5 must be set to dram_clk / 2,
> where as on A31 it needs to be set to dram_clk * 2. By codifying k and m
> so that they do the * 2 on A31 and / 2 on A23 we can make any multiple of
> 24 MHz as DRAM clk without needing any other code to figure out the optimal
> k and m.

Wouldn't such other code in 'clock_set_pll5' just look like this
(adds only a few extra instructions with an optimizing compiler):

    const int max_n = 32;
    int k = 1, m = 2;
    if (clk > 24000000 * k * max_n / m) {
        m = 1;
        if (clk > 24000000 * k * max_n / m)
            k = 2;
    }

As an additional bonus, you get 12 MHz clock frequency selection
granularity on A31 for the DRAM clock speeds up to 384 MHz. And
keep the current 24 MHz granularity for anything larger than that.

> AFAIK using other k and m factors with the same end-result should
> work fine.

This statement seems to somewhat contradict with your original commit
message. Should the commit message be updated?

> But doing things this way follows the KISS principle and I'm
> a great fan of KISS.

By instead spreading the complexity all across the sources? So that each
caller code needs to make assumptions about the valid clock frequency
range and statically pick the right multiplier/divisor parameters as
an additional burden?

In what way is it simple?


> 
> Regards,
> 
> Hans
> 
> 
> 
> >
> > And if they are really required for A23, then why exposing them as the
> > function arguments instead of hiding this implementation detail inside
> > of the 'clock_set_pll5' function?
> >
> >> ---
> >>   arch/arm/cpu/armv7/sunxi/clock_sun6i.c        | 4 +---
> >>   arch/arm/cpu/armv7/sunxi/dram_sun6i.c         | 2 +-
> >>   arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 2 +-
> >>   3 files changed, 3 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
> >> index 193e314..8ef19df 100644
> >> --- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
> >> +++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
> >> @@ -144,12 +144,10 @@ void clock_set_pll3(unsigned int clk)
> >>   	       &ccm->pll3_cfg);
> >>   }
> >>
> >> -void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
> >> +void clock_set_pll5(unsigned int clk, int k, int m, bool sigma_delta_enable)
> >>   {
> >>   	struct sunxi_ccm_reg * const ccm =
> >>   		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> >> -	const int k = 2;
> >> -	const int m = 1;
> >>
> >>   	if (sigma_delta_enable)
> >>   		writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg);
> >> diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> >> index bc6428a..a8bbdfd 100644
> >> --- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> >> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
> >> @@ -46,7 +46,7 @@ static void mctl_sys_init(void)
> >>   		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> >>   	const int dram_clk_div = 2;
> >>
> >> -	clock_set_pll5(DRAM_CLK * dram_clk_div, false);
> >> +	clock_set_pll5(DRAM_CLK * dram_clk_div, 2, 1, false);
> >>
> >>   	clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV0_MASK,
> >>   		CCM_DRAMCLK_CFG_DIV0(dram_clk_div) | CCM_DRAMCLK_CFG_RST |
> >> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> >> index f807af3..7d61216 100644
> >> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> >> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> >> @@ -311,6 +311,6 @@ struct sunxi_ccm_reg {
> >>   #define CCM_DE_CTRL_PLL10		(5 << 24)
> >>   #define CCM_DE_CTRL_GATE		(1 << 31)
> >>
> >> -void clock_set_pll5(unsigned int clk, bool sigma_delta_enable);
> >> +void clock_set_pll5(unsigned int clk, int k, int m, bool sigma_delta_enable);
> >>
> >>   #endif /* _SUNXI_CLOCK_SUN6I_H */
> >
> >
> >

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

* [U-Boot] [PATCH 10/14] sunxi: Move await_completion dram helper to dram.h
  2014-12-19 16:42     ` Hans de Goede
@ 2014-12-22  7:28       ` Siarhei Siamashka
  0 siblings, 0 replies; 54+ messages in thread
From: Siarhei Siamashka @ 2014-12-22  7:28 UTC (permalink / raw)
  To: u-boot

On Fri, 19 Dec 2014 17:42:58 +0100
Hans de Goede <hdegoede@redhat.com> wrote:

> Hi,
> 
> On 19-12-14 11:06, Siarhei Siamashka wrote:
> > On Tue, 16 Dec 2014 21:31:35 +0100
> > Hans de Goede <hdegoede@redhat.com> wrote:
> >
> >> The await_completion helper is already copy pasted between the sun4i and sun6i
> >> dram code, and we need it for sun8i too, so lets make it an inline helper in
> >> dram.h, rather then adding yet another copy.
> >>
> >> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> >
> > Making this function "static inline" and placing it into a header file
> > encourages the compiler to actually inline it. Which is not great for
> > code size:
> >
> >
> > == Before the patch and using gcc version 4.8.3 ==
> >
> > $ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun4i.o
> >   text    data     bss     dec     hex filename
> >   1731       0       0    1731     6c3
> >
> > $ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun6i.o
> >   text    data     bss     dec     hex filename
> >   1841       0       0    1841     731
> >
> > == After the patch and using gcc version 4.8.3 ==
> >
> > $ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun4i.o
> >   text    data     bss     dec     hex filename
> >   1763       0       0    1763     6e3
> >
> > $ arm-none-linux-gnieabi-size spl/arch/arm/cpu/armv7/sunxi/dram_sun6i.o
> >   text    data     bss     dec     hex filename
> >   1983       0       0    1983     7bf
> 
> Ah, thanks for catching that, the size increase does not seem to be a problem
> right now, but it certainly is something to keep in mind.
> 
> > Could we perhaps just introduce something like a new source file
> > "dram_common.c" or even "dram.c"?
> 
> Sounds like a good idea, patches welcome.

I would definitely appreciate if we could have avoided having this
unnecessary code size increase in the first place.

But if we run out of the code size space, then the oversized static
inline functions in the headers are always relatively easy to identify
and eliminate in one go. That's only a minor annoyance and I'm not
going to waste time on pointless debates.

> > As an additional observation, moving await_bits_clear/await_bits_set
> > functions into a common header file and using them in the sun6i dram
> > code might improve readability.
> 
> Sounds like another good idea, patches welcome.


-- 
Best regards,
Siarhei Siamashka

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

* [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i
  2014-12-19 16:56       ` Hans de Goede
@ 2014-12-22  7:39         ` Siarhei Siamashka
  0 siblings, 0 replies; 54+ messages in thread
From: Siarhei Siamashka @ 2014-12-22  7:39 UTC (permalink / raw)
  To: u-boot

On Fri, 19 Dec 2014 17:56:40 +0100
Hans de Goede <hdegoede@redhat.com> wrote:

> Hi,
> 
> On 19-12-14 11:08, Siarhei Siamashka wrote:
> > On Thu, 18 Dec 2014 19:12:13 +0000
> > Ian Campbell <ijc@hellion.org.uk> wrote:
> >
> >> On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> >>> The sun8i boot0 code fills the DRAM with a "random" pattern before comparing
> >>> it at different offsets to do columns, etc. detection. The sun6i boot0 code
> >>> does not do it, but it seems like a good idea to do this regardless.
> >>
> >> Is this the right way round? The existing sun6i code (which you are
> >> moving here) seems to _rely_ on something having written a useful
> >> pattern, which I would have assumed to have been boot0. Or else how does
> >> it work now? Chance?
> >
> > It appears that this code is just trying to find the first address line,
> > which is not connected anywhere. If the address line is not connected,
> > then having the corresponding bit set or clear in the memory address
> > does not matter and we are effectively accessing the same location.
> 
> Correct.
> 
> > Both sun6i and sun8i code is incorrect and only works because of relying
> > on luck.
> >
> > The sun6i code is incorrect because it is just reading memory without
> > initializing it at all. Probably relying on having some unique garbage
> > there in a natural way.
> >
> > The newer sun8i code is still incorrect because it is not safeguarding
> > against accidentally encountering the same test pattern at an unrelated
> > memory location. Yes, the probability is extremely low, but still not
> > zero.
> 
> The probability is so low that it really does not matter, so I've no intention
> to fix this.

"If anything bad can happen, it probably will" :-)

There are many real life examples, when something supposedly almost
impossible has in fact happened. Like the following story:
    http://ixbtlabs.com/articles2/magia-chisel/
In a nutshell, the designers of some old CD/CD-RW drives just did not
bother to ensure that the written user data can be never confused
with the service information (sync headers) on disk. The probability
of encountering something that resembles a sync header was considered
to be way too low. Well, until somebody has encountered a hardware
glitch and a sync header fragment got mistakenly read from the drive
as part of some file. Now this corrupted file can wreak havoc if
written to a CD disk, because the false sync header in it is getting
interpreted as an actual sync header. Oops.

Anyway, this is a bug in the sun6i/sun8i dram code. And the submitted
patch appears to be only a partial/incomplete fix. A strong NAK from
me.

-- 
Best regards,
Siarhei Siamashka

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

* [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support
  2014-12-19 17:05     ` Hans de Goede
@ 2014-12-22  7:43       ` Siarhei Siamashka
  0 siblings, 0 replies; 54+ messages in thread
From: Siarhei Siamashka @ 2014-12-22  7:43 UTC (permalink / raw)
  To: u-boot

On Fri, 19 Dec 2014 18:05:49 +0100
Hans de Goede <hdegoede@redhat.com> wrote:

> Hi,
> 
> On 19-12-14 11:20, Siarhei Siamashka wrote:
> > On Tue, 16 Dec 2014 21:31:38 +0100
> > Hans de Goede <hdegoede@redhat.com> wrote:
> >
> >> Based on the register / dram_para headers from the Allwinner u-boot / linux
> >> sources + the init sequences from boot0.
> >
> > Can the commit message have more detailed information about the precise
> > location of the original Allwinner code, which was used as the
> > reference?
> 
> No, it cannot because no code was referenced, I traced the boot0 binary to
> figure out what was needed to get dram going on the A23.

Thanks for explaining. And good job extracting all the information
from there.

In this case, can we have a clear reference to this binary in the
commit message? It might be useful to have a look at objdump logs
when reviewing your patch.

[...]

> >> +++ b/arch/arm/cpu/armv7/sunxi/dram_sun8i.c
> >> @@ -0,0 +1,340 @@
> >> +/*
> >> + * Sun8i platform dram controller init.
> >> + *
> >> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
> >
> > Is Allwinner copyright really not necessary here?
> >
> >> + * SPDX-License-Identifier:	GPL-2.0+
> >> + */
> >> +
> >> +/*
> >> + * Note this code uses a lot of magic hex values, that is because this code
> >> + * simply replays the init sequence as done by the Allwinner boot0 code, so
> >> + * we do not know what these values mean. There are no symbolic constants for
> >> + * these magic values, since we do not know how to name them and making up
> >> + * names for them is not useful.
> >> + */
> >
> > You are well aware of this documentation since a long time ago, right?
> >     http://www.ti.com/lit/ug/spruhn7a/spruhn7a.pdf
> 
> I'm aware you've used various sources to figure out more about the A10
> dram controller, since this DRAM controller seems significantly different
> I assumed your sources would not apply, it is good to hear that they do.

I wonder how could you have ended up with this strange assumption?
When I clearly told you that "It looks like the Allwinner A31 DRAM
controller registers are very similar to what is used in RK3288" and
provided the links to the relevant sources and documentation back
in September:
    http://lists.denx.de/pipermail/u-boot/2014-September/189199.html

Then reminded yet again about this RK3288 similarity and used the
mctl_phy->ptr0 register as an example:
    http://lists.denx.de/pipermail/u-boot/2014-December/198582.html

When we were discussing the A31 DRAM controller, of course you should
have expected the information about A31.

Yes, A23 was not a part of the picture at that time. However comparing
its registers with the information from spruhn7a.pdf and various
Rockchip source code drops is a very natural thing to try.

So far the best matching pairs (almost 100% identical PHY) are:
   Allwinner A10 (sun4i) - RK29xx
   Allwinner A31 (sun6i) - RK3288
   Allwinner A23 (sun8i) - TI Keystone2

It's all the same family of DRAM controllers, very likely just
different revisions/generations from the same supplier. I don't
expect A80 or other Allwinner chips to be any different.

[...]

> >> +	else
> >> +		writel(0x1000040b, &mctl_phy->dcr);
> >
> > The bit 28 is marked as reserved and "Reads return zeros" in the
> > TI Keystone2 documentation. It's a nice chance to test whether
> > this write has any effect and whether it does modify the register.
> 
> It modifies the register, so that means that at least that bit does
> not match the TI Keystone2 documentation.

OK.

-- 
Best regards,
Siarhei Siamashka

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

* [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i
  2014-12-19 16:55     ` Hans de Goede
@ 2014-12-22 14:19       ` Ian Campbell
  2014-12-22 14:32         ` Siarhei Siamashka
  2014-12-22 15:47         ` Hans de Goede
  0 siblings, 2 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-22 14:19 UTC (permalink / raw)
  To: u-boot

On Fri, 2014-12-19 at 17:55 +0100, Hans de Goede wrote:
> Hi,
> 
> On 18-12-14 20:12, Ian Campbell wrote:
> > On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> >> The sun8i boot0 code fills the DRAM with a "random" pattern before comparing
> >> it at different offsets to do columns, etc. detection. The sun6i boot0 code
> >> does not do it, but it seems like a good idea to do this regardless.
> >
> > Is this the right way round?
> 
> Yes, while working on the sun8i code I noticed that it was prefilling memory
> before doing wrap-around checks like the sun6i code is doing too, and then I
> realized that the sun6i code was relying on whatever is in DRAM being random
> enough for its wrap-around tests to work, without ensuring it is random
> enough.
> 
> > The existing sun6i code (which you are
> > moving here) seems to _rely_ on something having written a useful
> > pattern, which I would have assumed to have been boot0. Or else how does
> > it work now? Chance?
> 
> Yep, it purely works by chance so far.

"excellent". Can you mention that in the commit message please. With
that: Acked-by: Ian Campbell <ijc@hellion.org.uk>

Ian.

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

* [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i
  2014-12-22 14:19       ` Ian Campbell
@ 2014-12-22 14:32         ` Siarhei Siamashka
  2014-12-22 14:34           ` Ian Campbell
  2014-12-22 15:47         ` Hans de Goede
  1 sibling, 1 reply; 54+ messages in thread
From: Siarhei Siamashka @ 2014-12-22 14:32 UTC (permalink / raw)
  To: u-boot

On Mon, 22 Dec 2014 14:19:20 +0000
Ian Campbell <ijc@hellion.org.uk> wrote:

> On Fri, 2014-12-19 at 17:55 +0100, Hans de Goede wrote:
> > Hi,
> > 
> > On 18-12-14 20:12, Ian Campbell wrote:
> > > On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> > >> The sun8i boot0 code fills the DRAM with a "random" pattern before comparing
> > >> it at different offsets to do columns, etc. detection. The sun6i boot0 code
> > >> does not do it, but it seems like a good idea to do this regardless.
> > >
> > > Is this the right way round?
> > 
> > Yes, while working on the sun8i code I noticed that it was prefilling memory
> > before doing wrap-around checks like the sun6i code is doing too, and then I
> > realized that the sun6i code was relying on whatever is in DRAM being random
> > enough for its wrap-around tests to work, without ensuring it is random
> > enough.
> > 
> > > The existing sun6i code (which you are
> > > moving here) seems to _rely_ on something having written a useful
> > > pattern, which I would have assumed to have been boot0. Or else how does
> > > it work now? Chance?
> > 
> > Yep, it purely works by chance so far.
> 
> "excellent". Can you mention that in the commit message please. With
> that: Acked-by: Ian Campbell <ijc@hellion.org.uk>

Ian, are you fine with the fact that it still works by chance
even after this "fix"? Albeit with a much higher chance of not
running into troubles.

-- 
Best regards,
Siarhei Siamashka

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

* [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i
  2014-12-22 14:32         ` Siarhei Siamashka
@ 2014-12-22 14:34           ` Ian Campbell
  0 siblings, 0 replies; 54+ messages in thread
From: Ian Campbell @ 2014-12-22 14:34 UTC (permalink / raw)
  To: u-boot

On Mon, 2014-12-22 at 16:32 +0200, Siarhei Siamashka wrote:
> On Mon, 22 Dec 2014 14:19:20 +0000
> Ian Campbell <ijc@hellion.org.uk> wrote:
> 
> > On Fri, 2014-12-19 at 17:55 +0100, Hans de Goede wrote:
> > > Hi,
> > > 
> > > On 18-12-14 20:12, Ian Campbell wrote:
> > > > On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
> > > >> The sun8i boot0 code fills the DRAM with a "random" pattern before comparing
> > > >> it at different offsets to do columns, etc. detection. The sun6i boot0 code
> > > >> does not do it, but it seems like a good idea to do this regardless.
> > > >
> > > > Is this the right way round?
> > > 
> > > Yes, while working on the sun8i code I noticed that it was prefilling memory
> > > before doing wrap-around checks like the sun6i code is doing too, and then I
> > > realized that the sun6i code was relying on whatever is in DRAM being random
> > > enough for its wrap-around tests to work, without ensuring it is random
> > > enough.
> > > 
> > > > The existing sun6i code (which you are
> > > > moving here) seems to _rely_ on something having written a useful
> > > > pattern, which I would have assumed to have been boot0. Or else how does
> > > > it work now? Chance?
> > > 
> > > Yep, it purely works by chance so far.
> > 
> > "excellent". Can you mention that in the commit message please. With
> > that: Acked-by: Ian Campbell <ijc@hellion.org.uk>
> 
> Ian, are you fine with the fact that it still works by chance
> even after this "fix"? Albeit with a much higher chance of not
> running into troubles.

Yes, it's clearly an improvement even if it isn't perfect.

Ian.

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

* [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i
  2014-12-22 14:19       ` Ian Campbell
  2014-12-22 14:32         ` Siarhei Siamashka
@ 2014-12-22 15:47         ` Hans de Goede
  1 sibling, 0 replies; 54+ messages in thread
From: Hans de Goede @ 2014-12-22 15:47 UTC (permalink / raw)
  To: u-boot

Hi,

On 22-12-14 15:19, Ian Campbell wrote:
> On Fri, 2014-12-19 at 17:55 +0100, Hans de Goede wrote:
>> Hi,
>>
>> On 18-12-14 20:12, Ian Campbell wrote:
>>> On Tue, 2014-12-16 at 21:31 +0100, Hans de Goede wrote:
>>>> The sun8i boot0 code fills the DRAM with a "random" pattern before comparing
>>>> it at different offsets to do columns, etc. detection. The sun6i boot0 code
>>>> does not do it, but it seems like a good idea to do this regardless.
>>>
>>> Is this the right way round?
>>
>> Yes, while working on the sun8i code I noticed that it was prefilling memory
>> before doing wrap-around checks like the sun6i code is doing too, and then I
>> realized that the sun6i code was relying on whatever is in DRAM being random
>> enough for its wrap-around tests to work, without ensuring it is random
>> enough.
>>
>>> The existing sun6i code (which you are
>>> moving here) seems to _rely_ on something having written a useful
>>> pattern, which I would have assumed to have been boot0. Or else how does
>>> it work now? Chance?
>>
>> Yep, it purely works by chance so far.
>
> "excellent". Can you mention that in the commit message please.

Done.

> With that: Acked-by: Ian Campbell <ijc@hellion.org.uk>

Thanks, the now fully acked sun8i support patch-set has been pushed to
u-boot-sunxi/next .

Thanks for all the reviews!

Regards,

Hans

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

end of thread, other threads:[~2014-12-22 15:47 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-16 20:31 [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Hans de Goede
2014-12-16 20:31 ` [U-Boot] [PATCH 02/14] sunxi: Add support for the rsb (Reduced Serial Bus) Hans de Goede
2014-12-17  2:22   ` Chen-Yu Tsai
2014-12-17 12:56     ` Hans de Goede
2014-12-18 18:57       ` Ian Campbell
2014-12-18 18:59       ` Ian Campbell
2014-12-19 15:26         ` Hans de Goede
2014-12-16 20:31 ` [U-Boot] [PATCH 03/14] sunxi: axp221: Add axp223 support Hans de Goede
2014-12-17  2:34   ` Chen-Yu Tsai
2014-12-18 10:44     ` Hans de Goede
2014-12-18 19:00   ` Ian Campbell
2014-12-16 20:31 ` [U-Boot] [PATCH 04/14] sunxi: axp221: Add Kconfig help and sane defaults for typical ldo usage Hans de Goede
2014-12-18 19:02   ` Ian Campbell
2014-12-16 20:31 ` [U-Boot] [PATCH 05/14] sunxi: axp221: Make dcdc1 voltage configurable Hans de Goede
2014-12-18 19:03   ` Ian Campbell
2014-12-16 20:31 ` [U-Boot] [PATCH 06/14] sunxi: axp221: Explicitly turn off unused voltages Hans de Goede
2014-12-18 19:04   ` Ian Campbell
2014-12-16 20:31 ` [U-Boot] [PATCH 07/14] sunxi: axp221: Disable dcdc4 on sun8i (A23) Hans de Goede
2014-12-18 19:05   ` Ian Campbell
2014-12-16 20:31 ` [U-Boot] [PATCH 08/14] sun6i: Add a sigma_delta_enable paramter to clock_set_pll5() Hans de Goede
2014-12-18 19:07   ` Ian Campbell
2014-12-19 10:02   ` Siarhei Siamashka
2014-12-16 20:31 ` [U-Boot] [PATCH 09/14] sun6i: Add k and m parameters " Hans de Goede
2014-12-18 19:07   ` Ian Campbell
2014-12-19 10:03   ` Siarhei Siamashka
2014-12-19 16:40     ` Hans de Goede
2014-12-22  7:25       ` Siarhei Siamashka
2014-12-16 20:31 ` [U-Boot] [PATCH 10/14] sunxi: Move await_completion dram helper to dram.h Hans de Goede
2014-12-18 19:08   ` Ian Campbell
2014-12-19 10:06   ` Siarhei Siamashka
2014-12-19 16:42     ` Hans de Goede
2014-12-22  7:28       ` Siarhei Siamashka
2014-12-16 20:31 ` [U-Boot] [PATCH 11/14] sunxi: Fill memory before comparing it when doing dram init on sun6i Hans de Goede
2014-12-18 19:12   ` Ian Campbell
2014-12-19 10:08     ` Siarhei Siamashka
2014-12-19 16:56       ` Hans de Goede
2014-12-22  7:39         ` Siarhei Siamashka
2014-12-19 16:55     ` Hans de Goede
2014-12-22 14:19       ` Ian Campbell
2014-12-22 14:32         ` Siarhei Siamashka
2014-12-22 14:34           ` Ian Campbell
2014-12-22 15:47         ` Hans de Goede
2014-12-16 20:31 ` [U-Boot] [PATCH 12/14] sunxi: Use memcmp for mctl_mem_matches Hans de Goede
2014-12-18 19:13   ` Ian Campbell
2014-12-16 20:31 ` [U-Boot] [PATCH 13/14] sun8i: Add dram initialization support Hans de Goede
2014-12-18 11:12   ` Chen-Yu Tsai
2014-12-18 19:17   ` Ian Campbell
2014-12-19 16:51     ` Hans de Goede
2014-12-19 10:20   ` Siarhei Siamashka
2014-12-19 17:05     ` Hans de Goede
2014-12-22  7:43       ` Siarhei Siamashka
2014-12-16 20:31 ` [U-Boot] [PATCH 14/14] sun8i: Add defconfig for Ippo_q8h v1.2 Hans de Goede
2014-12-18 19:19   ` Ian Campbell
2014-12-18 18:56 ` [U-Boot] [PATCH 01/14] sun6i: s/SUNXI_GPL0_R_P2WI/SUN6I_GPL0_R_P2WI/ Ian Campbell

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.