All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17] sunxi: Introduce H616 support
@ 2021-01-03  9:26 Jernej Skrabec
  2021-01-03  9:26 ` [PATCH 01/17] sunxi: Add support for AXP305 PMIC Jernej Skrabec
                   ` (16 more replies)
  0 siblings, 17 replies; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

This series introduces H616 support. Later patches add also OrangePi
Zero2 support but since H616 DT is not merged into Linux yet, I don't
expect them to land yet.

Patches 1-13 are ready to land, while 14-17 depends on non-upstreamed
DT yet.

This work relies on https://patchwork.ozlabs.org/project/uboot/list/?series=215309
otherwise image won't be built properly due to bigger SPL size.

Please take a look.

Best regards,
Jernej

Andre Przywara (2):
  sunxi: support loading with SPL > 32KB
  net: sun8i-emac: Determine pinmux based on SoC, not EMAC type

Jernej Skrabec (15):
  sunxi: Add support for AXP305 PMIC
  sunxi: Introduce common symbol for H6 like SoCs
  mmc: sunxi: Replace H6 ifdefs with H6 gen macro
  i2c: mvtwsi: sunxi: update macro
  sunxi: prcm: Add memory map for H6 like SoCs
  sunxi: Add support for I2C on H6 like SoCs
  sunxi: introduce support for H616 clocks
  sunxi: add support for H616 uart0
  sunxi: add support for R_I2C on H616
  sunxi: Add H616 DRAM support
  sunxi: Add support for H616 SoC
  arm: sunxi: add initial H616 DTSI and headers
  sunxi: gpio: introduce compatible for H616
  clk: sunxi: Add support for H616 clocks
  sunxi: Add support for OrangePi Zero2

 arch/arm/dts/Makefile                         |    2 +
 arch/arm/dts/sun50i-h616-orangepi-zero2.dts   |  240 ++++
 arch/arm/dts/sun50i-h616.dtsi                 |  716 ++++++++++++
 arch/arm/dts/sunxi-u-boot.dtsi                |    9 +
 arch/arm/include/asm/arch-sunxi/boot0.h       |    2 +-
 arch/arm/include/asm/arch-sunxi/clock.h       |    2 +-
 .../include/asm/arch-sunxi/clock_sun50i_h6.h  |   19 +-
 arch/arm/include/asm/arch-sunxi/cpu.h         |    2 +-
 .../include/asm/arch-sunxi/cpu_sun50i_h6.h    |    7 +
 arch/arm/include/asm/arch-sunxi/dram.h        |    2 +
 .../include/asm/arch-sunxi/dram_sun50i_h616.h |  159 +++
 arch/arm/include/asm/arch-sunxi/gpio.h        |    2 +
 arch/arm/include/asm/arch-sunxi/mmc.h         |    2 +-
 arch/arm/include/asm/arch-sunxi/prcm.h        |  249 +---
 arch/arm/include/asm/arch-sunxi/prcm_sun50i.h |   41 +
 arch/arm/include/asm/arch-sunxi/prcm_sun6i.h  |  247 ++++
 arch/arm/include/asm/arch-sunxi/timer.h       |    2 +-
 arch/arm/mach-sunxi/Kconfig                   |   77 +-
 arch/arm/mach-sunxi/Makefile                  |    4 +-
 arch/arm/mach-sunxi/board.c                   |   20 +-
 arch/arm/mach-sunxi/clock_sun50i_h6.c         |   39 +-
 arch/arm/mach-sunxi/cpu_info.c                |    2 +
 arch/arm/mach-sunxi/dram_sun50i_h616.c        | 1023 +++++++++++++++++
 arch/arm/mach-sunxi/dram_timings/Makefile     |    2 +
 .../mach-sunxi/dram_timings/h616_ddr3_1333.c  |   94 ++
 arch/arm/mach-sunxi/pmic_bus.c                |    6 +
 arch/arm/mach-sunxi/rmr_switch.S              |    2 +-
 board/sunxi/MAINTAINERS                       |    5 +
 board/sunxi/board.c                           |   14 +-
 common/spl/Kconfig                            |    4 +-
 configs/orangepi_zero2_defconfig              |   15 +
 drivers/clk/sunxi/Kconfig                     |    7 +
 drivers/clk/sunxi/Makefile                    |    1 +
 drivers/clk/sunxi/clk_h616.c                  |  120 ++
 drivers/gpio/sunxi_gpio.c                     |    1 +
 drivers/i2c/mvtwsi.c                          |    2 +-
 drivers/mmc/sunxi_mmc.c                       |   12 +-
 drivers/net/sun8i_emac.c                      |   28 +-
 drivers/power/Kconfig                         |   14 +-
 drivers/power/Makefile                        |    1 +
 drivers/power/axp305.c                        |   80 ++
 include/axp305.h                              |   17 +
 include/axp_pmic.h                            |    3 +
 include/configs/sun50i.h                      |    2 +-
 include/configs/sunxi-common.h                |   10 +
 include/dt-bindings/clock/sun50i-h616-ccu.h   |  115 ++
 include/dt-bindings/reset/sun50i-h616-ccu.h   |   70 ++
 47 files changed, 3211 insertions(+), 282 deletions(-)
 create mode 100644 arch/arm/dts/sun50i-h616-orangepi-zero2.dts
 create mode 100644 arch/arm/dts/sun50i-h616.dtsi
 create mode 100644 arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
 create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
 create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun6i.h
 create mode 100644 arch/arm/mach-sunxi/dram_sun50i_h616.c
 create mode 100644 arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
 create mode 100644 configs/orangepi_zero2_defconfig
 create mode 100644 drivers/clk/sunxi/clk_h616.c
 create mode 100644 drivers/power/axp305.c
 create mode 100644 include/axp305.h
 create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h

-- 
2.30.0

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

* [PATCH 01/17] sunxi: Add support for AXP305 PMIC
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-05 22:36   ` Jaehoon Chung
  2021-01-11  0:02   ` André Przywara
  2021-01-03  9:26 ` [PATCH 02/17] sunxi: Introduce common symbol for H6 like SoCs Jernej Skrabec
                   ` (15 subsequent siblings)
  16 siblings, 2 replies; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

This PMIC can be found on H616 boards and it's very similar to AXP805
and AXP806.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/mach-sunxi/pmic_bus.c |  6 +++
 board/sunxi/board.c            | 10 +++--
 drivers/power/Kconfig          | 13 +++++-
 drivers/power/Makefile         |  1 +
 drivers/power/axp305.c         | 80 ++++++++++++++++++++++++++++++++++
 include/axp305.h               | 17 ++++++++
 include/axp_pmic.h             |  3 ++
 7 files changed, 126 insertions(+), 4 deletions(-)
 create mode 100644 drivers/power/axp305.c
 create mode 100644 include/axp305.h

diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
index dea42de833f1..0394ce856448 100644
--- a/arch/arm/mach-sunxi/pmic_bus.c
+++ b/arch/arm/mach-sunxi/pmic_bus.c
@@ -18,6 +18,8 @@
 
 #define AXP209_I2C_ADDR			0x34
 
+#define AXP305_I2C_ADDR			0x36
+
 #define AXP221_CHIP_ADDR		0x68
 #define AXP221_CTRL_ADDR		0x3e
 #define AXP221_INIT_DATA		0x3e
@@ -64,6 +66,8 @@ int pmic_bus_read(u8 reg, u8 *data)
 	return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1);
 #elif defined CONFIG_AXP209_POWER
 	return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
+#elif defined CONFIG_AXP305_POWER
+	return i2c_read(AXP305_I2C_ADDR, reg, 1, data, 1);
 #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
 # ifdef CONFIG_MACH_SUN6I
 	return p2wi_read(reg, data);
@@ -81,6 +85,8 @@ int pmic_bus_write(u8 reg, u8 data)
 	return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1);
 #elif defined CONFIG_AXP209_POWER
 	return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
+#elif defined CONFIG_AXP305_POWER
+	return i2c_write(AXP305_I2C_ADDR, reg, 1, &data, 1);
 #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
 # ifdef CONFIG_MACH_SUN6I
 	return p2wi_write(reg, data);
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 708a27ed78e9..54ff9bc92396 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -634,16 +634,18 @@ void sunxi_board_init(void)
 #endif
 
 #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
-	defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
-	defined CONFIG_AXP818_POWER
+	defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
+	defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
 	power_failed = axp_init();
 
 #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
 	defined CONFIG_AXP818_POWER
 	power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
 #endif
+#if !defined(CONFIG_AXP305_POWER)
 	power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
 	power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
+#endif
 #if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
 	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
 #endif
@@ -656,8 +658,10 @@ void sunxi_board_init(void)
 	defined CONFIG_AXP818_POWER
 	power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
 #endif
+#if !defined(CONFIG_AXP305_POWER)
 	power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
-#if !defined(CONFIG_AXP152_POWER)
+#endif
+#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER)
 	power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
 #endif
 #ifdef CONFIG_AXP209_POWER
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 02050f6f3569..d17cf2d9112a 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -48,6 +48,15 @@ config AXP221_POWER
 	Select this to enable support for the axp221/axp223 pmic found on most
 	A23 and A31 boards.
 
+config AXP305_POWER
+	bool "axp305 pmic support"
+	depends on MACH_SUN50I_H616
+	select AXP_PMIC_BUS
+	select CMD_POWEROFF
+	---help---
+	Select this to enable support for the axp305 pmic found on most
+	H616 boards.
+
 config AXP809_POWER
 	bool "axp809 pmic support"
 	depends on MACH_SUN9I
@@ -127,11 +136,12 @@ config AXP_DCDC3_VOLT
 
 config AXP_DCDC4_VOLT
 	int "axp pmic dcdc4 voltage"
-	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
+	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP305_POWER
 	default 1250 if AXP152_POWER
 	default 1200 if MACH_SUN6I
 	default 0 if MACH_SUN8I
 	default 900 if MACH_SUN9I
+	default 1500 if AXP305_POWER
 	---help---
 	Set the voltage (mV) to program the axp pmic dcdc4 at, set to 0 to
 	disable dcdc4.
@@ -140,6 +150,7 @@ config AXP_DCDC4_VOLT
 	On A23 / A33 boards dcdc4 is unused and should be disabled.
 	On A80 boards dcdc4 powers VDD-SYS, HDMI, USB OTG and should be 0.9V.
 	On A83T boards dcdc4 is used for VDD-GPU.
+	On H616 boards dcdcd is used for VCC-DRAM.
 
 config AXP_DCDC5_VOLT
 	int "axp pmic dcdc5 voltage"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 2dcc7bb99d02..0bef06920a7d 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_AXP152_POWER)	+= axp152.o
 obj-$(CONFIG_AXP209_POWER)	+= axp209.o
 obj-$(CONFIG_AXP221_POWER)	+= axp221.o
+obj-$(CONFIG_AXP305_POWER)	+= axp305.o
 obj-$(CONFIG_AXP809_POWER)	+= axp809.o
 obj-$(CONFIG_AXP818_POWER)	+= axp818.o
 obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
diff --git a/drivers/power/axp305.c b/drivers/power/axp305.c
new file mode 100644
index 000000000000..f620798bb1d7
--- /dev/null
+++ b/drivers/power/axp305.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AXP305 driver
+ *
+ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * Based on axp221.c
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <asm/arch/pmic_bus.h>
+#include <axp_pmic.h>
+
+static u8 axp305_mvolt_to_cfg(int mvolt, int min, int max, int div)
+{
+	if (mvolt < min)
+		mvolt = min;
+	else if (mvolt > max)
+		mvolt = max;
+
+	return  (mvolt - min) / div;
+}
+
+int axp_set_dcdc4(unsigned int mvolt)
+{
+	int ret;
+	u8 cfg;
+
+	if (mvolt >= 1600)
+		cfg = 46 + axp305_mvolt_to_cfg(mvolt, 1600, 3300, 100);
+	else
+		cfg = axp305_mvolt_to_cfg(mvolt, 600, 1500, 20);
+
+	if (mvolt == 0)
+		return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1,
+					AXP305_OUTPUT_CTRL1_DCDCD_EN);
+
+	ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg);
+	if (ret)
+		return ret;
+
+	return pmic_bus_setbits(AXP305_OUTPUT_CTRL1,
+				AXP305_OUTPUT_CTRL1_DCDCD_EN);
+}
+
+int axp_init(void)
+{
+	u8 axp_chip_id;
+	int ret;
+
+	ret = pmic_bus_init();
+	if (ret)
+		return ret;
+
+	ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id);
+	if (ret)
+		return ret;
+
+	if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x40)
+		return -ENODEV;
+
+	return ret;
+}
+
+#ifndef CONFIG_PSCI_RESET
+int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	pmic_bus_write(AXP305_SHUTDOWN, AXP305_POWEROFF);
+
+	/* infinite loop during shutdown */
+	while (1) {}
+
+	/* not reached */
+	return 0;
+}
+#endif
diff --git a/include/axp305.h b/include/axp305.h
new file mode 100644
index 000000000000..225c5040a322
--- /dev/null
+++ b/include/axp305.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
+ */
+
+enum axp305_reg {
+	AXP305_CHIP_VERSION = 0x3,
+	AXP305_OUTPUT_CTRL1 = 0x10,
+	AXP305_DCDCD_VOLTAGE = 0x15,
+	AXP305_SHUTDOWN = 0x32,
+};
+
+#define AXP305_CHIP_VERSION_MASK	0xcf
+
+#define AXP305_OUTPUT_CTRL1_DCDCD_EN	(1 << 3)
+
+#define AXP305_POWEROFF			(1 << 7)
diff --git a/include/axp_pmic.h b/include/axp_pmic.h
index 10091d0bb278..405044c3a32f 100644
--- a/include/axp_pmic.h
+++ b/include/axp_pmic.h
@@ -15,6 +15,9 @@
 #ifdef CONFIG_AXP221_POWER
 #include <axp221.h>
 #endif
+#ifdef CONFIG_AXP305_POWER
+#include <axp305.h>
+#endif
 #ifdef CONFIG_AXP809_POWER
 #include <axp809.h>
 #endif
-- 
2.30.0

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

* [PATCH 02/17] sunxi: Introduce common symbol for H6 like SoCs
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
  2021-01-03  9:26 ` [PATCH 01/17] sunxi: Add support for AXP305 PMIC Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-03 23:43   ` [linux-sunxi] " Samuel Holland
  2021-01-03  9:26 ` [PATCH 03/17] mmc: sunxi: Replace H6 ifdefs with H6 gen macro Jernej Skrabec
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

It turns out that there are at least 2 other SoCs which have basically
the same memory map, similar clocks and other features as H6. It's very
likely that we'll see more such SoCs in the future. In order to ease
porting to new SoCs and lower ifdef clutter, introduce common symbol for
them.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/include/asm/arch-sunxi/boot0.h |  2 +-
 arch/arm/include/asm/arch-sunxi/clock.h |  2 +-
 arch/arm/include/asm/arch-sunxi/cpu.h   |  2 +-
 arch/arm/include/asm/arch-sunxi/timer.h |  2 +-
 arch/arm/mach-sunxi/Kconfig             | 21 +++++++++++++--------
 arch/arm/mach-sunxi/Makefile            |  2 +-
 arch/arm/mach-sunxi/board.c             |  4 ++--
 arch/arm/mach-sunxi/rmr_switch.S        |  2 +-
 common/spl/Kconfig                      |  4 ++--
 include/configs/sun50i.h                |  2 +-
 10 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
index 46d0f0666c2b..e8e8e38f0556 100644
--- a/arch/arm/include/asm/arch-sunxi/boot0.h
+++ b/arch/arm/include/asm/arch-sunxi/boot0.h
@@ -39,7 +39,7 @@
 	.word	0xf57ff06f	// isb     sy
 	.word	0xe320f003	// wfi
 	.word	0xeafffffd	// b       @wfi
-#ifndef CONFIG_MACH_SUN50I_H6
+#ifndef CONFIG_SUN50I_GEN_H6
 	.word	0x017000a0	// writeable RVBAR mapping address
 #else
 	.word	0x09010040	// writeable RVBAR mapping address
diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
index 5994130e6b54..cbbe5c7a1e68 100644
--- a/arch/arm/include/asm/arch-sunxi/clock.h
+++ b/arch/arm/include/asm/arch-sunxi/clock.h
@@ -16,7 +16,7 @@
 /* clock control module regs definition */
 #if defined(CONFIG_MACH_SUN8I_A83T)
 #include <asm/arch/clock_sun8i_a83t.h>
-#elif defined(CONFIG_MACH_SUN50I_H6)
+#elif defined(CONFIG_SUN50I_GEN_H6)
 #include <asm/arch/clock_sun50i_h6.h>
 #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
       defined(CONFIG_MACH_SUN50I)
diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
index 8b57d24e2f0c..b08f2023748c 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -8,7 +8,7 @@
 
 #if defined(CONFIG_MACH_SUN9I)
 #include <asm/arch/cpu_sun9i.h>
-#elif defined(CONFIG_MACH_SUN50I_H6)
+#elif defined(CONFIG_SUN50I_GEN_H6)
 #include <asm/arch/cpu_sun50i_h6.h>
 #else
 #include <asm/arch/cpu_sun4i.h>
diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h
index 6f138d04b806..bb5626d893bb 100644
--- a/arch/arm/include/asm/arch-sunxi/timer.h
+++ b/arch/arm/include/asm/arch-sunxi/timer.h
@@ -76,7 +76,7 @@ struct sunxi_timer_reg {
 	struct sunxi_tgp tgp[4];
 	u8 res5[8];
 	u32 cpu_cfg;
-#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
 	u8 res3[16];
 	struct sunxi_wdog wdog[5];	/* We have 5 watchdogs */
 #endif
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 49ef217f08c0..1cf79bad7cf6 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -82,7 +82,7 @@ config SUN8I_RSB
 config SUNXI_SRAM_ADDRESS
 	hex
 	default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
-	default 0x20000 if MACH_SUN50I_H6
+	default 0x20000 if SUN50I_GEN_H6
 	default 0x0
 	---help---
 	Older Allwinner SoCs have their mask boot ROM mapped just below 4GB,
@@ -108,6 +108,15 @@ config SUNXI_GEN_SUN6I
 	separate ahb reset control registers, custom pmic bus, new style
 	watchdog, etc.
 
+config SUN50I_GEN_H6
+	bool
+	select FIT
+	select SPL_LOAD_FIT
+	select SUPPORT_SPL
+	---help---
+	Select this for sunxi SoCs which have H6 like peripherals, clocks
+	and memory map.
+
 config SUNXI_DRAM_DW
 	bool
 	---help---
@@ -302,10 +311,7 @@ config MACH_SUN50I_H5
 config MACH_SUN50I_H6
 	bool "sun50i (Allwinner H6)"
 	select ARM64
-	select SUPPORT_SPL
-	select FIT
 	select PHY_SUN4I_USB
-	select SPL_LOAD_FIT
 	select DRAM_SUN50I_H6
 
 endchoice
@@ -540,7 +546,6 @@ config SYS_CLK_FREQ
 	default 816000000 if MACH_SUN50I || MACH_SUN50I_H5
 	default 1008000000 if MACH_SUN8I
 	default 1008000000 if MACH_SUN9I
-	default 888000000 if MACH_SUN50I_H6
 
 config SYS_CONFIG_NAME
 	default "sun4i" if MACH_SUN4I
@@ -756,7 +761,7 @@ config VIDEO_SUNXI
 	depends on !MACH_SUN8I_V3S
 	depends on !MACH_SUN9I
 	depends on !MACH_SUN50I
-	depends on !MACH_SUN50I_H6
+	depends on !SUN50I_GEN_H6
 	select VIDEO
 	imply VIDEO_DT_SIMPLEFB
 	default y
@@ -989,11 +994,11 @@ config SPL_STACK_R_ADDR
 	default 0x4fe00000 if MACH_SUN8I
 	default 0x2fe00000 if MACH_SUN9I
 	default 0x4fe00000 if MACH_SUN50I
-	default 0x4fe00000 if MACH_SUN50I_H6
+	default 0x4fe00000 if SUN50I_GEN_H6
 
 config SPL_SPI_SUNXI
 	bool "Support for SPI Flash on Allwinner SoCs in SPL"
-	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6
+	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6
 	help
 	  Enable support for SPI Flash. This option allows SPL to read from
 	  sunxi SPI Flash. It uses the same method as the boot ROM, so does
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index d129f334798b..b8aca43d6630 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -26,7 +26,7 @@ else
 obj-$(CONFIG_MACH_SUN8I)	+= clock_sun6i.o
 endif
 obj-$(CONFIG_MACH_SUN9I)	+= clock_sun9i.o gtbus_sun9i.o
-obj-$(CONFIG_MACH_SUN50I_H6)	+= clock_sun50i_h6.o
+obj-$(CONFIG_SUN50I_GEN_H6)	+= clock_sun50i_h6.o
 
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_DRAM_SUN4I)	+= dram_sun4i.o
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index f40fccd8f8b9..7a8b303f233c 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -144,7 +144,7 @@ static int gpio_init(void)
 #error Unsupported console port number. Please fix pin mux settings in board.c
 #endif
 
-#ifdef CONFIG_MACH_SUN50I_H6
+#ifdef CONFIG_SUN50I_GEN_H6
 	/* Update PIO power bias configuration by copy hardware detected value */
 	val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
 	writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
@@ -329,7 +329,7 @@ void reset_cpu(ulong addr)
 		/* sun5i sometimes gets stuck without this */
 		writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
 	}
-#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
 #if defined(CONFIG_MACH_SUN50I_H6)
 	/* WDOG is broken for some H6 rev. use the R_WDOG instead */
 	static const struct sunxi_wdog *wdog =
diff --git a/arch/arm/mach-sunxi/rmr_switch.S b/arch/arm/mach-sunxi/rmr_switch.S
index fafd306f95b1..33e55d496865 100644
--- a/arch/arm/mach-sunxi/rmr_switch.S
+++ b/arch/arm/mach-sunxi/rmr_switch.S
@@ -30,7 +30,7 @@
 
 .text
 
-#ifndef CONFIG_MACH_SUN50I_H6
+#ifndef CONFIG_SUN50I_GEN_H6
 	ldr	r1, =0x017000a0		@ MMIO mapped RVBAR[0] register
 #else
 	ldr	r1, =0x09010040		@ MMIO mapped RVBAR[0] register
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index d8086bd9e874..bed715774d81 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -150,7 +150,7 @@ config SPL_TEXT_BASE
 	hex "SPL Text Base"
 	default ISW_ENTRY_ADDR if AM43XX || AM33XX || OMAP54XX || ARCH_KEYSTONE
 	default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I
-	default 0x20060 if MACH_SUN50I_H6
+	default 0x20060 if SUN50I_GEN_H6
 	default 0x00060 if ARCH_SUNXI
 	default 0xfffc0000 if ARCH_ZYNQMP
 	default 0x0
@@ -459,7 +459,7 @@ config SPL_SHA512_SUPPORT
 config SPL_FIT_IMAGE_TINY
 	bool "Remove functionality from SPL FIT loading to reduce size"
 	depends on SPL_FIT
-	default y if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6
+	default y if MACH_SUN50I || MACH_SUN50I_H5 || SUN50I_GEN_H6
 	default y if ARCH_IMX8M
 	help
 	  Enable this to reduce the size of the FIT image loading code
diff --git a/include/configs/sun50i.h b/include/configs/sun50i.h
index e050a5299f3b..bc2e3a3d0088 100644
--- a/include/configs/sun50i.h
+++ b/include/configs/sun50i.h
@@ -10,7 +10,7 @@
  * A64 specific configuration
  */
 
-#ifndef CONFIG_MACH_SUN50I_H6
+#ifndef CONFIG_SUN50I_GEN_H6
 #define GICD_BASE		0x1c81000
 #define GICC_BASE		0x1c82000
 #else
-- 
2.30.0

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

* [PATCH 03/17] mmc: sunxi: Replace H6 ifdefs with H6 gen macro
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
  2021-01-03  9:26 ` [PATCH 01/17] sunxi: Add support for AXP305 PMIC Jernej Skrabec
  2021-01-03  9:26 ` [PATCH 02/17] sunxi: Introduce common symbol for H6 like SoCs Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-11  0:13   ` André Przywara
  2021-01-03  9:26 ` [PATCH 04/17] i2c: mvtwsi: sunxi: update macro Jernej Skrabec
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

It turns out that several SoCs share same mmc configuration as H6. In
order to lower ifdef clutter replace H6 specific macro with common one.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/include/asm/arch-sunxi/mmc.h |  2 +-
 drivers/mmc/sunxi_mmc.c               | 12 ++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
index f2deafddd202..340e25b04d2a 100644
--- a/arch/arm/include/asm/arch-sunxi/mmc.h
+++ b/arch/arm/include/asm/arch-sunxi/mmc.h
@@ -45,7 +45,7 @@ struct sunxi_mmc {
 	u32 chda;		/* 0x90 */
 	u32 cbda;		/* 0x94 */
 	u32 res2[26];
-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
 	u32 res3[17];
 	u32 samp_dl;
 	u32 res4[46];
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 0e03b07ce555..3767a39277c1 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -122,7 +122,7 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
 	if (IS_ENABLED(CONFIG_MACH_SUN8I_A83T) && priv->mmc_no != 2)
 		new_mode = false;
 
-#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6)
+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_SUN50I_GEN_H6)
 	calibrate = true;
 #endif
 
@@ -133,7 +133,7 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
 #ifdef CONFIG_MACH_SUN9I
 		pll = CCM_MMC_CTRL_PLL_PERIPH0;
 		pll_hz = clock_get_pll4_periph0();
-#elif defined(CONFIG_MACH_SUN50I_H6)
+#elif defined(CONFIG_SUN50I_GEN_H6)
 		pll = CCM_MMC_CTRL_PLL6X2;
 		pll_hz = clock_get_pll6() * 2;
 #else
@@ -249,7 +249,7 @@ static int mmc_config_clock(struct sunxi_mmc_priv *priv, struct mmc *mmc)
 	rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK;
 	writel(rval, &priv->reg->clkcr);
 
-#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6)
+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_SUN50I_GEN_H6)
 	/* A64 supports calibration of delays on MMC controller and we
 	 * have to set delay of zero before starting calibration.
 	 * Allwinner BSP driver sets a delay only in the case of
@@ -530,7 +530,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
 
 	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 	cfg->host_caps = MMC_MODE_4BIT;
-#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN50I_H6)
+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I) || defined(CONFIG_SUN50I_GEN_H6)
 	if (sdc_no == 2)
 		cfg->host_caps = MMC_MODE_8BIT;
 #endif
@@ -545,7 +545,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
 
 	/* config ahb clock */
 	debug("init mmc %d clock and io\n", sdc_no);
-#if !defined(CONFIG_MACH_SUN50I_H6)
+#if !defined(CONFIG_SUN50I_GEN_H6)
 	setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
 
 #ifdef CONFIG_SUNXI_GEN_SUN6I
@@ -557,7 +557,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
 	writel(SUNXI_MMC_COMMON_CLK_GATE | SUNXI_MMC_COMMON_RESET,
 	       SUNXI_MMC_COMMON_BASE + 4 * sdc_no);
 #endif
-#else /* CONFIG_MACH_SUN50I_H6 */
+#else /* CONFIG_SUN50I_GEN_H6 */
 	setbits_le32(&ccm->sd_gate_reset, 1 << sdc_no);
 	/* unassert reset */
 	setbits_le32(&ccm->sd_gate_reset, 1 << (RESET_SHIFT + sdc_no));
-- 
2.30.0

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

* [PATCH 04/17] i2c: mvtwsi: sunxi: update macro
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (2 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 03/17] mmc: sunxi: Replace H6 ifdefs with H6 gen macro Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-03 23:55   ` [linux-sunxi] " Samuel Holland
  2021-01-04  5:57   ` Heiko Schocher
  2021-01-03  9:26 ` [PATCH 05/17] sunxi: prcm: Add memory map for H6 like SoCs Jernej Skrabec
                   ` (12 subsequent siblings)
  16 siblings, 2 replies; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

While currently none of the newer Allwinner SoCs currently has I2C
support implemented in U-Boot, this will change soon. mvtwsi driver is
good as it is for them except one macro. Update it to be ready once I2C
support lands for those SoCs.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/i2c/mvtwsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c
index 14c594d648ba..36d0d1485277 100644
--- a/drivers/i2c/mvtwsi.c
+++ b/drivers/i2c/mvtwsi.c
@@ -121,7 +121,7 @@ enum mvtwsi_ctrl_register_fields {
  * on other platforms, it is a normal r/w bit, which is cleared by writing 0.
  */
 
-#ifdef CONFIG_SUNXI_GEN_SUN6I
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
 #define	MVTWSI_CONTROL_CLEAR_IFLG	0x00000008
 #else
 #define	MVTWSI_CONTROL_CLEAR_IFLG	0x00000000
-- 
2.30.0

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

* [PATCH 05/17] sunxi: prcm: Add memory map for H6 like SoCs
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (3 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 04/17] i2c: mvtwsi: sunxi: update macro Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-04  0:03   ` [linux-sunxi] " Samuel Holland
  2021-01-03  9:26 ` [PATCH 06/17] sunxi: Add support for I2C on " Jernej Skrabec
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

There was no need to have prcm definitions for H6 and similar SoCs till
now. However, support R_I2C will be needed soon in SPL.

Move old definitions to prcm_sun6i.h and add new ones in prcm_sun50i.h.
One of those files will be selected in common prcm.h based on defined
macros.

This commit doesn't do any functional change.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/include/asm/arch-sunxi/prcm.h        | 249 +-----------------
 arch/arm/include/asm/arch-sunxi/prcm_sun50i.h |  41 +++
 arch/arm/include/asm/arch-sunxi/prcm_sun6i.h  | 247 +++++++++++++++++
 3 files changed, 298 insertions(+), 239 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
 create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun6i.h

diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
index 767d1ff98d74..5106076f5e91 100644
--- a/arch/arm/include/asm/arch-sunxi/prcm.h
+++ b/arch/arm/include/asm/arch-sunxi/prcm.h
@@ -1,247 +1,18 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * Sunxi A31 Power Management Unit register definition.
+ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
  *
- * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
- * http://linux-sunxi.org
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- * Berg Xing <bergxing@allwinnertech.com>
- * Tom Cubie <tangliang@allwinnertech.com>
+ * Sunxi platform prcm register definition.
  */
 
 #ifndef _SUNXI_PRCM_H
 #define _SUNXI_PRCM_H
 
-#define __PRCM_CPUS_CFG_PRE(n) (((n) & 0x3) << 4)
-#define PRCM_CPUS_CFG_PRE_MASK __PRCM_CPUS_CFG_PRE(0x3)
-#define __PRCM_CPUS_CFG_PRE_DIV(n) (((n) >> 1) - 1)
-#define PRCM_CPUS_CFG_PRE_DIV(n) \
-	__PRCM_CPUS_CFG_PRE(__PRCM_CPUS_CFG_CLK_PRE(n))
-#define __PRCM_CPUS_CFG_POST(n) (((n) & 0x1f) << 8)
-#define PRCM_CPUS_CFG_POST_MASK __PRCM_CPUS_CFG_POST(0x1f)
-#define __PRCM_CPUS_CFG_POST_DIV(n) ((n) - 1)
-#define PRCM_CPUS_CFG_POST_DIV(n) \
-	__PRCM_CPUS_CFG_POST_DIV(__PRCM_CPUS_CFG_POST_DIV(n))
-#define __PRCM_CPUS_CFG_CLK_SRC(n) (((n) & 0x3) << 16)
-#define PRCM_CPUS_CFG_CLK_SRC_MASK __PRCM_CPUS_CFG_CLK_SRC(0x3)
-#define __PRCM_CPUS_CFG_CLK_SRC_LOSC 0x0
-#define __PRCM_CPUS_CFG_CLK_SRC_HOSC 0x1
-#define __PRCM_CPUS_CFG_CLK_SRC_PLL6 0x2
-#define __PRCM_CPUS_CFG_CLK_SRC_PDIV 0x3
-#define PRCM_CPUS_CFG_CLK_SRC_LOSC \
-	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_LOSC)
-#define PRCM_CPUS_CFG_CLK_SRC_HOSC \
-	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_HOSC)
-#define PRCM_CPUS_CFG_CLK_SRC_PLL6 \
-	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PLL6)
-#define PRCM_CPUS_CFG_CLK_SRC_PDIV \
-	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PDIV)
-
-#define __PRCM_APB0_RATIO(n) (((n) & 0x3) << 0)
-#define PRCM_APB0_RATIO_DIV_MASK __PRCM_APB0_RATIO_DIV(0x3)
-#define __PRCM_APB0_RATIO_DIV(n) (((n) >> 1) - 1)
-#define PRCM_APB0_RATIO_DIV(n) \
-	__PRCM_APB0_RATIO(__PRCM_APB0_RATIO_DIV(n))
-
-#define PRCM_CPU_CFG_NEON_CLK_EN (0x1 << 0)
-#define PRCM_CPU_CFG_CPU_CLK_EN (0x1 << 1)
-
-#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)		/* 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)
-
-#define PRCM_APB0_RESET_PIO (0x1 << 0)
-#define PRCM_APB0_RESET_IR (0x1 << 1)
-#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
-#define PRCM_APB0_RESET_P2WI (0x1 << 3)
-#define PRCM_APB0_RESET_UART (0x1 << 4)
-#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
-#define PRCM_APB0_RESET_I2C (0x1 << 6)
-
-#define PRCM_PLL_CTRL_PLL_BIAS (0x1 << 0)
-#define PRCM_PLL_CTRL_HOSC_GAIN_ENH (0x1 << 1)
-#define __PRCM_PLL_CTRL_USB_CLK_SRC(n) (((n) & 0x3) << 4)
-#define PRCM_PLL_CTRL_USB_CLK_SRC_MASK \
-	__PRCM_PLL_CTRL_USB_CLK_SRC(0x3)
-#define __PRCM_PLL_CTRL_USB_CLK_0 0x0
-#define __PRCM_PLL_CTRL_USB_CLK_1 0x1
-#define __PRCM_PLL_CTRL_USB_CLK_2 0x2
-#define __PRCM_PLL_CTRL_USB_CLK_3 0x3
-#define PRCM_PLL_CTRL_USB_CLK_0 \
-	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_0)
-#define PRCM_PLL_CTRL_USB_CLK_1 \
-	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_1)
-#define PRCM_PLL_CTRL_USB_CLK_2 \
-	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_2)
-#define PRCM_PLL_CTRL_USB_CLK_3 \
-	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_3)
-#define __PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) (((n) & 0x3) << 12)
-#define PRCM_PLL_CTRL_INT_PLL_IN_SEL_MASK \
-	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(0x3)
-#define PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) \
-	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(n)
-#define __PRCM_PLL_CTRL_HOSC_CLK_SEL(n) (((n) & 0x3) << 20)
-#define PRCM_PLL_CTRL_HOSC_CLK_SEL_MASK \
-	__PRCM_PLL_CTRL_HOSC_CLK_SEL(0x3)
-#define __PRCM_PLL_CTRL_HOSC_CLK_0 0x0
-#define __PRCM_PLL_CTRL_HOSC_CLK_1 0x1
-#define __PRCM_PLL_CTRL_HOSC_CLK_2 0x2
-#define __PRCM_PLL_CTRL_HOSC_CLK_3 0x3
-#define PRCM_PLL_CTRL_HOSC_CLK_0 \
-	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_0)
-#define PRCM_PLL_CTRL_HOSC_CLK_1 \
-	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_1)
-#define PRCM_PLL_CTRL_HOSC_CLK_2 \
-	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_2)
-#define PRCM_PLL_CTRL_HOSC_CLK_3 \
-	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_3)
-#define PRCM_PLL_CTRL_PLL_TST_SRC_EXT (0x1 << 24)
-#define PRCM_PLL_CTRL_LDO_DIGITAL_EN (0x1 << 0)
-#define PRCM_PLL_CTRL_LDO_ANALOG_EN (0x1 << 1)
-#define PRCM_PLL_CTRL_EXT_OSC_EN (0x1 << 2)
-#define PRCM_PLL_CTRL_CLK_TST_EN (0x1 << 3)
-#define PRCM_PLL_CTRL_IN_PWR_HIGH (0x1 << 15) /* 3.3 for hi 2.5 for lo */
-#define __PRCM_PLL_CTRL_VDD_LDO_OUT(n) (((n) & 0x7) << 16)
-#define PRCM_PLL_CTRL_LDO_OUT_MASK \
-	__PRCM_PLL_CTRL_LDO_OUT(0x7)
-/* When using the low voltage 20 mV steps, and high voltage 30 mV steps */
-#define PRCM_PLL_CTRL_LDO_OUT_L(n) \
-	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1000) / 20) & 0x7)
-#define PRCM_PLL_CTRL_LDO_OUT_H(n) \
-	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1160) / 30) & 0x7)
-#define PRCM_PLL_CTRL_LDO_OUT_LV(n) \
-	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 20) + 1000)
-#define PRCM_PLL_CTRL_LDO_OUT_HV(n) \
-	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 30) + 1160)
-#define PRCM_PLL_CTRL_LDO_KEY (0xa7 << 24)
-#define PRCM_PLL_CTRL_LDO_KEY_MASK (0xff << 24)
-
-#define PRCM_CLK_1WIRE_GATE (0x1 << 31)
-
-#define __PRCM_CLK_MOD0_M(n) (((n) & 0xf) << 0)
-#define PRCM_CLK_MOD0_M_MASK __PRCM_CLK_MOD0_M(0xf)
-#define __PRCM_CLK_MOD0_M_X(n) (n - 1)
-#define PRCM_CLK_MOD0_M(n) __PRCM_CLK_MOD0_M(__PRCM_CLK_MOD0_M_X(n))
-#define PRCM_CLK_MOD0_OUT_PHASE(n) (((n) & 0x7) << 8)
-#define PRCM_CLK_MOD0_OUT_PHASE_MASK(n) PRCM_CLK_MOD0_OUT_PHASE(0x7)
-#define _PRCM_CLK_MOD0_N(n) (((n) & 0x3) << 16)
-#define PRCM_CLK_MOD0_N_MASK __PRCM_CLK_MOD_N(0x3)
-#define __PRCM_CLK_MOD0_N_X(n) (((n) >> 1) - 1)
-#define PRCM_CLK_MOD0_N(n) __PRCM_CLK_MOD0_N(__PRCM_CLK_MOD0_N_X(n))
-#define PRCM_CLK_MOD0_SMPL_PHASE(n) (((n) & 0x7) << 20)
-#define PRCM_CLK_MOD0_SMPL_PHASE_MASK PRCM_CLK_MOD0_SMPL_PHASE(0x7)
-#define PRCM_CLK_MOD0_SRC_SEL(n) (((n) & 0x7) << 24)
-#define PRCM_CLK_MOD0_SRC_SEL_MASK PRCM_CLK_MOD0_SRC_SEL(0x7)
-#define PRCM_CLK_MOD0_GATE_EN (0x1 << 31)
-
-#define PRCM_APB0_RESET_PIO (0x1 << 0)
-#define PRCM_APB0_RESET_IR (0x1 << 1)
-#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
-#define PRCM_APB0_RESET_P2WI (0x1 << 3)
-#define PRCM_APB0_RESET_UART (0x1 << 4)
-#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
-#define PRCM_APB0_RESET_I2C (0x1 << 6)
-
-#define __PRCM_CLK_OUTD_M(n) (((n) & 0x7) << 8)
-#define PRCM_CLK_OUTD_M_MASK __PRCM_CLK_OUTD_M(0x7)
-#define __PRCM_CLK_OUTD_M_X() ((n) - 1)
-#define PRCM_CLK_OUTD_M(n) __PRCM_CLK_OUTD_M(__PRCM_CLK_OUTD_M_X(n))
-#define __PRCM_CLK_OUTD_N(n) (((n) & 0x7) << 20)
-#define PRCM_CLK_OUTD_N_MASK __PRCM_CLK_OUTD_N(0x7)
-#define __PRCM_CLK_OUTD_N_X(n) (((n) >> 1) - 1)
-#define PRCM_CLK_OUTD_N(n) __PRCM_CLK_OUTD_N(__PRCM_CLK_OUTD_N_X(n)
-#define __PRCM_CLK_OUTD_SRC_SEL(n) (((n) & 0x3) << 24)
-#define PRCM_CLK_OUTD_SRC_SEL_MASK __PRCM_CLK_OUTD_SRC_SEL(0x3)
-#define __PRCM_CLK_OUTD_SRC_LOSC2 0x0
-#define __PRCM_CLK_OUTD_SRC_LOSC 0x1
-#define __PRCM_CLK_OUTD_SRC_HOSC 0x2
-#define __PRCM_CLK_OUTD_SRC_ERR 0x3
-#define PRCM_CLK_OUTD_SRC_LOSC2 \
-#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC2)
-#define PRCM_CLK_OUTD_SRC_LOSC \
-#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC)
-#define PRCM_CLK_OUTD_SRC_HOSC \
-#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_HOSC)
-#define PRCM_CLK_OUTD_SRC_ERR \
-#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_ERR)
-#define PRCM_CLK_OUTD_EN (0x1 << 31)
-
-#define PRCM_CPU0_PWROFF (0x1 << 0)
-#define PRCM_CPU1_PWROFF (0x1 << 1)
-#define PRCM_CPU2_PWROFF (0x1 << 2)
-#define PRCM_CPU3_PWROFF (0x1 << 3)
-#define PRCM_CPU_ALL_PWROFF (0xf << 0)
-
-#define PRCM_VDD_SYS_DRAM_CH0_PAD_HOLD_PWROFF (0x1 << 0)
-#define PRCM_VDD_SYS_DRAM_CH1_PAD_HOLD_PWROFF (0x1 << 1)
-#define PRCM_VDD_SYS_AVCC_A_PWROFF (0x1 << 2)
-#define PRCM_VDD_SYS_CPU0_VDD_PWROFF (0x1 << 3)
-
-#define PRCM_VDD_GPU_PWROFF (0x1 << 0)
-
-#define PRCM_VDD_SYS_RESET (0x1 << 0)
-
-#define PRCM_CPU1_PWR_CLAMP(n) (((n) & 0xff) << 0)
-#define PRCM_CPU1_PWR_CLAMP_MASK PRCM_CPU1_PWR_CLAMP(0xff)
-
-#define PRCM_CPU2_PWR_CLAMP(n) (((n) & 0xff) << 0)
-#define PRCM_CPU2_PWR_CLAMP_MASK PRCM_CPU2_PWR_CLAMP(0xff)
-
-#define PRCM_CPU3_PWR_CLAMP(n) (((n) & 0xff) << 0)
-#define PRCM_CPU3_PWR_CLAMP_MASK PRCM_CPU3_PWR_CLAMP(0xff)
-
-#define PRCM_SEC_SWITCH_APB0_CLK_NONSEC (0x1 << 0)
-#define PRCM_SEC_SWITCH_PLL_CFG_NONSEC (0x1 << 1)
-#define PRCM_SEC_SWITCH_PWR_GATE_NONSEC (0x1 << 2)
-
-#ifndef __ASSEMBLY__
-#include <linux/compiler.h>
-
-struct sunxi_prcm_reg {
-	u32 cpus_cfg;		/* 0x000 */
-	u8 res0[0x8];		/* 0x004 */
-	u32 apb0_ratio;		/* 0x00c */
-	u32 cpu0_cfg;		/* 0x010 */
-	u32 cpu1_cfg;		/* 0x014 */
-	u32 cpu2_cfg;		/* 0x018 */
-	u32 cpu3_cfg;		/* 0x01c */
-	u8 res1[0x8];		/* 0x020 */
-	u32 apb0_gate;		/* 0x028 */
-	u8 res2[0x14];		/* 0x02c */
-	u32 pll_ctrl0;		/* 0x040 */
-	u32 pll_ctrl1;		/* 0x044 */
-	u8 res3[0x8];		/* 0x048 */
-	u32 clk_1wire;		/* 0x050 */
-	u32 clk_ir;		/* 0x054 */
-	u8 res4[0x58];		/* 0x058 */
-	u32 apb0_reset;		/* 0x0b0 */
-	u8 res5[0x3c];		/* 0x0b4 */
-	u32 clk_outd;		/* 0x0f0 */
-	u8 res6[0xc];		/* 0x0f4 */
-	u32 cpu_pwroff;		/* 0x100 */
-	u8 res7[0xc];		/* 0x104 */
-	u32 vdd_sys_pwroff;	/* 0x110 */
-	u8 res8[0x4];		/* 0x114 */
-	u32 gpu_pwroff;		/* 0x118 */
-	u8 res9[0x4];		/* 0x11c */
-	u32 vdd_pwr_reset;	/* 0x120 */
-	u8 res10[0x1c];		/* 0x124 */
-	u32 cpu_pwr_clamp[4];	/* 0x140 but first one is actually unused */
-	u8 res11[0x30];		/* 0x150 */
-	u32 dram_pwr;		/* 0x180 */
-	u8 res12[0xc];		/* 0x184 */
-	u32 dram_tst;		/* 0x190 */
-	u8 res13[0x3c];		/* 0x194 */
-	u32 prcm_sec_switch;	/* 0x1d0 */
-};
-
-void prcm_apb0_enable(u32 flags);
-void prcm_apb0_disable(u32 flags);
-
-#endif /* __ASSEMBLY__ */
-#endif /* _PRCM_H */
+/* prcm regs definition */
+#if defined(CONFIG_SUN50I_GEN_H6)
+#include <asm/arch/prcm_sun50i.h>
+#else
+#include <asm/arch/prcm_sun6i.h>
+#endif
+
+#endif /* _SUNXI_PRCM_H */
diff --git a/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h b/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
new file mode 100644
index 000000000000..68a78e50ce64
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Sunxi H6 Power Management Unit register definition.
+ *
+ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
+ */
+
+#ifndef _SUN50I_PRCM_H
+#define _SUN50I_PRCM_H
+
+#ifndef __ASSEMBLY__
+#include <linux/compiler.h>
+
+struct sunxi_prcm_reg {
+	u32 cpus_cfg;		/* 0x000 */
+	u8 res0[0x8];		/* 0x004 */
+	u32 apbs1_cfg;		/* 0x00c */
+	u32 apbs2_cfg;		/* 0x010 */
+	u8 res1[0x118];		/* 0x014 */
+	u32 wdg_gate_reset;	/* 0x12c */
+	u8 res2[0x6c];		/* 0x130 */
+	u32 twi_gate_reset;	/* 0x19c */
+	u8 res3[0x1c];		/* 0x1a0 */
+	u32 rsb_gate_reset;	/* 0x1bc */
+	u32 cir_cfg;		/* 0x1c0 */
+	u8 res4[0x8];		/* 0x1c4 */
+	u32 cir_gate_reset;	/* 0x1cc */
+	u8 res5[0x10];		/* 0x1d0 */
+	u32 w1_cfg;		/* 0x1e0 */
+	u8 res6[0x8];		/* 0x1e4 */
+	u32 w1_gate_reset;	/* 0x1ec */
+	u8 res7[0x1c];		/* 0x1f0 */
+	u32 rtc_gate_reset;	/* 0x20c */
+};
+check_member(sunxi_prcm_reg, rtc_gate_reset, 0x20c);
+
+#define PRCM_TWI_GATE		(1 << 0)
+#define PRCM_TWI_RESET		(1 << 16)
+
+#endif /* __ASSEMBLY__ */
+#endif /* _PRCM_H */
diff --git a/arch/arm/include/asm/arch-sunxi/prcm_sun6i.h b/arch/arm/include/asm/arch-sunxi/prcm_sun6i.h
new file mode 100644
index 000000000000..ab664e80bbe8
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/prcm_sun6i.h
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Sunxi A31 Power Management Unit register definition.
+ *
+ * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
+ * http://linux-sunxi.org
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Berg Xing <bergxing@allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ */
+
+#ifndef _SUN6I_PRCM_H
+#define _SUN6I_PRCM_H
+
+#define __PRCM_CPUS_CFG_PRE(n) (((n) & 0x3) << 4)
+#define PRCM_CPUS_CFG_PRE_MASK __PRCM_CPUS_CFG_PRE(0x3)
+#define __PRCM_CPUS_CFG_PRE_DIV(n) (((n) >> 1) - 1)
+#define PRCM_CPUS_CFG_PRE_DIV(n) \
+	__PRCM_CPUS_CFG_PRE(__PRCM_CPUS_CFG_CLK_PRE(n))
+#define __PRCM_CPUS_CFG_POST(n) (((n) & 0x1f) << 8)
+#define PRCM_CPUS_CFG_POST_MASK __PRCM_CPUS_CFG_POST(0x1f)
+#define __PRCM_CPUS_CFG_POST_DIV(n) ((n) - 1)
+#define PRCM_CPUS_CFG_POST_DIV(n) \
+	__PRCM_CPUS_CFG_POST_DIV(__PRCM_CPUS_CFG_POST_DIV(n))
+#define __PRCM_CPUS_CFG_CLK_SRC(n) (((n) & 0x3) << 16)
+#define PRCM_CPUS_CFG_CLK_SRC_MASK __PRCM_CPUS_CFG_CLK_SRC(0x3)
+#define __PRCM_CPUS_CFG_CLK_SRC_LOSC 0x0
+#define __PRCM_CPUS_CFG_CLK_SRC_HOSC 0x1
+#define __PRCM_CPUS_CFG_CLK_SRC_PLL6 0x2
+#define __PRCM_CPUS_CFG_CLK_SRC_PDIV 0x3
+#define PRCM_CPUS_CFG_CLK_SRC_LOSC \
+	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_LOSC)
+#define PRCM_CPUS_CFG_CLK_SRC_HOSC \
+	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_HOSC)
+#define PRCM_CPUS_CFG_CLK_SRC_PLL6 \
+	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PLL6)
+#define PRCM_CPUS_CFG_CLK_SRC_PDIV \
+	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PDIV)
+
+#define __PRCM_APB0_RATIO(n) (((n) & 0x3) << 0)
+#define PRCM_APB0_RATIO_DIV_MASK __PRCM_APB0_RATIO_DIV(0x3)
+#define __PRCM_APB0_RATIO_DIV(n) (((n) >> 1) - 1)
+#define PRCM_APB0_RATIO_DIV(n) \
+	__PRCM_APB0_RATIO(__PRCM_APB0_RATIO_DIV(n))
+
+#define PRCM_CPU_CFG_NEON_CLK_EN (0x1 << 0)
+#define PRCM_CPU_CFG_CPU_CLK_EN (0x1 << 1)
+
+#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)		/* 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)
+
+#define PRCM_APB0_RESET_PIO (0x1 << 0)
+#define PRCM_APB0_RESET_IR (0x1 << 1)
+#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
+#define PRCM_APB0_RESET_P2WI (0x1 << 3)
+#define PRCM_APB0_RESET_UART (0x1 << 4)
+#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
+#define PRCM_APB0_RESET_I2C (0x1 << 6)
+
+#define PRCM_PLL_CTRL_PLL_BIAS (0x1 << 0)
+#define PRCM_PLL_CTRL_HOSC_GAIN_ENH (0x1 << 1)
+#define __PRCM_PLL_CTRL_USB_CLK_SRC(n) (((n) & 0x3) << 4)
+#define PRCM_PLL_CTRL_USB_CLK_SRC_MASK \
+	__PRCM_PLL_CTRL_USB_CLK_SRC(0x3)
+#define __PRCM_PLL_CTRL_USB_CLK_0 0x0
+#define __PRCM_PLL_CTRL_USB_CLK_1 0x1
+#define __PRCM_PLL_CTRL_USB_CLK_2 0x2
+#define __PRCM_PLL_CTRL_USB_CLK_3 0x3
+#define PRCM_PLL_CTRL_USB_CLK_0 \
+	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_0)
+#define PRCM_PLL_CTRL_USB_CLK_1 \
+	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_1)
+#define PRCM_PLL_CTRL_USB_CLK_2 \
+	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_2)
+#define PRCM_PLL_CTRL_USB_CLK_3 \
+	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_3)
+#define __PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) (((n) & 0x3) << 12)
+#define PRCM_PLL_CTRL_INT_PLL_IN_SEL_MASK \
+	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(0x3)
+#define PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) \
+	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(n)
+#define __PRCM_PLL_CTRL_HOSC_CLK_SEL(n) (((n) & 0x3) << 20)
+#define PRCM_PLL_CTRL_HOSC_CLK_SEL_MASK \
+	__PRCM_PLL_CTRL_HOSC_CLK_SEL(0x3)
+#define __PRCM_PLL_CTRL_HOSC_CLK_0 0x0
+#define __PRCM_PLL_CTRL_HOSC_CLK_1 0x1
+#define __PRCM_PLL_CTRL_HOSC_CLK_2 0x2
+#define __PRCM_PLL_CTRL_HOSC_CLK_3 0x3
+#define PRCM_PLL_CTRL_HOSC_CLK_0 \
+	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_0)
+#define PRCM_PLL_CTRL_HOSC_CLK_1 \
+	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_1)
+#define PRCM_PLL_CTRL_HOSC_CLK_2 \
+	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_2)
+#define PRCM_PLL_CTRL_HOSC_CLK_3 \
+	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_3)
+#define PRCM_PLL_CTRL_PLL_TST_SRC_EXT (0x1 << 24)
+#define PRCM_PLL_CTRL_LDO_DIGITAL_EN (0x1 << 0)
+#define PRCM_PLL_CTRL_LDO_ANALOG_EN (0x1 << 1)
+#define PRCM_PLL_CTRL_EXT_OSC_EN (0x1 << 2)
+#define PRCM_PLL_CTRL_CLK_TST_EN (0x1 << 3)
+#define PRCM_PLL_CTRL_IN_PWR_HIGH (0x1 << 15) /* 3.3 for hi 2.5 for lo */
+#define __PRCM_PLL_CTRL_VDD_LDO_OUT(n) (((n) & 0x7) << 16)
+#define PRCM_PLL_CTRL_LDO_OUT_MASK \
+	__PRCM_PLL_CTRL_LDO_OUT(0x7)
+/* When using the low voltage 20 mV steps, and high voltage 30 mV steps */
+#define PRCM_PLL_CTRL_LDO_OUT_L(n) \
+	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1000) / 20) & 0x7)
+#define PRCM_PLL_CTRL_LDO_OUT_H(n) \
+	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1160) / 30) & 0x7)
+#define PRCM_PLL_CTRL_LDO_OUT_LV(n) \
+	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 20) + 1000)
+#define PRCM_PLL_CTRL_LDO_OUT_HV(n) \
+	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 30) + 1160)
+#define PRCM_PLL_CTRL_LDO_KEY (0xa7 << 24)
+#define PRCM_PLL_CTRL_LDO_KEY_MASK (0xff << 24)
+
+#define PRCM_CLK_1WIRE_GATE (0x1 << 31)
+
+#define __PRCM_CLK_MOD0_M(n) (((n) & 0xf) << 0)
+#define PRCM_CLK_MOD0_M_MASK __PRCM_CLK_MOD0_M(0xf)
+#define __PRCM_CLK_MOD0_M_X(n) (n - 1)
+#define PRCM_CLK_MOD0_M(n) __PRCM_CLK_MOD0_M(__PRCM_CLK_MOD0_M_X(n))
+#define PRCM_CLK_MOD0_OUT_PHASE(n) (((n) & 0x7) << 8)
+#define PRCM_CLK_MOD0_OUT_PHASE_MASK(n) PRCM_CLK_MOD0_OUT_PHASE(0x7)
+#define _PRCM_CLK_MOD0_N(n) (((n) & 0x3) << 16)
+#define PRCM_CLK_MOD0_N_MASK __PRCM_CLK_MOD_N(0x3)
+#define __PRCM_CLK_MOD0_N_X(n) (((n) >> 1) - 1)
+#define PRCM_CLK_MOD0_N(n) __PRCM_CLK_MOD0_N(__PRCM_CLK_MOD0_N_X(n))
+#define PRCM_CLK_MOD0_SMPL_PHASE(n) (((n) & 0x7) << 20)
+#define PRCM_CLK_MOD0_SMPL_PHASE_MASK PRCM_CLK_MOD0_SMPL_PHASE(0x7)
+#define PRCM_CLK_MOD0_SRC_SEL(n) (((n) & 0x7) << 24)
+#define PRCM_CLK_MOD0_SRC_SEL_MASK PRCM_CLK_MOD0_SRC_SEL(0x7)
+#define PRCM_CLK_MOD0_GATE_EN (0x1 << 31)
+
+#define PRCM_APB0_RESET_PIO (0x1 << 0)
+#define PRCM_APB0_RESET_IR (0x1 << 1)
+#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
+#define PRCM_APB0_RESET_P2WI (0x1 << 3)
+#define PRCM_APB0_RESET_UART (0x1 << 4)
+#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
+#define PRCM_APB0_RESET_I2C (0x1 << 6)
+
+#define __PRCM_CLK_OUTD_M(n) (((n) & 0x7) << 8)
+#define PRCM_CLK_OUTD_M_MASK __PRCM_CLK_OUTD_M(0x7)
+#define __PRCM_CLK_OUTD_M_X() ((n) - 1)
+#define PRCM_CLK_OUTD_M(n) __PRCM_CLK_OUTD_M(__PRCM_CLK_OUTD_M_X(n))
+#define __PRCM_CLK_OUTD_N(n) (((n) & 0x7) << 20)
+#define PRCM_CLK_OUTD_N_MASK __PRCM_CLK_OUTD_N(0x7)
+#define __PRCM_CLK_OUTD_N_X(n) (((n) >> 1) - 1)
+#define PRCM_CLK_OUTD_N(n) __PRCM_CLK_OUTD_N(__PRCM_CLK_OUTD_N_X(n)
+#define __PRCM_CLK_OUTD_SRC_SEL(n) (((n) & 0x3) << 24)
+#define PRCM_CLK_OUTD_SRC_SEL_MASK __PRCM_CLK_OUTD_SRC_SEL(0x3)
+#define __PRCM_CLK_OUTD_SRC_LOSC2 0x0
+#define __PRCM_CLK_OUTD_SRC_LOSC 0x1
+#define __PRCM_CLK_OUTD_SRC_HOSC 0x2
+#define __PRCM_CLK_OUTD_SRC_ERR 0x3
+#define PRCM_CLK_OUTD_SRC_LOSC2 \
+#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC2)
+#define PRCM_CLK_OUTD_SRC_LOSC \
+#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC)
+#define PRCM_CLK_OUTD_SRC_HOSC \
+#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_HOSC)
+#define PRCM_CLK_OUTD_SRC_ERR \
+#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_ERR)
+#define PRCM_CLK_OUTD_EN (0x1 << 31)
+
+#define PRCM_CPU0_PWROFF (0x1 << 0)
+#define PRCM_CPU1_PWROFF (0x1 << 1)
+#define PRCM_CPU2_PWROFF (0x1 << 2)
+#define PRCM_CPU3_PWROFF (0x1 << 3)
+#define PRCM_CPU_ALL_PWROFF (0xf << 0)
+
+#define PRCM_VDD_SYS_DRAM_CH0_PAD_HOLD_PWROFF (0x1 << 0)
+#define PRCM_VDD_SYS_DRAM_CH1_PAD_HOLD_PWROFF (0x1 << 1)
+#define PRCM_VDD_SYS_AVCC_A_PWROFF (0x1 << 2)
+#define PRCM_VDD_SYS_CPU0_VDD_PWROFF (0x1 << 3)
+
+#define PRCM_VDD_GPU_PWROFF (0x1 << 0)
+
+#define PRCM_VDD_SYS_RESET (0x1 << 0)
+
+#define PRCM_CPU1_PWR_CLAMP(n) (((n) & 0xff) << 0)
+#define PRCM_CPU1_PWR_CLAMP_MASK PRCM_CPU1_PWR_CLAMP(0xff)
+
+#define PRCM_CPU2_PWR_CLAMP(n) (((n) & 0xff) << 0)
+#define PRCM_CPU2_PWR_CLAMP_MASK PRCM_CPU2_PWR_CLAMP(0xff)
+
+#define PRCM_CPU3_PWR_CLAMP(n) (((n) & 0xff) << 0)
+#define PRCM_CPU3_PWR_CLAMP_MASK PRCM_CPU3_PWR_CLAMP(0xff)
+
+#define PRCM_SEC_SWITCH_APB0_CLK_NONSEC (0x1 << 0)
+#define PRCM_SEC_SWITCH_PLL_CFG_NONSEC (0x1 << 1)
+#define PRCM_SEC_SWITCH_PWR_GATE_NONSEC (0x1 << 2)
+
+#ifndef __ASSEMBLY__
+#include <linux/compiler.h>
+
+struct sunxi_prcm_reg {
+	u32 cpus_cfg;		/* 0x000 */
+	u8 res0[0x8];		/* 0x004 */
+	u32 apb0_ratio;		/* 0x00c */
+	u32 cpu0_cfg;		/* 0x010 */
+	u32 cpu1_cfg;		/* 0x014 */
+	u32 cpu2_cfg;		/* 0x018 */
+	u32 cpu3_cfg;		/* 0x01c */
+	u8 res1[0x8];		/* 0x020 */
+	u32 apb0_gate;		/* 0x028 */
+	u8 res2[0x14];		/* 0x02c */
+	u32 pll_ctrl0;		/* 0x040 */
+	u32 pll_ctrl1;		/* 0x044 */
+	u8 res3[0x8];		/* 0x048 */
+	u32 clk_1wire;		/* 0x050 */
+	u32 clk_ir;		/* 0x054 */
+	u8 res4[0x58];		/* 0x058 */
+	u32 apb0_reset;		/* 0x0b0 */
+	u8 res5[0x3c];		/* 0x0b4 */
+	u32 clk_outd;		/* 0x0f0 */
+	u8 res6[0xc];		/* 0x0f4 */
+	u32 cpu_pwroff;		/* 0x100 */
+	u8 res7[0xc];		/* 0x104 */
+	u32 vdd_sys_pwroff;	/* 0x110 */
+	u8 res8[0x4];		/* 0x114 */
+	u32 gpu_pwroff;		/* 0x118 */
+	u8 res9[0x4];		/* 0x11c */
+	u32 vdd_pwr_reset;	/* 0x120 */
+	u8 res10[0x1c];		/* 0x124 */
+	u32 cpu_pwr_clamp[4];	/* 0x140 but first one is actually unused */
+	u8 res11[0x30];		/* 0x150 */
+	u32 dram_pwr;		/* 0x180 */
+	u8 res12[0xc];		/* 0x184 */
+	u32 dram_tst;		/* 0x190 */
+	u8 res13[0x3c];		/* 0x194 */
+	u32 prcm_sec_switch;	/* 0x1d0 */
+};
+
+void prcm_apb0_enable(u32 flags);
+void prcm_apb0_disable(u32 flags);
+
+#endif /* __ASSEMBLY__ */
+#endif /* _PRCM_H */
-- 
2.30.0

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

* [PATCH 06/17] sunxi: Add support for I2C on H6 like SoCs
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (4 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 05/17] sunxi: prcm: Add memory map for H6 like SoCs Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-04  0:04   ` [linux-sunxi] " Samuel Holland
  2021-01-03  9:26 ` [PATCH 07/17] sunxi: support loading with SPL > 32KB Jernej Skrabec
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

I2C support, especially R_I2C port, will be needed in future. Upcoming
support for H616 will need R_I2C to adjust DRAM voltage.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 .../include/asm/arch-sunxi/clock_sun50i_h6.h  |  1 +
 arch/arm/mach-sunxi/Kconfig                   |  2 +-
 arch/arm/mach-sunxi/clock_sun50i_h6.c         | 29 +++++++++++++++++++
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
index 426069fc69a4..e83e84ab6cab 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
@@ -297,6 +297,7 @@ struct sunxi_ccm_reg {
 
 /* Module gate/reset shift*/
 #define RESET_SHIFT			(16)
+#define GATE_SHIFT			(0)
 
 /* DRAM clock bit field */
 #define DRAM_MOD_RESET			BIT(30)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 1cf79bad7cf6..69ab670abf39 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -728,7 +728,7 @@ config I2C3_ENABLE
 	See I2C0_ENABLE help text.
 endif
 
-if SUNXI_GEN_SUN6I
+if SUNXI_GEN_SUN6I || SUN50I_GEN_H6
 config R_I2C_ENABLE
 	bool "Enable the PRCM I2C/TWI controller"
 	# This is used for the pmic on H3
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index ba8a26eb0d36..6bd466915c11 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -2,6 +2,7 @@
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/prcm.h>
 
 #ifdef CONFIG_SPL_BUILD
 void clock_init_safe(void)
@@ -92,3 +93,31 @@ unsigned int clock_get_pll6(void)
 	/* The register defines PLL6-4X, not plain PLL6 */
 	return 24000000 / 4 * n / div1 / div2;
 }
+
+int clock_twi_onoff(int port, int state)
+{
+	struct sunxi_ccm_reg *const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	struct sunxi_prcm_reg *const prcm =
+		(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+	u32 value, *ptr;
+	int shift;
+
+	value = BIT(GATE_SHIFT) | BIT (RESET_SHIFT);
+
+	if (port == 5) {
+		shift = 0;
+		ptr = &prcm->twi_gate_reset;
+	} else {
+		shift = port;
+		ptr = &ccm->twi_gate_reset;
+	}
+
+	/* set the apb clock gate and reset for twi */
+	if (state)
+		setbits_le32(ptr, value << shift);
+	else
+		clrbits_le32(ptr, value << shift);
+
+	return 0;
+}
-- 
2.30.0

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

* [PATCH 07/17] sunxi: support loading with SPL > 32KB
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (5 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 06/17] sunxi: Add support for I2C on " Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-04  2:02   ` [linux-sunxi] " Samuel Holland
  2021-01-03  9:26 ` [PATCH 08/17] sunxi: introduce support for H616 clocks Jernej Skrabec
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

From: Andre Przywara <andre.przywara@arm.com>

H616 supports and needs bigger SPL than 32 KiB, mostly due to big DRAM
driver and need for PMIC configuration, which pull several drivers which
are not needed otherwise.

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

diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 7a8b303f233c..296efd615769 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -277,6 +277,14 @@ uint32_t sunxi_get_boot_device(void)
 }
 
 #ifdef CONFIG_SPL_BUILD
+static u32 sunxi_get_spl_size(void)
+{
+	if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */
+		return 32768;
+
+	return readl(SPL_ADDR + 0x10);
+}
+
 /*
  * The eGON SPL image can be located at 8KB or at 128KB into an SD card or
  * an eMMC device. The boot source has bit 4 set in the latter case.
@@ -286,6 +294,7 @@ uint32_t sunxi_get_boot_device(void)
 unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc)
 {
 	unsigned long sector = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR;
+	u32 spl_size = sunxi_get_spl_size();
 
 	switch (sunxi_get_boot_source()) {
 	case SUNXI_BOOTED_FROM_MMC0_HIGH:
@@ -294,6 +303,9 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc)
 		break;
 	}
 
+	if (spl_size > 32768)
+		sector += (spl_size - 32768) / 512;
+
 	return sector;
 }
 
-- 
2.30.0

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

* [PATCH 08/17] sunxi: introduce support for H616 clocks
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (6 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 07/17] sunxi: support loading with SPL > 32KB Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-04  2:28   ` [linux-sunxi] " Samuel Holland
  2021-01-03  9:26 ` [PATCH 09/17] sunxi: add support for H616 uart0 Jernej Skrabec
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

H616 has mostly the same clocks as H6 with some small differences. Just
reuse H6 clocks for H616 and handle differences with macros.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 .../include/asm/arch-sunxi/clock_sun50i_h6.h   | 18 +++++++++++++++++-
 arch/arm/mach-sunxi/clock_sun50i_h6.c          | 10 +++++++++-
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
index e83e84ab6cab..62abfc4ef6bd 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
@@ -230,6 +230,7 @@ struct sunxi_ccm_reg {
 #define CCM_PLL1_CTRL_EN		BIT(31)
 #define CCM_PLL1_LOCK_EN		BIT(29)
 #define CCM_PLL1_LOCK			BIT(28)
+#define CCM_PLL1_OUT_EN			BIT(27)
 #define CCM_PLL1_CLOCK_TIME_2		(2 << 24)
 #define CCM_PLL1_CTRL_P(p)		((p) << 16)
 #define CCM_PLL1_CTRL_N(n)		((n) << 8)
@@ -238,6 +239,7 @@ struct sunxi_ccm_reg {
 #define CCM_PLL5_CTRL_EN		BIT(31)
 #define CCM_PLL5_LOCK_EN		BIT(29)
 #define CCM_PLL5_LOCK			BIT(28)
+#define CCM_PLL5_OUT_EN			BIT(27)
 #define CCM_PLL5_CTRL_N(n)		((n) << 8)
 #define CCM_PLL5_CTRL_DIV1(div1)	((div1) << 0)
 #define CCM_PLL5_CTRL_DIV2(div0)	((div0) << 1)
@@ -252,7 +254,6 @@ struct sunxi_ccm_reg {
 #define CCM_PLL6_CTRL_DIV1_MASK		(0x1 << CCM_PLL6_CTRL_DIV1_SHIFT)
 #define CCM_PLL6_CTRL_DIV2_SHIFT	1
 #define CCM_PLL6_CTRL_DIV2_MASK		(0x1 << CCM_PLL6_CTRL_DIV2_SHIFT)
-#define CCM_PLL6_DEFAULT		0xa0006300
 
 /* cpu_axi bit field*/
 #define CCM_CPU_AXI_MUX_MASK		(0x3 << 24)
@@ -262,6 +263,9 @@ struct sunxi_ccm_reg {
 #define CCM_CPU_AXI_AXI_MASK		0x3
 #define CCM_CPU_AXI_DEFAULT_FACTORS	0x301
 
+#ifdef CONFIG_MACH_SUN50I_H6
+#define CCM_PLL6_DEFAULT		0xa0006300
+
 /* psi_ahb1_ahb2 bit field */
 #define CCM_PSI_AHB1_AHB2_DEFAULT	0x03000102
 
@@ -270,6 +274,18 @@ struct sunxi_ccm_reg {
 
 /* apb1 bit field */
 #define CCM_APB1_DEFAULT		0x03000102
+#elif CONFIG_MACH_SUN50I_H616
+#define CCM_PLL6_DEFAULT		0xa8003100
+
+/* psi_ahb1_ahb2 bit field */
+#define CCM_PSI_AHB1_AHB2_DEFAULT	0x03000002
+
+/* ahb3 bit field */
+#define CCM_AHB3_DEFAULT		0x03000002
+
+/* apb1 bit field */
+#define CCM_APB1_DEFAULT		0x03000102
+#endif
 
 /* apb2 bit field */
 #define APB2_CLK_SRC_OSC24M		(0x0 << 24)
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index 6bd466915c11..a4cc1b53728b 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -68,6 +68,9 @@ void clock_set_pll1(unsigned int clk)
 
 	/* clk = 24*n/p, p is ignored if clock is >288MHz */
 	writel(CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2 |
+#ifdef CONFIG_MACH_SUN50I_H616
+	       CCM_PLL1_OUT_EN |
+#endif
 	       CCM_PLL1_CTRL_N(clk / 24000000), &ccm->pll1_cfg);
 	while (!(readl(&ccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
 
@@ -83,6 +86,11 @@ unsigned int clock_get_pll6(void)
 {
 	struct sunxi_ccm_reg *const ccm =
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+#ifdef CONFIG_MACH_SUN50I_H6
+	int m = 4;
+#else
+	int m = 2;
+#endif
 
 	uint32_t rval = readl(&ccm->pll6_cfg);
 	int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT);
@@ -91,7 +99,7 @@ unsigned int clock_get_pll6(void)
 	int div2 = ((rval & CCM_PLL6_CTRL_DIV2_MASK) >>
 			CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
 	/* The register defines PLL6-4X, not plain PLL6 */
-	return 24000000 / 4 * n / div1 / div2;
+	return 24000000 / m * n / div1 / div2;
 }
 
 int clock_twi_onoff(int port, int state)
-- 
2.30.0

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

* [PATCH 09/17] sunxi: add support for H616 uart0
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (7 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 08/17] sunxi: introduce support for H616 clocks Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-04  2:30   ` [linux-sunxi] " Samuel Holland
  2021-01-03  9:26 ` [PATCH 10/17] sunxi: add support for R_I2C on H616 Jernej Skrabec
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

This port is used for debug terminal on all known H616 boards.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/include/asm/arch-sunxi/gpio.h | 1 +
 arch/arm/mach-sunxi/board.c            | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index f817d328f432..cdb7dbd5b8e5 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -206,6 +206,7 @@ enum sunxi_gpio_number {
 #define SUN6I_GPH_UART0		2
 #define SUN9I_GPH_UART0		2
 #define SUN50I_H6_GPH_UART0	2
+#define SUN50I_H616_GPH_UART0	2
 
 #define SUNXI_GPI_SDC3		2
 #define SUN7I_GPI_TWI3		3
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 296efd615769..2dece395aa7c 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -116,6 +116,10 @@ static int gpio_init(void)
 	sunxi_gpio_set_cfgpin(SUNXI_GPH(0), SUN50I_H6_GPH_UART0);
 	sunxi_gpio_set_cfgpin(SUNXI_GPH(1), SUN50I_H6_GPH_UART0);
 	sunxi_gpio_set_pull(SUNXI_GPH(1), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN50I_H616)
+	sunxi_gpio_set_cfgpin(SUNXI_GPH(0), SUN50I_H616_GPH_UART0);
+	sunxi_gpio_set_cfgpin(SUNXI_GPH(1), SUN50I_H616_GPH_UART0);
+	sunxi_gpio_set_pull(SUNXI_GPH(1), SUNXI_GPIO_PULL_UP);
 #elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_A83T)
 	sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN8I_A83T_GPB_UART0);
 	sunxi_gpio_set_cfgpin(SUNXI_GPB(10), SUN8I_A83T_GPB_UART0);
-- 
2.30.0

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

* [PATCH 10/17] sunxi: add support for R_I2C on H616
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (8 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 09/17] sunxi: add support for H616 uart0 Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-04  2:33   ` [linux-sunxi] " Samuel Holland
  2021-01-03  9:26 ` [PATCH 11/17] sunxi: Add H616 DRAM support Jernej Skrabec
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

This port is needed for communication with PMIC. SPL uses it to set DRAM
voltage on H616 boards.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/include/asm/arch-sunxi/gpio.h | 1 +
 board/sunxi/board.c                    | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index cdb7dbd5b8e5..de77bf638e21 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -220,6 +220,7 @@ enum sunxi_gpio_number {
 #define SUN8I_A23_GPL_R_TWI	3
 #define SUN8I_GPL_R_UART	2
 #define SUN50I_GPL_R_TWI	2
+#define SUN50I_H616_GPL_R_TWI	3
 
 #define SUN9I_GPN_R_RSB		3
 
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 54ff9bc92396..727e8320318f 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -196,6 +196,10 @@ void i2c_init_board(void)
 	clock_twi_onoff(5, 1);
 	sunxi_gpio_set_cfgpin(SUNXI_GPL(8), SUN50I_GPL_R_TWI);
 	sunxi_gpio_set_cfgpin(SUNXI_GPL(9), SUN50I_GPL_R_TWI);
+#elif CONFIG_MACH_SUN50I_H616
+	clock_twi_onoff(5, 1);
+	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN50I_H616_GPL_R_TWI);
+	sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN50I_H616_GPL_R_TWI);
 #else
 	clock_twi_onoff(5, 1);
 	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_H3_GPL_R_TWI);
-- 
2.30.0

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

* [PATCH 11/17] sunxi: Add H616 DRAM support
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (9 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 10/17] sunxi: add support for R_I2C on H616 Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-04  2:39   ` [linux-sunxi] " Samuel Holland
  2021-01-03  9:26 ` [PATCH 12/17] sunxi: Add support for H616 SoC Jernej Skrabec
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

Allwinner H616 supports many types of DRAM. Most notably it supports
LPDDR4. However, all commercially available boards at this time use
only DDR3, so this commit adds only DDR3 support.

Controller and MBUS are very similar to H6 but PHY is completely
unknown.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/include/asm/arch-sunxi/dram.h        |    2 +
 .../include/asm/arch-sunxi/dram_sun50i_h616.h |  159 +++
 arch/arm/mach-sunxi/Kconfig                   |   43 +
 arch/arm/mach-sunxi/Makefile                  |    2 +
 arch/arm/mach-sunxi/dram_sun50i_h616.c        | 1023 +++++++++++++++++
 arch/arm/mach-sunxi/dram_timings/Makefile     |    2 +
 .../mach-sunxi/dram_timings/h616_ddr3_1333.c  |   94 ++
 7 files changed, 1325 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
 create mode 100644 arch/arm/mach-sunxi/dram_sun50i_h616.c
 create mode 100644 arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c

diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 8002b7efdc19..c3b3e1f512b2 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -29,6 +29,8 @@
 #include <asm/arch/dram_sun9i.h>
 #elif defined(CONFIG_MACH_SUN50I_H6)
 #include <asm/arch/dram_sun50i_h6.h>
+#elif defined(CONFIG_MACH_SUN50I_H616)
+#include <asm/arch/dram_sun50i_h616.h>
 #else
 #include <asm/arch/dram_sun4i.h>
 #endif
diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
new file mode 100644
index 000000000000..5d105afd6110
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
@@ -0,0 +1,159 @@
+/*
+ * H616 dram controller register and constant defines
+ *
+ * (C) Copyright 2020  Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * Based on H6 one, which is:
+ * (C) Copyright 2017  Icenowy Zheng <icenowy@aosc.io>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _SUNXI_DRAM_SUN50I_H616_H
+#define _SUNXI_DRAM_SUN50I_H616_H
+
+#include <stdbool.h>
+#ifndef __ASSEMBLY__
+#include <linux/bitops.h>
+#endif
+
+enum sunxi_dram_type {
+	SUNXI_DRAM_TYPE_DDR3 = 3,
+	SUNXI_DRAM_TYPE_DDR4,
+	SUNXI_DRAM_TYPE_LPDDR3 = 7,
+	SUNXI_DRAM_TYPE_LPDDR4
+};
+
+/* MBUS part is largely the same as in H6, except for one special register */
+struct sunxi_mctl_com_reg {
+	u32 cr;			/* 0x000 control register */
+	u8 reserved_0x004[4];	/* 0x004 */
+	u32 unk_0x008;		/* 0x008 */
+	u32 tmr;		/* 0x00c timer register */
+	u8 reserved_0x010[4];	/* 0x010 */
+	u32 unk_0x014;		/* 0x014 */
+	u8 reserved_0x018[8];	/* 0x018 */
+	u32 maer0;		/* 0x020 master enable register 0 */
+	u32 maer1;		/* 0x024 master enable register 1 */
+	u32 maer2;		/* 0x028 master enable register 2 */
+	u8 reserved_0x02c[468];	/* 0x02c */
+	u32 bwcr;		/* 0x200 bandwidth control register */
+	u8 reserved_0x204[12];	/* 0x204 */
+	/*
+	 * The last master configured by BSP libdram is at 0x49x, so the
+	 * size of this struct array is set to 41 (0x29) now.
+	 */
+	struct {
+		u32 cfg0;		/* 0x0 */
+		u32 cfg1;		/* 0x4 */
+		u8 reserved_0x8[8];	/* 0x8 */
+	} master[41];		/* 0x210 + index * 0x10 */
+	u8 reserved_0x4a0[96];	/* 0x4a0 */
+	u32 unk_0x500;		/* 0x500 */
+};
+check_member(sunxi_mctl_com_reg, unk_0x500, 0x500);
+
+/*
+ * Controller registers seems to be the same or at least very similar
+ * to those in H6.
+ */
+struct sunxi_mctl_ctl_reg {
+	u32 mstr;		/* 0x000 */
+	u32 statr;		/* 0x004 unused */
+	u32 mstr1;		/* 0x008 unused */
+	u32 unk_0x00c;		/* 0x00c */
+	u32 mrctrl0;		/* 0x010 unused */
+	u32 mrctrl1;		/* 0x014 unused */
+	u32 mrstatr;		/* 0x018 unused */
+	u32 mrctrl2;		/* 0x01c unused */
+	u32 derateen;		/* 0x020 unused */
+	u32 derateint;		/* 0x024 unused */
+	u8 reserved_0x028[8];	/* 0x028 */
+	u32 pwrctl;		/* 0x030 unused */
+	u32 pwrtmg;		/* 0x034 unused */
+	u32 hwlpctl;		/* 0x038 unused */
+	u8 reserved_0x03c[20];	/* 0x03c */
+	u32 rfshctl0;		/* 0x050 unused */
+	u32 rfshctl1;		/* 0x054 unused */
+	u8 reserved_0x058[8];	/* 0x05c */
+	u32 rfshctl3;		/* 0x060 */
+	u32 rfshtmg;		/* 0x064 */
+	u8 reserved_0x068[104];	/* 0x068 */
+	u32 init[8];		/* 0x0d0 */
+	u32 dimmctl;		/* 0x0f0 unused */
+	u32 rankctl;		/* 0x0f4 */
+	u8 reserved_0x0f8[8];	/* 0x0f8 */
+	u32 dramtmg[17];	/* 0x100 */
+	u8 reserved_0x144[60];	/* 0x144 */
+	u32 zqctl[3];		/* 0x180 */
+	u32 zqstat;		/* 0x18c unused */
+	u32 dfitmg0;		/* 0x190 */
+	u32 dfitmg1;		/* 0x194 */
+	u32 dfilpcfg[2];	/* 0x198 unused */
+	u32 dfiupd[3];		/* 0x1a0 */
+	u32 reserved_0x1ac;	/* 0x1ac */
+	u32 dfimisc;		/* 0x1b0 */
+	u32 dfitmg2;		/* 0x1b4 unused */
+	u32 dfitmg3;		/* 0x1b8 unused */
+	u32 dfistat;		/* 0x1bc */
+	u32 dbictl;		/* 0x1c0 */
+	u8 reserved_0x1c4[60];	/* 0x1c4 */
+	u32 addrmap[12];	/* 0x200 */
+	u8 reserved_0x230[16];	/* 0x230 */
+	u32 odtcfg;		/* 0x240 */
+	u32 odtmap;		/* 0x244 */
+	u8 reserved_0x248[8];	/* 0x248 */
+	u32 sched[2];		/* 0x250 */
+	u8 reserved_0x258[180];	/* 0x258 */
+	u32 dbgcmd;		/* 0x30c unused */
+	u32 dbgstat;		/* 0x310 unused */
+	u8 reserved_0x314[12];	/* 0x314 */
+	u32 swctl;		/* 0x320 */
+	u32 swstat;		/* 0x324 */
+	u8 reserved_0x328[7768];/* 0x328 */
+	u32 unk_0x2180;		/* 0x2180 */
+	u8 reserved_0x2184[188];/* 0x2184 */
+	u32 unk_0x2240;		/* 0x2240 */
+	u8 reserved_0x2244[3900];/* 0x2244 */
+	u32 unk_0x3180;		/* 0x3180 */
+	u8 reserved_0x3184[188];/* 0x3184 */
+	u32 unk_0x3240;		/* 0x3240 */
+	u8 reserved_0x3244[3900];/* 0x3244 */
+	u32 unk_0x4180;		/* 0x4180 */
+	u8 reserved_0x4184[188];/* 0x4184 */
+	u32 unk_0x4240;		/* 0x4240 */
+};
+check_member(sunxi_mctl_ctl_reg, swstat, 0x324);
+check_member(sunxi_mctl_ctl_reg, unk_0x4240, 0x4240);
+
+#define MSTR_DEVICETYPE_DDR3	BIT(0)
+#define MSTR_DEVICETYPE_LPDDR2	BIT(2)
+#define MSTR_DEVICETYPE_LPDDR3	BIT(3)
+#define MSTR_DEVICETYPE_DDR4	BIT(4)
+#define MSTR_DEVICETYPE_MASK	GENMASK(5, 0)
+#define MSTR_2TMODE		BIT(10)
+#define MSTR_BUSWIDTH_FULL	(0 << 12)
+#define MSTR_BUSWIDTH_HALF	(1 << 12)
+#define MSTR_ACTIVE_RANKS(x)	(((x == 2) ? 3 : 1) << 24)
+#define MSTR_BURST_LENGTH(x)	(((x) >> 1) << 16)
+
+struct dram_para {
+	u32 clk;
+	enum sunxi_dram_type type;
+	u8 cols;
+	u8 rows;
+	u8 ranks;
+	u8 bus_full_width;
+};
+
+
+static inline int ns_to_t(int nanoseconds)
+{
+	const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
+
+	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
+}
+
+void mctl_set_timing_params(struct dram_para *para);
+
+#endif /* _SUNXI_DRAM_SUN50I_H616_H */
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 69ab670abf39..1a5497989f04 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -48,6 +48,46 @@ config DRAM_SUN50I_H6
 	  Select this dram controller driver for some sun50i platforms,
 	  like H6.
 
+config DRAM_SUN50I_H616
+	bool
+	help
+	  Select this dram controller driver for some sun50i platforms,
+	  like H616.
+
+if DRAM_SUN50I_H616
+config DRAM_SUN50I_H616_WRITE_LEVELING
+	bool "H616 DRAM write leveling"
+	---help---
+	  Select this when DRAM on your H616 board needs write leveling.
+
+config DRAM_SUN50I_H616_READ_CALIBRATION
+	bool"H616 DRAM read calibration"
+	---help---
+	  Select this when DRAM on your H616 board needs read calibration.
+
+config DRAM_SUN50I_H616_READ_TRAINING
+	bool "H616 DRAM read training"
+	---help---
+	  Select this when DRAM on your H616 board needs read training.
+
+config DRAM_SUN50I_H616_WRITE_TRAINING
+	bool "H616 DRAM write training"
+	---help---
+	  Select this when DRAM on your H616 board needs write training.
+
+config DRAM_SUN50I_H616_BIT_DELAY_COMPENSATION
+	bool "H616 DRAM bit delay compensation"
+	---help---
+	  Select this when DRAM on your H616 board needs bit delay
+	  compensation.
+
+config DRAM_SUN50I_H616_UNKNOWN_FEATURE
+	bool "H616 DRAM unknown feature"
+	---help---
+	  Select this when DRAM on your H616 board needs this unknown
+	  feature.
+endif
+
 config SUN6I_P2WI
 	bool "Allwinner sun6i internal P2WI controller"
 	help
@@ -423,6 +463,7 @@ config DRAM_CLK
 		       MACH_SUN8I_V3S
 	default 672 if MACH_SUN50I
 	default 744 if MACH_SUN50I_H6
+	default 720 if MACH_SUN50I_H616
 	---help---
 	Set the dram clock speed, valid range 240 - 480 (prior to sun9i),
 	must be a multiple of 24. For the sun9i (A80), the tested values
@@ -439,6 +480,7 @@ endif
 
 config DRAM_ZQ
 	int "sunxi dram zq value"
+	depends on !MACH_SUN50I_H616
 	default 123 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || \
 		       MACH_SUN8I_A23 || MACH_SUN8I_A33 || MACH_SUN8I_A83T
 	default 127 if MACH_SUN7I
@@ -456,6 +498,7 @@ config DRAM_ODT_EN
 	default y if MACH_SUN8I_R40
 	default y if MACH_SUN50I
 	default y if MACH_SUN50I_H6
+	default y if MACH_SUN50I_H616
 	---help---
 	Select this to enable dram odt (on die termination).
 
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index b8aca43d6630..3f081d92f379 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -40,4 +40,6 @@ obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_sunxi_dw.o
 obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_timings/
 obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_sun50i_h6.o
 obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_timings/
+obj-$(CONFIG_DRAM_SUN50I_H616)	+= dram_sun50i_h616.o
+obj-$(CONFIG_DRAM_SUN50I_H616)	+= dram_timings/
 endif
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
new file mode 100644
index 000000000000..0c86f54b8a73
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c
@@ -0,0 +1,1023 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * sun50i H616 platform dram controller driver
+ *
+ * While controller is very similar to that in H6, PHY is completely
+ * unknown. That's why this driver has plenty of magic numbers. Some
+ * meaning was nevertheless deduced from strings found in boot0 and
+ * known meaning of some dram parameters.
+ * This driver only supports DDR3 memory and omits logic for all
+ * other supported types supported by hardware.
+ *
+ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ */
+#include <common.h>
+#include <init.h>
+#include <log.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/cpu.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/kconfig.h>
+
+enum {
+	MBUS_QOS_LOWEST = 0,
+	MBUS_QOS_LOW,
+	MBUS_QOS_HIGH,
+	MBUS_QOS_HIGHEST
+};
+
+inline void mbus_configure_port(u8 port,
+				bool bwlimit,
+				bool priority,
+				u8 qos,
+				u8 waittime,
+				u8 acs,
+				u16 bwl0,
+				u16 bwl1,
+				u16 bwl2)
+{
+	struct sunxi_mctl_com_reg * const mctl_com =
+			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+
+	const u32 cfg0 = ( (bwlimit ? (1 << 0) : 0)
+			   | (priority ? (1 << 1) : 0)
+			   | ((qos & 0x3) << 2)
+			   | ((waittime & 0xf) << 4)
+			   | ((acs & 0xff) << 8)
+			   | (bwl0 << 16) );
+	const u32 cfg1 = ((u32)bwl2 << 16) | (bwl1 & 0xffff);
+
+	debug("MBUS port %d cfg0 %08x cfg1 %08x\n", port, cfg0, cfg1);
+	writel_relaxed(cfg0, &mctl_com->master[port].cfg0);
+	writel_relaxed(cfg1, &mctl_com->master[port].cfg1);
+}
+
+#define MBUS_CONF(port, bwlimit, qos, acs, bwl0, bwl1, bwl2)	\
+	mbus_configure_port(port, bwlimit, false, \
+			    MBUS_QOS_ ## qos, 0, acs, bwl0, bwl1, bwl2)
+
+static void mctl_set_master_priority(void)
+{
+	struct sunxi_mctl_com_reg * const mctl_com =
+			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+
+	/* enable bandwidth limit windows and set windows size 1us */
+	writel(399, &mctl_com->tmr);
+	writel(BIT(16), &mctl_com->bwcr);
+
+	MBUS_CONF( 0, true, HIGHEST, 0,  256,  128,  100);
+	MBUS_CONF( 1, true,    HIGH, 0, 1536, 1400,  256);
+	MBUS_CONF( 2, true, HIGHEST, 0,  512,  256,   96);
+	MBUS_CONF( 3, true,    HIGH, 0,  256,  100,   80);
+	MBUS_CONF( 4, true,    HIGH, 2, 8192, 5500, 5000);
+	MBUS_CONF( 5, true,    HIGH, 2,  100,   64,   32);
+	MBUS_CONF( 6, true,    HIGH, 2,  100,   64,   32);
+	MBUS_CONF( 8, true,    HIGH, 0,  256,  128,   64);
+	MBUS_CONF(11, true,    HIGH, 0,  256,  128,  100);
+	MBUS_CONF(14, true,    HIGH, 0, 1024,  256,   64);
+	MBUS_CONF(16, true, HIGHEST, 6, 8192, 2800, 2400);
+	MBUS_CONF(21, true, HIGHEST, 6, 2048,  768,  512);
+	MBUS_CONF(25, true, HIGHEST, 0,  100,   64,   32);
+	MBUS_CONF(26, true,    HIGH, 2, 8192, 5500, 5000);
+	MBUS_CONF(37, true,    HIGH, 0,  256,  128,   64);
+	MBUS_CONF(38, true,    HIGH, 2,  100,   64,   32);
+	MBUS_CONF(39, true,    HIGH, 2, 8192, 5500, 5000);
+	MBUS_CONF(40, true,    HIGH, 2,  100,   64,   32);
+
+	dmb();
+}
+
+static void mctl_sys_init(struct dram_para *para)
+{
+	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;
+
+	/* Put all DRAM-related blocks to reset state */
+	clrbits_le32(&ccm->mbus_cfg, MBUS_ENABLE);
+	clrbits_le32(&ccm->mbus_cfg, MBUS_RESET);
+	clrbits_le32(&ccm->dram_gate_reset, BIT(GATE_SHIFT));
+	udelay(5);
+	clrbits_le32(&ccm->dram_gate_reset, BIT(RESET_SHIFT));
+	clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
+	clrbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
+
+	udelay(5);
+
+	/* Set PLL5 rate to doubled DRAM clock rate */
+	writel(CCM_PLL5_CTRL_EN | CCM_PLL5_LOCK_EN | CCM_PLL5_OUT_EN |
+	       CCM_PLL5_CTRL_N(para->clk * 2 / 24 - 1), &ccm->pll5_cfg);
+	mctl_await_completion(&ccm->pll5_cfg, CCM_PLL5_LOCK, CCM_PLL5_LOCK);
+
+	/* Configure DRAM mod clock */
+	writel(DRAM_CLK_SRC_PLL5, &ccm->dram_clk_cfg);
+	writel(BIT(RESET_SHIFT), &ccm->dram_gate_reset);
+	udelay(5);
+	setbits_le32(&ccm->dram_gate_reset, BIT(GATE_SHIFT));
+
+	/* Disable all channels */
+	writel(0, &mctl_com->maer0);
+	writel(0, &mctl_com->maer1);
+	writel(0, &mctl_com->maer2);
+
+	/* Configure MBUS and enable DRAM mod reset */
+	setbits_le32(&ccm->mbus_cfg, MBUS_RESET);
+	setbits_le32(&ccm->mbus_cfg, MBUS_ENABLE);
+
+	clrbits_le32(&mctl_com->unk_0x500, BIT(25));
+
+	setbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
+	udelay(5);
+
+	/* Unknown hack, which enables access of mctl_ctl regs */
+	writel(0x8000, &mctl_ctl->unk_0x00c);
+}
+
+static void mctl_set_addrmap(struct dram_para *para)
+{
+	struct sunxi_mctl_ctl_reg * const mctl_ctl =
+			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+	u8 cols = para->cols;
+	u8 rows = para->rows;
+	u8 ranks = para->ranks;
+
+	if (!para->bus_full_width)
+		cols -= 1;
+
+	/* Ranks */
+	if (ranks == 2)
+		mctl_ctl->addrmap[0] = rows + cols - 3;
+	else
+		mctl_ctl->addrmap[0] = 0x1F;
+
+	/* Banks, hardcoded to 8 banks now */
+	mctl_ctl->addrmap[1] = (cols - 2) | (cols - 2) << 8 | (cols - 2) << 16;
+
+	/* Columns */
+	mctl_ctl->addrmap[2] = 0;
+	switch (cols) {
+	case 7:
+		mctl_ctl->addrmap[3] = 0x1F1F1F00;
+		mctl_ctl->addrmap[4] = 0x1F1F;
+		break;
+	case 8:
+		mctl_ctl->addrmap[3] = 0x1F1F0000;
+		mctl_ctl->addrmap[4] = 0x1F1F;
+		break;
+	case 9:
+		mctl_ctl->addrmap[3] = 0x1F000000;
+		mctl_ctl->addrmap[4] = 0x1F1F;
+		break;
+	case 10:
+		mctl_ctl->addrmap[3] = 0;
+		mctl_ctl->addrmap[4] = 0x1F1F;
+		break;
+	case 11:
+		mctl_ctl->addrmap[3] = 0;
+		mctl_ctl->addrmap[4] = 0x1F00;
+		break;
+	case 12:
+		mctl_ctl->addrmap[3] = 0;
+		mctl_ctl->addrmap[4] = 0;
+		break;
+	default:
+		panic("Unsupported DRAM configuration: column number invalid\n");
+	}
+
+	/* Rows */
+	mctl_ctl->addrmap[5] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
+	switch (rows) {
+	case 13:
+		mctl_ctl->addrmap[6] = (cols - 3) | 0x0F0F0F00;
+		mctl_ctl->addrmap[7] = 0x0F0F;
+		break;
+	case 14:
+		mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | 0x0F0F0000;
+		mctl_ctl->addrmap[7] = 0x0F0F;
+		break;
+	case 15:
+		mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | 0x0F000000;
+		mctl_ctl->addrmap[7] = 0x0F0F;
+		break;
+	case 16:
+		mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
+		mctl_ctl->addrmap[7] = 0x0F0F;
+		break;
+	case 17:
+		mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
+		mctl_ctl->addrmap[7] = (cols - 3) | 0x0F00;
+		break;
+	case 18:
+		mctl_ctl->addrmap[6] = (cols - 3) | ((cols - 3) << 8) | ((cols - 3) << 16) | ((cols - 3) << 24);
+		mctl_ctl->addrmap[7] = (cols - 3) | ((cols - 3) << 8);
+		break;
+	default:
+		panic("Unsupported DRAM configuration: row number invalid\n");
+	}
+
+	/* Bank groups, DDR4 only */
+	mctl_ctl->addrmap[8] = 0x3F3F;
+}
+
+static const u8 phy_init[] = {
+	0x07, 0x0b, 0x02, 0x16, 0x0d, 0x0e, 0x14, 0x19,
+	0x0a, 0x15, 0x03, 0x13, 0x04, 0x0c, 0x10, 0x06,
+	0x0f, 0x11, 0x1a, 0x01, 0x12, 0x17, 0x00, 0x08,
+	0x09, 0x05, 0x18
+};
+
+static void mctl_phy_configure_odt(void)
+{
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x388);
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x38c);
+
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x3c8);
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x3cc);
+
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x408);
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x40c);
+
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x448);
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x44c);
+
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x340);
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x344);
+
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x348);
+	writel_relaxed(0xe, SUNXI_DRAM_PHY0_BASE + 0x34c);
+
+	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x380);
+	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x384);
+
+	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x3c0);
+	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x3c4);
+
+	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x400);
+	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x404);
+
+	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x440);
+	writel_relaxed(0x8, SUNXI_DRAM_PHY0_BASE + 0x444);
+
+	dmb();
+}
+
+static bool mctl_phy_write_leveling(struct dram_para *para)
+{
+	bool result = true;
+	u32 val;
+
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x80);
+	writel(4, SUNXI_DRAM_PHY0_BASE + 0xc);
+	writel(0x40, SUNXI_DRAM_PHY0_BASE + 0x10);
+
+	setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
+
+	if (para->bus_full_width)
+		val = 0xf;
+	else
+		val = 3;
+
+	mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
+
+	val = readl(SUNXI_DRAM_PHY0_BASE + 0x258);
+	if (val == 0 || val == 0x3f)
+		result = false;
+	val = readl(SUNXI_DRAM_PHY0_BASE + 0x25c);
+	if (val == 0 || val == 0x3f)
+		result = false;
+	val = readl(SUNXI_DRAM_PHY0_BASE + 0x318);
+	if (val == 0 || val == 0x3f)
+		result = false;
+	val = readl(SUNXI_DRAM_PHY0_BASE + 0x31c);
+	if (val == 0 || val == 0x3f)
+		result = false;
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
+
+	if (para->ranks == 2) {
+		clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x40);
+
+		setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
+
+		if (para->bus_full_width)
+			val = 0xf;
+		else
+			val = 3;
+
+		mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x188), val, val);
+
+		clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
+	}
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
+
+	return result;
+}
+
+static bool mctl_phy_read_calibration(struct dram_para *para)
+{
+	bool result = true;
+	u32 val, tmp;
+
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x20);
+
+	setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
+
+	if (para->bus_full_width)
+		val = 0xf;
+	else
+		val = 3;
+
+	while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
+		if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
+			result = false;
+			break;
+		}
+	}
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
+
+	if (para->ranks == 2) {
+		clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x10);
+
+		setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
+
+		while ((readl(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
+			if (readl(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
+				result = false;
+				break;
+			}
+		}
+
+		setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
+	}
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
+
+	val = readl(SUNXI_DRAM_PHY0_BASE + 0x274) & 7;
+	tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x26c) & 7;
+	if (val < tmp)
+		val = tmp;
+	tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x32c) & 7;
+	if (val < tmp)
+		val = tmp;
+	tmp = readl(SUNXI_DRAM_PHY0_BASE + 0x334) & 7;
+	if (val < tmp)
+		val = tmp;
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x38, 0x7, (val + 2) & 7);
+
+	setbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x20);
+
+	return result;
+}
+
+static bool mctl_phy_read_training(struct dram_para *para)
+{
+	u32 val1, val2, *ptr1, *ptr2;
+	bool result = true;
+	int i;
+
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x804, 0x3f, 0xf);
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x808, 0x3f, 0xf);
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa04, 0x3f, 0xf);
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0xa08, 0x3f, 0xf);
+
+	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
+	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
+
+	mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
+	if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
+		result = false;
+
+	if (para->bus_full_width) {
+		mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
+		if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
+			result = false;
+	}
+
+	ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x898);
+	ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x850);
+	for (i = 0; i < 9; i++) {
+		val1 = readl(&ptr1[i]);
+		val2 = readl(&ptr2[i]);
+		if (val1 - val2 <= 6)
+			result = false;
+	}
+	ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x8bc);
+	ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x874);
+	for (i = 0; i < 9; i++) {
+		val1 = readl(&ptr1[i]);
+		val2 = readl(&ptr2[i]);
+		if (val1 - val2 <= 6)
+			result = false;
+	}
+
+	if (para->bus_full_width) {
+		ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xa98);
+		ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xa50);
+		for (i = 0; i < 9; i++) {
+			val1 = readl(&ptr1[i]);
+			val2 = readl(&ptr2[i]);
+			if (val1 - val2 <= 6)
+				result = false;
+		}
+
+		ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xabc);
+		ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xa74);
+		for (i = 0; i < 9; i++) {
+			val1 = readl(&ptr1[i]);
+			val2 = readl(&ptr2[i]);
+			if (val1 - val2 <= 6)
+				result = false;
+		}
+	}
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
+
+	if (para->ranks == 2) {
+		/* maybe last parameter should be 1? */
+		clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
+
+		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 6);
+		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 1);
+
+		mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x840), 0xc, 0xc);
+		if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
+			result = false;
+
+		if (para->bus_full_width) {
+			mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
+			if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
+				result = false;
+		}
+
+		clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
+	}
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3);
+
+	return result;
+}
+
+static bool mctl_phy_write_training(struct dram_para *para)
+{
+	u32 val1, val2, *ptr1, *ptr2;
+	bool result = true;
+	int i;
+
+	writel(0, SUNXI_DRAM_PHY0_BASE + 0x134);
+	writel(0, SUNXI_DRAM_PHY0_BASE + 0x138);
+	writel(0, SUNXI_DRAM_PHY0_BASE + 0x19c);
+	writel(0, SUNXI_DRAM_PHY0_BASE + 0x1a0);
+
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 8);
+
+	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
+	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
+
+	mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
+	if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
+		result = false;
+
+	if (para->bus_full_width) {
+		mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
+		if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
+			result = false;
+	}
+
+	ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x938);
+	ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x8f0);
+	for (i = 0; i < 9; i++) {
+		val1 = readl(&ptr1[i]);
+		val2 = readl(&ptr2[i]);
+		if (val1 - val2 <= 6)
+			result = false;
+	}
+	ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x95c);
+	ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x914);
+	for (i = 0; i < 9; i++) {
+		val1 = readl(&ptr1[i]);
+		val2 = readl(&ptr2[i]);
+		if (val1 - val2 <= 6)
+			result = false;
+	}
+
+	if (para->bus_full_width) {
+		ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xb38);
+		ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xaf0);
+		for (i = 0; i < 9; i++) {
+			val1 = readl(&ptr1[i]);
+			val2 = readl(&ptr2[i]);
+			if (val1 - val2 <= 6)
+				result = false;
+		}
+		ptr1 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xb5c);
+		ptr2 = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xb14);
+		for (i = 0; i < 9; i++) {
+			val1 = readl(&ptr1[i]);
+			val2 = readl(&ptr2[i]);
+			if (val1 - val2 <= 6)
+				result = false;
+		}
+	}
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
+
+	if (para->ranks == 2) {
+		clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 4);
+
+		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
+		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x20);
+
+		mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x8e0), 3, 3);
+		if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
+			result = false;
+
+		if (para->bus_full_width) {
+			mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
+			if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
+				result = false;
+		}
+
+		clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
+	}
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc);
+
+	return result;
+}
+
+static bool mctl_phy_bit_delay_compensation(struct dram_para *para)
+{
+	u32 *ptr;
+	int i;
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
+	setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 8);
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
+
+	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x484);
+	for (i = 0; i < 9; i++) {
+		writel_relaxed(0x16, ptr);
+		writel_relaxed(0x16, ptr + 0x30);
+		ptr += 2;
+	}
+	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x4d0);
+	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x590);
+	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x4cc);
+	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x58c);
+
+	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x4d8);
+	for (i = 0; i < 9; i++) {
+		writel_relaxed(0x1a, ptr);
+		writel_relaxed(0x1a, ptr + 0x30);
+		ptr += 2;
+	}
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x524);
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x5e4);
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x520);
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x5e0);
+
+	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x604);
+	for (i = 0; i < 9; i++) {
+		writel_relaxed(0x1a, ptr);
+		writel_relaxed(0x1a, ptr + 0x30);
+		ptr += 2;
+	}
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x650);
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x710);
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x64c);
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x70c);
+
+	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x658);
+	for (i = 0; i < 9; i++) {
+		writel_relaxed(0x1a, ptr);
+		writel_relaxed(0x1a, ptr + 0x30);
+		ptr += 2;
+	}
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x6a4);
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x764);
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x6a0);
+	writel_relaxed(0x1e, SUNXI_DRAM_PHY0_BASE + 0x760);
+
+	dmb();
+
+	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
+
+	/* second part */
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 4);
+
+	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x480);
+	for (i = 0; i < 9; i++) {
+		writel_relaxed(0x10, ptr);
+		writel_relaxed(0x10, ptr + 0x30);
+		ptr += 2;
+	}
+	writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x528);
+	writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x5e8);
+	writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x4c8);
+	writel_relaxed(0x18, SUNXI_DRAM_PHY0_BASE + 0x588);
+
+	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x4d4);
+	for (i = 0; i < 9; i++) {
+		writel_relaxed(0x12, ptr);
+		writel_relaxed(0x12, ptr + 0x30);
+		ptr += 2;
+	}
+	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x52c);
+	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x5ec);
+	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x51c);
+	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x5dc);
+
+	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x600);
+	for (i = 0; i < 9; i++) {
+		writel_relaxed(0x12, ptr);
+		writel_relaxed(0x12, ptr + 0x30);
+		ptr += 2;
+	}
+	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x6a8);
+	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x768);
+	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x648);
+	writel_relaxed(0x1a, SUNXI_DRAM_PHY0_BASE + 0x708);
+
+	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x654);
+	for (i = 0; i < 9; i++) {
+		writel_relaxed(0x14, ptr);
+		writel_relaxed(0x14, ptr + 0x30);
+		ptr += 2;
+	}
+	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x6ac);
+	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x76c);
+	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x69c);
+	writel_relaxed(0x1c, SUNXI_DRAM_PHY0_BASE + 0x75c);
+
+	dmb();
+
+	setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 0x80);
+
+	return true;
+}
+
+static bool mctl_phy_init(struct dram_para *para)
+{
+	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;
+	u32 val, *ptr;
+	int i;
+
+	if (para->bus_full_width)
+		val = 0xf;
+	else
+		val = 3;
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
+
+	writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x14);
+	writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x35c);
+	writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x368);
+	writel(0xd, SUNXI_DRAM_PHY0_BASE + 0x374);
+
+	writel(0, SUNXI_DRAM_PHY0_BASE + 0x18);
+	writel(0, SUNXI_DRAM_PHY0_BASE + 0x360);
+	writel(0, SUNXI_DRAM_PHY0_BASE + 0x36c);
+	writel(0, SUNXI_DRAM_PHY0_BASE + 0x378);
+
+	writel(9, SUNXI_DRAM_PHY0_BASE + 0x1c);
+	writel(9, SUNXI_DRAM_PHY0_BASE + 0x364);
+	writel(9, SUNXI_DRAM_PHY0_BASE + 0x370);
+	writel(9, SUNXI_DRAM_PHY0_BASE + 0x37c);
+
+	ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0xc0);
+	for (i = 0; i < ARRAY_SIZE(phy_init); i++)
+		writel(phy_init[i], &ptr[i]);
+
+	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_UNKNOWN_FEATURE)) {
+		ptr = (u32*)(SUNXI_DRAM_PHY0_BASE + 0x780);
+		for (i = 0; i < 32; i++)
+			writel(0x16, &ptr[i]);
+		writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x78c);
+		writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7a4);
+		writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7b8);
+		writel(0x8, SUNXI_DRAM_PHY0_BASE + 0x7d4);
+		writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7dc);
+		writel(0xe, SUNXI_DRAM_PHY0_BASE + 0x7e0);
+	}
+
+	writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x3dc);
+	writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x45c);
+
+	if (IS_ENABLED(DRAM_ODT_EN))
+		mctl_phy_configure_odt();
+
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 7, 0xa);
+
+	if (para->clk <= 672)
+		writel(0xf, SUNXI_DRAM_PHY0_BASE + 0x20);
+	if (para->clk > 500) {
+		clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
+		clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0);
+	} else {
+		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, BIT(7));
+		clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0, 0x20);
+	}
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 8);
+
+	mctl_await_completion((u32*)(SUNXI_DRAM_PHY0_BASE + 0x180), 4, 4);
+
+	writel(0x37, SUNXI_DRAM_PHY0_BASE + 0x58);
+	clrbits_le32(&mctl_com->unk_0x500, 0x200);
+
+	writel(0, &mctl_ctl->swctl);
+	setbits_le32(&mctl_ctl->dfimisc, 1);
+
+	/* start DFI init */
+	setbits_le32(&mctl_ctl->dfimisc, 0x20);
+	writel(1, &mctl_ctl->swctl);
+	mctl_await_completion(&mctl_ctl->swstat, 1, 1);
+	/* poll DFI init complete */
+	mctl_await_completion(&mctl_ctl->dfistat, 1, 1);
+	writel(0, &mctl_ctl->swctl);
+	clrbits_le32(&mctl_ctl->dfimisc, 0x20);
+
+	clrbits_le32(&mctl_ctl->pwrctl, 0x20);
+	writel(1, &mctl_ctl->swctl);
+	mctl_await_completion(&mctl_ctl->swstat, 1, 1);
+	mctl_await_completion(&mctl_ctl->statr, 3, 1);
+
+	writel(0, &mctl_ctl->swctl);
+	clrbits_le32(&mctl_ctl->dfimisc, 1);
+
+	writel(1, &mctl_ctl->swctl);
+	mctl_await_completion(&mctl_ctl->swstat, 1, 1);
+
+	writel(0x1f14, &mctl_ctl->mrctrl1);
+	writel(0x80000030, &mctl_ctl->mrctrl0);
+	mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
+
+	writel(4, &mctl_ctl->mrctrl1);
+	writel(0x80001030, &mctl_ctl->mrctrl0);
+	mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
+
+	writel(0x20, &mctl_ctl->mrctrl1);
+	writel(0x80002030, &mctl_ctl->mrctrl0);
+	mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
+
+	writel(0, &mctl_ctl->mrctrl1);
+	writel(0x80003030, &mctl_ctl->mrctrl0);
+	mctl_await_completion(&mctl_ctl->mrctrl0, BIT(31), 0);
+
+	writel(0, SUNXI_DRAM_PHY0_BASE + 0x54);
+
+	writel(0, &mctl_ctl->swctl);
+	clrbits_le32(&mctl_ctl->rfshctl3, 1);
+	writel(1, &mctl_ctl->swctl);
+
+	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_WRITE_LEVELING)) {
+		for (i = 0; i < 5; i++)
+			if (mctl_phy_write_leveling(para))
+				break;
+		if (i == 5) {
+			debug("write leveling failed!\n");
+			return false;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_READ_CALIBRATION)) {
+		for (i = 0; i < 5; i++)
+			if (mctl_phy_read_calibration(para))
+				break;
+		if (i == 5) {
+			debug("read calibration failed!\n");
+			return false;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_READ_TRAINING)) {
+		for (i = 0; i < 5; i++)
+			if (mctl_phy_read_training(para))
+				break;
+		if (i == 5) {
+			debug("read training failed!\n");
+			return false;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_WRITE_TRAINING)) {
+		for (i = 0; i < 5; i++)
+			if (mctl_phy_write_training(para))
+				break;
+		if (i == 5) {
+			debug("write training failed!\n");
+			return false;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_DRAM_SUN50I_H616_BIT_DELAY_COMPENSATION))
+		mctl_phy_bit_delay_compensation(para);
+
+	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 4);
+
+	return true;
+}
+
+static bool mctl_ctrl_init(struct dram_para *para)
+{
+	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;
+	u32 reg_val;
+
+	clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x200);
+	writel(0x8000, &mctl_ctl->unk_0x00c);
+
+	setbits_le32(&mctl_com->unk_0x008, 0xff00);
+
+	clrsetbits_le32(&mctl_ctl->sched[0], 0xff00, 0x3000);
+
+	writel(0, &mctl_ctl->hwlpctl);
+
+	setbits_le32(&mctl_com->unk_0x008, 0xff00);
+
+	reg_val = MSTR_BURST_LENGTH(8) | MSTR_ACTIVE_RANKS(para->ranks);
+	reg_val |= MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE;
+	if (para->bus_full_width)
+		reg_val |= MSTR_BUSWIDTH_FULL;
+	else
+		reg_val |= MSTR_BUSWIDTH_HALF;
+	writel(BIT(31) | BIT(30) | reg_val, &mctl_ctl->mstr);
+
+	if (para->ranks == 2)
+		writel(0x0303, &mctl_ctl->odtmap);
+	else
+		writel(0x0201, &mctl_ctl->odtmap);
+
+	writel(0x06000400, &mctl_ctl->odtcfg);
+	writel(0x06000400, &mctl_ctl->unk_0x2240);
+	writel(0x06000400, &mctl_ctl->unk_0x3240);
+	writel(0x06000400, &mctl_ctl->unk_0x4240);
+
+	setbits_le32(&mctl_com->cr, BIT(31));
+
+	mctl_set_addrmap(para);
+
+	mctl_set_timing_params(para);
+
+	writel(0, &mctl_ctl->pwrctl);
+
+	setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
+	setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
+	setbits_le32(&mctl_ctl->unk_0x2180, BIT(31) | BIT(30));
+	setbits_le32(&mctl_ctl->unk_0x3180, BIT(31) | BIT(30));
+	setbits_le32(&mctl_ctl->unk_0x4180, BIT(31) | BIT(30));
+
+	setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
+	clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
+
+	writel(0, &mctl_com->maer0);
+	writel(0, &mctl_com->maer1);
+	writel(0, &mctl_com->maer2);
+
+	writel(0x20, &mctl_ctl->pwrctl);
+	setbits_le32(&mctl_ctl->unk_0x00c, BIT(8));
+
+	clrsetbits_le32(&mctl_com->unk_0x500, BIT(24), 0x300);
+	/* this write seems to enable PHY MMIO region */
+	setbits_le32(&mctl_com->unk_0x500, BIT(24));
+
+	if (!mctl_phy_init(para))
+		return false;
+
+	writel(0, &mctl_ctl->swctl);
+	clrbits_le32(&mctl_ctl->rfshctl3, BIT(0));
+
+	setbits_le32(&mctl_com->unk_0x014, BIT(31));
+	writel(0xffffffff, &mctl_com->maer0);
+	writel(0x7ff, &mctl_com->maer1);
+	writel(0xffff, &mctl_com->maer2);
+
+	writel(1, &mctl_ctl->swctl);
+	mctl_await_completion(&mctl_ctl->swstat, 1, 1);
+
+	return true;
+}
+
+static bool mctl_core_init(struct dram_para *para)
+{
+	mctl_sys_init(para);
+
+	return mctl_ctrl_init(para);
+}
+
+static void mctl_auto_detect_rank_width(struct dram_para *para)
+{
+	/* this is minimum size that it's supported */
+	para->cols = 8;
+	para->rows = 13;
+
+	/*
+	 * Strategy here is to test most demanding combination first and least
+	 * demanding last, otherwise HW might not be fully utilized. For
+	 * example, half bus width and rank = 1 combination would also work
+	 * on HW with full bus width and rank = 2, but only 1/4 RAM would be
+	 * visible.
+	 */
+
+	debug("testing 32-bit width, rank = 2\n");
+	para->bus_full_width = 1;
+	para->ranks = 2;
+	if (mctl_core_init(para))
+		return;
+
+	debug("testing 32-bit width, rank = 1\n");
+	para->bus_full_width = 1;
+	para->ranks = 1;
+	if (mctl_core_init(para))
+		return;
+
+	debug("testing 16-bit width, rank = 2\n");
+	para->bus_full_width = 0;
+	para->ranks = 2;
+	if (mctl_core_init(para))
+		return;
+
+	debug("testing 16-bit width, rank = 1\n");
+	para->bus_full_width = 0;
+	para->ranks = 1;
+	if (mctl_core_init(para))
+		return;
+
+	panic("This DRAM setup is currently not supported.\n");
+}
+
+static void mctl_auto_detect_dram_size(struct dram_para *para)
+{
+	/* detect row address bits */
+	para->cols = 8;
+	para->rows = 18;
+	mctl_core_init(para);
+
+	for (para->rows = 13; para->rows < 18; para->rows++) {
+		/* 8 banks, 8 bit per byte and 16/32 bit width */
+		if (mctl_mem_matches((1 << (para->rows + para->cols +
+					    4 + para->bus_full_width))))
+			break;
+	}
+
+	/* detect column address bits */
+	para->cols = 11;
+	mctl_core_init(para);
+
+	for (para->cols = 8; para->cols < 11; para->cols++) {
+		/* 8 bits per byte and 16/32 bit width */
+		if (mctl_mem_matches(1 << (para->cols + 1 +
+					   para->bus_full_width)))
+			break;
+	}
+}
+
+static unsigned long mctl_calc_size(struct dram_para *para)
+{
+	u8 width = para->bus_full_width ? 4 : 2;
+
+	/* 8 banks */
+	return (1ULL << (para->cols + para->rows + 3)) * width * para->ranks;
+}
+
+unsigned long sunxi_dram_init(void)
+{
+	struct dram_para para = {
+		.clk = CONFIG_DRAM_CLK,
+		.type = SUNXI_DRAM_TYPE_DDR3,
+	};
+	unsigned long size;
+
+	setbits_le32(0x7010310, BIT(8));
+	clrbits_le32(0x7010318, 0x3f);
+
+	mctl_auto_detect_rank_width(&para);
+	mctl_auto_detect_dram_size(&para);
+
+	mctl_core_init(&para);
+
+	size = mctl_calc_size(&para);
+
+	mctl_set_master_priority();
+
+	return size;
+};
diff --git a/arch/arm/mach-sunxi/dram_timings/Makefile b/arch/arm/mach-sunxi/dram_timings/Makefile
index 0deb9911fd79..39a8756c297e 100644
--- a/arch/arm/mach-sunxi/dram_timings/Makefile
+++ b/arch/arm/mach-sunxi/dram_timings/Makefile
@@ -3,3 +3,5 @@ obj-$(CONFIG_SUNXI_DRAM_LPDDR3_STOCK)	+= lpddr3_stock.o
 obj-$(CONFIG_SUNXI_DRAM_DDR2_V3S)	+= ddr2_v3s.o
 obj-$(CONFIG_SUNXI_DRAM_H6_LPDDR3)	+= h6_lpddr3.o
 obj-$(CONFIG_SUNXI_DRAM_H6_DDR3_1333)	+= h6_ddr3_1333.o
+# currently only DDR3 is supported on H616
+obj-$(CONFIG_MACH_SUN50I_H616)		+= h616_ddr3_1333.o
diff --git a/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c b/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
new file mode 100644
index 000000000000..8f508344bc17
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
@@ -0,0 +1,94 @@
+/*
+ * sun50i H616 DDR3-1333 timings, as programmed by Allwinner's boot0
+ *
+ * The chips are probably able to be driven by a faster clock, but boot0
+ * uses a more conservative timing (as usual).
+ *
+ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
+ * Based on H6 DDR3 timings:
+ * (C) Copyright 2018,2019 Arm Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/cpu.h>
+
+void mctl_set_timing_params(struct dram_para *para)
+{
+	struct sunxi_mctl_ctl_reg * const mctl_ctl =
+			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+	u8 tccd		= 2;			/* JEDEC: 4nCK */
+	u8 tfaw		= ns_to_t(50);		/* JEDEC: 30 ns w/ 1K pages */
+	u8 trrd		= max(ns_to_t(6), 4);	/* JEDEC: max(6 ns, 4nCK) */
+	u8 trcd		= ns_to_t(15);		/* JEDEC: 13.5 ns */
+	u8 trc		= ns_to_t(53);		/* JEDEC: 49.5 ns */
+	u8 txp		= max(ns_to_t(6), 3);	/* JEDEC: max(6 ns, 3nCK) */
+	u8 trtp		= max(ns_to_t(8), 2);	/* JEDEC: max(7.5 ns, 4nCK) */
+	u8 trp		= ns_to_t(15);		/* JEDEC: >= 13.75 ns */
+	u8 tras		= ns_to_t(38);		/* JEDEC >= 36 ns, <= 9*trefi */
+	u16 trefi	= ns_to_t(7800) / 32;	/* JEDEC: 7.8us@Tcase <= 85C */
+	u16 trfc	= ns_to_t(350);		/* JEDEC: 160 ns for 2Gb */
+	u16 txsr	= 4;			/* ? */
+
+	u8 tmrw		= 0;			/* ? */
+	u8 tmrd		= 4;			/* JEDEC: 4nCK */
+	u8 tmod		= max(ns_to_t(15), 12);	/* JEDEC: max(15 ns, 12nCK) */
+	u8 tcke		= max(ns_to_t(6), 3);	/* JEDEC: max(5.625 ns, 3nCK) */
+	u8 tcksrx	= max(ns_to_t(10), 4);	/* JEDEC: max(10 ns, 5nCK) */
+	u8 tcksre	= max(ns_to_t(10), 4);	/* JEDEC: max(10 ns, 5nCK) */
+	u8 tckesr	= tcke + 1;		/* JEDEC: tCKE(min) + 1nCK */
+	u8 trasmax	= (para->clk / 2) / 15;	/* JEDEC: tREFI * 9 */
+	u8 txs		= ns_to_t(360) / 32;	/* JEDEC: max(5nCK,tRFC+10ns) */
+	u8 txsdll	= 16;			/* JEDEC: 512 nCK */
+	u8 txsabort	= 4;			/* ? */
+	u8 txsfast	= 4;			/* ? */
+	u8 tcl		= 7;			/* JEDEC: CL / 2 => 6 */
+	u8 tcwl		= 5;			/* JEDEC: 8 */
+	u8 t_rdata_en	= 9;			/* ? */
+
+	u8 twtp		= 14;			/* (WL + BL / 2 + tWR) / 2 */
+	u8 twr2rd	= trtp + 7;		/* (WL + BL / 2 + tWTR) / 2 */
+	u8 trd2wr	= 5;			/* (RL + BL / 2 + 2 - WL) / 2 */
+
+	/* set DRAM timing */
+	writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
+	       &mctl_ctl->dramtmg[0]);
+	writel((txp << 16) | (trtp << 8) | trc, &mctl_ctl->dramtmg[1]);
+	writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | twr2rd,
+	       &mctl_ctl->dramtmg[2]);
+	writel((tmrw << 20) | (tmrd << 12) | tmod, &mctl_ctl->dramtmg[3]);
+	writel((trcd << 24) | (tccd << 16) | (trrd << 8) | trp,
+	       &mctl_ctl->dramtmg[4]);
+	writel((tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | tcke,
+	       &mctl_ctl->dramtmg[5]);
+	/* Value suggested by ZynqMP manual and used by libdram */
+	writel((txp + 2) | 0x02020000, &mctl_ctl->dramtmg[6]);
+	writel((txsfast << 24) | (txsabort << 16) | (txsdll << 8) | txs,
+	       &mctl_ctl->dramtmg[8]);
+	writel(0x00020208, &mctl_ctl->dramtmg[9]);
+	writel(0xE0C05, &mctl_ctl->dramtmg[10]);
+	writel(0x440C021C, &mctl_ctl->dramtmg[11]);
+	writel(8, &mctl_ctl->dramtmg[12]);
+	writel(0xA100002, &mctl_ctl->dramtmg[13]);
+	writel(txsr, &mctl_ctl->dramtmg[14]);
+
+	clrbits_le32(&mctl_ctl->init[0], 3 << 30);
+	writel(0x420000, &mctl_ctl->init[1]);
+	writel(5, &mctl_ctl->init[2]);
+	writel(0x1f140004, &mctl_ctl->init[3]);
+	writel(0x00200000, &mctl_ctl->init[4]);
+
+	writel(0, &mctl_ctl->dfimisc);
+	clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
+
+	/* Configure DFI timing */
+	writel((tcl - 2) | 0x2000000 | (t_rdata_en << 16) | 0x808000,
+	       &mctl_ctl->dfitmg0);
+	writel(0x100202, &mctl_ctl->dfitmg1);
+
+	/* set refresh timing */
+	writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
+}
-- 
2.30.0

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

* [PATCH 12/17] sunxi: Add support for H616 SoC
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (10 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 11/17] sunxi: Add H616 DRAM support Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-04  2:47   ` [linux-sunxi] " Samuel Holland
  2021-01-03  9:26 ` [PATCH 13/17] net: sun8i-emac: Determine pinmux based on SoC, not EMAC type Jernej Skrabec
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

H616 is very similar to H6 so most of the infrastructure can be reused.
However, two big differences are that it doesn't have functional SRAM A2
which is usually used for TF-A and it doesn't have ARISC co-processor.
It also needs bigger SPL size - 48 KiB.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/dts/sunxi-u-boot.dtsi                  |  9 +++++++++
 arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h |  7 +++++++
 arch/arm/mach-sunxi/Kconfig                     | 11 ++++++++++-
 arch/arm/mach-sunxi/cpu_info.c                  |  2 ++
 drivers/power/Kconfig                           |  1 +
 include/configs/sunxi-common.h                  | 10 ++++++++++
 6 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index c77cf7cacf0c..7e8644f390a8 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -3,6 +3,9 @@
 #ifdef CONFIG_MACH_SUN50I_H6
 #define BL31_ADDR 0x104000
 #define  SCP_ADDR 0x114000
+#elif defined(CONFIG_MACH_SUN50I_H616)
+#define BL31_ADDR 0x40004000
+#define  SCP_ADDR 0x028000
 #else
 #define BL31_ADDR  0x44000
 #define  SCP_ADDR  0x50000
@@ -61,6 +64,7 @@
 					};
 				};
 
+#ifndef CONFIG_MACH_SUN50I_H616
 				scp {
 					description = "SCP firmware";
 					type = "firmware";
@@ -73,6 +77,7 @@
 						missing-msg = "scp-sunxi";
 					};
 				};
+#endif
 
 				@fdt-SEQ {
 					description = "NAME";
@@ -87,7 +92,11 @@
 				@config-SEQ {
 					description = "NAME";
 					firmware = "atf";
+#ifdef CONFIG_MACH_SUN50I_H616
+					loadables = "uboot";
+#else
 					loadables = "scp", "uboot";
+#endif
 					fdt = "fdt-SEQ";
 				};
 			};
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
index 6392cb07b472..d9cf8ae04288 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
@@ -28,13 +28,20 @@
 #define SUNXI_GIC400_BASE		0x03020000
 #define SUNXI_IOMMU_BASE		0x030F0000
 
+#ifdef CONFIG_MACH_SUN50I_H6
 #define SUNXI_DRAM_COM_BASE		0x04002000
 #define SUNXI_DRAM_CTL0_BASE		0x04003000
 #define SUNXI_DRAM_PHY0_BASE		0x04005000
+#endif
 #define SUNXI_NFC_BASE			0x04011000
 #define SUNXI_MMC0_BASE			0x04020000
 #define SUNXI_MMC1_BASE			0x04021000
 #define SUNXI_MMC2_BASE			0x04022000
+#ifdef CONFIG_MACH_SUN50I_H616
+#define SUNXI_DRAM_COM_BASE		0x047FA000
+#define SUNXI_DRAM_CTL0_BASE		0x047FB000
+#define SUNXI_DRAM_PHY0_BASE		0x04800000
+#endif
 
 #define SUNXI_UART0_BASE		0x05000000
 #define SUNXI_UART1_BASE		0x05000400
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 1a5497989f04..859b30d74ceb 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -190,9 +190,10 @@ config MACH_SUNXI_H3_H5
 	select SUPPORT_SPL
 
 # TODO: try out A80's 8GiB DRAM space
+# TODO: H616 supports 4 GiB DRAM space
 config SUNXI_DRAM_MAX_SIZE
 	hex
-	default 0xC0000000 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6
+	default 0xC0000000 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6 || MACH_SUN50I_H616
 	default 0x80000000
 
 choice
@@ -354,6 +355,12 @@ config MACH_SUN50I_H6
 	select PHY_SUN4I_USB
 	select DRAM_SUN50I_H6
 
+config MACH_SUN50I_H616
+	bool "sun50i (Allwinner H616)"
+	select ARM64
+	select DRAM_SUN50I_H616
+	select SUN50I_GEN_H6
+
 endchoice
 
 # The sun8i SoCs share a lot, this helps to avoid a lot of "if A23 || A33"
@@ -589,6 +596,7 @@ config SYS_CLK_FREQ
 	default 816000000 if MACH_SUN50I || MACH_SUN50I_H5
 	default 1008000000 if MACH_SUN8I
 	default 1008000000 if MACH_SUN9I
+	default 1008000000 if MACH_SUN50I_H616
 
 config SYS_CONFIG_NAME
 	default "sun4i" if MACH_SUN4I
@@ -599,6 +607,7 @@ config SYS_CONFIG_NAME
 	default "sun9i" if MACH_SUN9I
 	default "sun50i" if MACH_SUN50I
 	default "sun50i" if MACH_SUN50I_H6
+	default "sun50i" if MACH_SUN50I_H616
 
 config SYS_BOARD
 	default "sunxi"
diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
index 875e5a1a8a8e..ba33ef24300c 100644
--- a/arch/arm/mach-sunxi/cpu_info.c
+++ b/arch/arm/mach-sunxi/cpu_info.c
@@ -99,6 +99,8 @@ int print_cpuinfo(void)
 	puts("CPU:   Allwinner H5 (SUN50I)\n");
 #elif defined CONFIG_MACH_SUN50I_H6
 	puts("CPU:   Allwinner H6 (SUN50I)\n");
+#elif defined CONFIG_MACH_SUN50I_H616
+	puts("CPU:   Allwinner H616 (SUN50I)\n");
 #else
 #warning Please update cpu_info.c with correct CPU information
 	puts("CPU:   SUNXI Family\n");
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index d17cf2d9112a..c5fbf1f832a9 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -13,6 +13,7 @@ choice
 	depends on ARCH_SUNXI
 	default AXP209_POWER if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
 	default AXP221_POWER if MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33 || MACH_SUN8I_R40
+	default AXP305_POWER if MACH_SUN50I_H616
 	default AXP818_POWER if MACH_SUN8I_A83T
 	default SUNXI_NO_PMIC if MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_V3S
 
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 203cb10fbabc..6e8f547214d6 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -178,9 +178,14 @@
 #define LOW_LEVEL_SRAM_STACK		0x00018000
 #endif /* !CONFIG_ARM64 */
 #elif CONFIG_SUNXI_SRAM_ADDRESS == 0x20000
+#ifdef CONFIG_MACH_SUN50I_H616
+#define CONFIG_SPL_MAX_SIZE		0xbfa0		/* 48 KiB */
+#define LOW_LEVEL_SRAM_STACK		0x58000
+#else
 #define CONFIG_SPL_MAX_SIZE		0x7fa0		/* 32 KiB */
 /* end of SRAM A2 on H6 for now */
 #define LOW_LEVEL_SRAM_STACK		0x00118000
+#endif
 #else
 #define CONFIG_SPL_MAX_SIZE		0x5fa0		/* 24KB on sun4i/sun7i */
 #define LOW_LEVEL_SRAM_STACK		0x00008000	/* End of sram */
@@ -188,7 +193,12 @@
 
 #define CONFIG_SPL_STACK		LOW_LEVEL_SRAM_STACK
 
+/* H616 supports 48 KiB SPL */
+#ifdef CONFIG_MACH_SUN50I_H616
+#define CONFIG_SPL_PAD_TO		49152		/* decimal for 'dd' */
+#else
 #define CONFIG_SPL_PAD_TO		32768		/* decimal for 'dd' */
+#endif
 
 
 /* I2C */
-- 
2.30.0

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

* [PATCH 13/17] net: sun8i-emac: Determine pinmux based on SoC, not EMAC type
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (11 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 12/17] sunxi: Add support for H616 SoC Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-03  9:26 ` [PATCH 14/17] arm: sunxi: add initial H616 DTSI and headers Jernej Skrabec
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

From: Andre Przywara <andre.przywara@arm.com>

---
 drivers/net/sun8i_emac.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index 4524604126c9..7e57f1d01c8c 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -85,7 +85,9 @@
 
 /* IO mux settings */
 #define SUN8I_IOMUX_H3		2
-#define SUN8I_IOMUX_R40	5
+#define SUN8I_IOMUX_R40		5
+#define SUN8I_IOMUX_H6		5
+#define SUN8I_IOMUX_H616	2
 #define SUN8I_IOMUX		4
 
 /* H3/A64 EMAC Register's offset */
@@ -519,10 +521,10 @@ static int sun8i_emac_eth_start(struct udevice *dev)
 
 static int parse_phy_pins(struct udevice *dev)
 {
-	struct emac_eth_dev *priv = dev_get_priv(dev);
 	int offset;
 	const char *pin_name;
 	int drive, pull = SUN4I_PINCTRL_NO_PULL, i;
+	u32 iomux;
 
 	offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev),
 				       "pinctrl-0");
@@ -549,6 +551,21 @@ static int parse_phy_pins(struct udevice *dev)
 	else if (fdt_get_property(gd->fdt_blob, offset, "bias-pull-down", NULL))
 		pull = SUN4I_PINCTRL_PULL_DOWN;
 
+	/*
+	 * The GPIO pinmux value is an integration choice, so depends on the
+	 * SoC, not the EMAC variant.
+	 */
+	if (IS_ENABLED(CONFIG_MACH_SUN8I_H3))
+		iomux = SUN8I_IOMUX_H3;
+	else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40))
+		iomux = SUN8I_IOMUX_R40;
+	else if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
+		iomux = SUN8I_IOMUX_H6;
+	else if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
+		iomux = SUN8I_IOMUX_H616;
+	else
+		iomux = SUN8I_IOMUX;
+
 	for (i = 0; ; i++) {
 		int pin;
 
@@ -561,12 +578,7 @@ static int parse_phy_pins(struct udevice *dev)
 		if (pin < 0)
 			continue;
 
-		if (priv->variant == H3_EMAC)
-			sunxi_gpio_set_cfgpin(pin, SUN8I_IOMUX_H3);
-		else if (priv->variant == R40_GMAC || priv->variant == H6_EMAC)
-			sunxi_gpio_set_cfgpin(pin, SUN8I_IOMUX_R40);
-		else
-			sunxi_gpio_set_cfgpin(pin, SUN8I_IOMUX);
+		sunxi_gpio_set_cfgpin(pin, iomux);
 
 		if (drive != ~0)
 			sunxi_gpio_set_drv(pin, drive);
-- 
2.30.0

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

* [PATCH 14/17] arm: sunxi: add initial H616 DTSI and headers
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (12 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 13/17] net: sun8i-emac: Determine pinmux based on SoC, not EMAC type Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-03  9:26 ` [PATCH 15/17] sunxi: gpio: introduce compatible for H616 Jernej Skrabec
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

This commit introduces H616 DTSI file and dt-bindings headers needed for
device tree files.

Files are taken from initial Linux H616 support submission with minor
change - emac0 fallback has H6 compatible instead of A64, otherwise
network doesn't work. H616 DTSI is not merged upstream yet.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/dts/sun50i-h616.dtsi               | 716 ++++++++++++++++++++
 include/dt-bindings/clock/sun50i-h616-ccu.h | 115 ++++
 include/dt-bindings/reset/sun50i-h616-ccu.h |  70 ++
 3 files changed, 901 insertions(+)
 create mode 100644 arch/arm/dts/sun50i-h616.dtsi
 create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h

diff --git a/arch/arm/dts/sun50i-h616.dtsi b/arch/arm/dts/sun50i-h616.dtsi
new file mode 100644
index 000000000000..d416e9a3d3e6
--- /dev/null
+++ b/arch/arm/dts/sun50i-h616.dtsi
@@ -0,0 +1,716 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2020 Arm Ltd.
+// based on the H6 dtsi, which is:
+//   Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun50i-h616-ccu.h>
+#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
+#include <dt-bindings/reset/sun50i-h616-ccu.h>
+#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+			reg = <0>;
+			enable-method = "psci";
+			clocks = <&ccu CLK_CPUX>;
+		};
+
+		cpu1: cpu at 1 {
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+			reg = <1>;
+			enable-method = "psci";
+			clocks = <&ccu CLK_CPUX>;
+		};
+
+		cpu2: cpu at 2 {
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+			reg = <2>;
+			enable-method = "psci";
+			clocks = <&ccu CLK_CPUX>;
+		};
+
+		cpu3: cpu at 3 {
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+			reg = <3>;
+			enable-method = "psci";
+			clocks = <&ccu CLK_CPUX>;
+		};
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* 512KiB reserved for ARM Trusted Firmware (BL31) */
+		secmon_reserved: secmon at 40000000 {
+			reg = <0x0 0x40000000 0x0 0x80000>;
+			no-map;
+		};
+	};
+
+	osc24M: osc24M_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "osc24M";
+	};
+
+	pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		arm,no-tick-in-suspend;
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0x0 0x0 0x40000000>;
+
+		syscon: syscon at 3000000 {
+			compatible = "allwinner,sun50i-h616-system-control";
+			reg = <0x03000000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			sram_c: sram at 28000 {
+				compatible = "mmio-sram";
+				reg = <0x00028000 0x30000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x00028000 0x30000>;
+			};
+		};
+
+		ccu: clock at 3001000 {
+			compatible = "allwinner,sun50i-h616-ccu";
+			reg = <0x03001000 0x1000>;
+			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
+			clock-names = "hosc", "losc", "iosc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		watchdog: watchdog at 30090a0 {
+			compatible = "allwinner,sun50i-h616-wdt",
+				     "allwinner,sun6i-a31-wdt";
+			reg = <0x030090a0 0x20>;
+			interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&osc24M>;
+			status = "disabled";
+		};
+
+		pio: pinctrl at 300b000 {
+			compatible = "allwinner,sun50i-h616-pinctrl";
+			reg = <0x0300b000 0x400>;
+			interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+
+			ext_rgmii_pins: rgmii-pins {
+				pins = "PI0", "PI1", "PI2", "PI3", "PI4",
+				       "PI5", "PI7", "PI8", "PI9", "PI10",
+				       "PI11", "PI12", "PI13", "PI14", "PI15",
+				       "PI16";
+				function = "emac0";
+				drive-strength = <40>;
+			};
+
+			i2c0_pins: i2c0-pins {
+				pins = "PI6", "PI7";
+				function = "i2c0";
+			};
+
+			i2c3_ph_pins: i2c3-ph-pins {
+				pins = "PH4", "PH5";
+				function = "i2c3";
+			};
+
+			ir_rx_pin: ir_rx_pin {
+				pins = "PH10";
+				function = "ir_rx";
+			};
+
+			mmc0_pins: mmc0-pins {
+				pins = "PF0", "PF1", "PF2", "PF3",
+				       "PF4", "PF5";
+				function = "mmc0";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
+			mmc1_pins: mmc1-pins {
+				pins = "PG0", "PG1", "PG2", "PG3",
+				       "PG4", "PG5";
+				function = "mmc1";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
+			mmc2_pins: mmc2-pins {
+				pins = "PC0", "PC1", "PC5", "PC6",
+				       "PC8", "PC9", "PC10", "PC11",
+				       "PC13", "PC14", "PC15", "PC16";
+				function = "mmc2";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
+			spi0_pins: spi0-pins {
+				pins = "PC0", "PC2", "PC3", "PC4";
+				function = "spi0";
+			};
+
+			spi1_pins: spi1-pins {
+				pins = "PH6", "PH7", "PH8";
+				function = "spi1";
+			};
+
+			spi1_cs_pin: spi1-cs-pin {
+				pins = "PH5";
+				function = "spi1";
+			};
+
+			uart0_ph_pins: uart0-ph-pins {
+				pins = "PH0", "PH1";
+				function = "uart0";
+			};
+
+			uart1_pins: uart1-pins {
+				pins = "PG6", "PG7";
+				function = "uart1";
+			};
+
+			uart1_rts_cts_pins: uart1-rts-cts-pins {
+				pins = "PG8", "PG9";
+				function = "uart1";
+			};
+		};
+
+		gic: interrupt-controller at 3021000 {
+			compatible = "arm,gic-400";
+			reg = <0x03021000 0x1000>,
+			      <0x03022000 0x2000>,
+			      <0x03024000 0x2000>,
+			      <0x03026000 0x2000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+		};
+
+		mmc0: mmc at 4020000 {
+			compatible = "allwinner,sun50i-h616-mmc",
+				     "allwinner,sun50i-a100-mmc";
+			reg = <0x04020000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC0>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc0_pins>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mmc1: mmc at 4021000 {
+			compatible = "allwinner,sun50i-h616-mmc",
+				     "allwinner,sun50i-a100-mmc";
+			reg = <0x04021000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC1>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc1_pins>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mmc2: mmc at 4022000 {
+			compatible = "allwinner,sun50i-h616-emmc",
+				     "allwinner,sun50i-a100-emmc";
+			reg = <0x04022000 0x1000>;
+			clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+			clock-names = "ahb", "mmc";
+			resets = <&ccu RST_BUS_MMC2>;
+			reset-names = "ahb";
+			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&mmc2_pins>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		uart0: serial at 5000000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x05000000 0x400>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART0>;
+			resets = <&ccu RST_BUS_UART0>;
+			status = "disabled";
+		};
+
+		uart1: serial at 5000400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x05000400 0x400>;
+			interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART1>;
+			resets = <&ccu RST_BUS_UART1>;
+			status = "disabled";
+		};
+
+		uart2: serial at 5000800 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x05000800 0x400>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART2>;
+			resets = <&ccu RST_BUS_UART2>;
+			status = "disabled";
+		};
+
+		uart3: serial at 5000c00 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x05000c00 0x400>;
+			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART3>;
+			resets = <&ccu RST_BUS_UART3>;
+			status = "disabled";
+		};
+
+		uart4: serial at 5001000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x05001000 0x400>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART4>;
+			resets = <&ccu RST_BUS_UART4>;
+			status = "disabled";
+		};
+
+		uart5: serial at 5001400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x05001400 0x400>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART5>;
+			resets = <&ccu RST_BUS_UART5>;
+			status = "disabled";
+		};
+
+		i2c0: i2c at 5002000 {
+			compatible = "allwinner,sun50i-h616-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x05002000 0x400>;
+			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C0>;
+			resets = <&ccu RST_BUS_I2C0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c1: i2c at 5002400 {
+			compatible = "allwinner,sun50i-h616-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x05002400 0x400>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C1>;
+			resets = <&ccu RST_BUS_I2C1>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c2: i2c at 5002800 {
+			compatible = "allwinner,sun50i-h616-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x05002800 0x400>;
+			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C2>;
+			resets = <&ccu RST_BUS_I2C2>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c3: i2c at 5002c00 {
+			compatible = "allwinner,sun50i-h616-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x05002c00 0x400>;
+			interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C3>;
+			resets = <&ccu RST_BUS_I2C3>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c4: i2c at 5003000 {
+			compatible = "allwinner,sun50i-h616-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x05003000 0x400>;
+			interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_I2C4>;
+			resets = <&ccu RST_BUS_I2C4>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		spi0: spi at 5010000 {
+			compatible = "allwinner,sun50i-h616-spi",
+				     "allwinner,sun8i-h3-spi";
+			reg = <0x05010000 0x1000>;
+			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+			clock-names = "ahb", "mod";
+			resets = <&ccu RST_BUS_SPI0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi0_pins>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		spi1: spi at 5011000 {
+			compatible = "allwinner,sun50i-h616-spi",
+				     "allwinner,sun8i-h3-spi";
+			reg = <0x05011000 0x1000>;
+			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+			clock-names = "ahb", "mod";
+			resets = <&ccu RST_BUS_SPI1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi1_pins>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		emac0: ethernet at 5020000 {
+			compatible = "allwinner,sun50i-h616-emac",
+				     "allwinner,sun50i-h6-emac",
+				     "allwinner,sun50i-a64-emac";
+			syscon = <&syscon>;
+			reg = <0x05020000 0x10000>;
+			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq";
+			resets = <&ccu RST_BUS_EMAC0>;
+			reset-names = "stmmaceth";
+			clocks = <&ccu CLK_BUS_EMAC0>;
+			clock-names = "stmmaceth";
+			status = "disabled";
+
+			mdio0: mdio {
+				compatible = "snps,dwmac-mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+		};
+
+		emac1: ethernet at 5030000 {
+			compatible = "allwinner,sun50i-h616-emac";
+			syscon = <&syscon 1>;
+			reg = <0x05030000 0x10000>;
+			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq";
+			resets = <&ccu RST_BUS_EMAC1>;
+			reset-names = "stmmaceth";
+			clocks = <&ccu CLK_BUS_EMAC1>;
+			clock-names = "stmmaceth";
+			status = "disabled";
+
+			mdio1: mdio {
+				compatible = "snps,dwmac-mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+		};
+
+		usbotg: usb at 5100000 {
+			compatible = "allwinner,sun50i-h616-musb",
+				     "allwinner,sun8i-h3-musb";
+			reg = <0x05100000 0x0400>;
+			clocks = <&ccu CLK_BUS_OTG>;
+			resets = <&ccu RST_BUS_OTG>;
+			interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "mc";
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			extcon = <&usbphy 0>;
+			status = "disabled";
+		};
+
+		usbphy: phy at 5100400 {
+			compatible = "allwinner,sun50i-h616-usb-phy";
+			reg = <0x05100400 0x24>,
+			      <0x05101800 0x14>,
+			      <0x05200800 0x14>,
+			      <0x05310800 0x14>,
+			      <0x05311800 0x14>;
+			reg-names = "phy_ctrl",
+				    "pmu0",
+				    "pmu1",
+				    "pmu2",
+				    "pmu3";
+			clocks = <&ccu CLK_USB_PHY0>,
+				 <&ccu CLK_USB_PHY1>,
+				 <&ccu CLK_USB_PHY2>,
+				 <&ccu CLK_USB_PHY3>;
+			clock-names = "usb0_phy",
+				      "usb1_phy",
+				      "usb2_phy",
+				      "usb3_phy";
+			resets = <&ccu RST_USB_PHY0>,
+				 <&ccu RST_USB_PHY1>,
+				 <&ccu RST_USB_PHY2>,
+				 <&ccu RST_USB_PHY3>;
+			reset-names = "usb0_reset",
+				      "usb1_reset",
+				      "usb2_reset",
+				      "usb3_reset";
+			status = "disabled";
+			#phy-cells = <1>;
+		};
+
+		ehci0: usb at 5101000 {
+			compatible = "allwinner,sun50i-h616-ehci",
+				     "generic-ehci";
+			reg = <0x05101000 0x100>;
+			interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI0>,
+				 <&ccu CLK_BUS_EHCI0>,
+				 <&ccu CLK_USB_OHCI0>;
+			resets = <&ccu RST_BUS_OHCI0>,
+				 <&ccu RST_BUS_EHCI0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci0: usb at 5101400 {
+			compatible = "allwinner,sun50i-h616-ohci",
+				     "generic-ohci";
+			reg = <0x05101400 0x100>;
+			interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI0>,
+				 <&ccu CLK_USB_OHCI0>;
+			resets = <&ccu RST_BUS_OHCI0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ehci1: usb at 5200000 {
+			compatible = "allwinner,sun50i-h616-ehci",
+				     "generic-ehci";
+			reg = <0x05200000 0x100>;
+			interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI1>,
+				 <&ccu CLK_BUS_EHCI1>,
+				 <&ccu CLK_USB_OHCI1>;
+			resets = <&ccu RST_BUS_OHCI1>,
+				 <&ccu RST_BUS_EHCI1>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci1: usb at 5200400 {
+			compatible = "allwinner,sun50i-h616-ohci",
+				     "generic-ohci";
+			reg = <0x05200400 0x100>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI1>,
+				 <&ccu CLK_USB_OHCI1>;
+			resets = <&ccu RST_BUS_OHCI1>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ehci2: usb at 5310000 {
+			compatible = "allwinner,sun50i-h616-ehci",
+				     "generic-ehci";
+			reg = <0x05310000 0x100>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI2>,
+				 <&ccu CLK_BUS_EHCI2>,
+				 <&ccu CLK_USB_OHCI2>;
+			resets = <&ccu RST_BUS_OHCI2>,
+				 <&ccu RST_BUS_EHCI2>;
+			phys = <&usbphy 2>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci2: usb at 5310400 {
+			compatible = "allwinner,sun50i-h616-ohci",
+				     "generic-ohci";
+			reg = <0x05310400 0x100>;
+			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI2>,
+				 <&ccu CLK_USB_OHCI2>;
+			resets = <&ccu RST_BUS_OHCI2>;
+			phys = <&usbphy 2>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ehci3: usb at 5311000 {
+			compatible = "allwinner,sun50i-h616-ehci",
+				     "generic-ehci";
+			reg = <0x05311000 0x100>;
+			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI3>,
+				 <&ccu CLK_BUS_EHCI3>,
+				 <&ccu CLK_USB_OHCI3>;
+			resets = <&ccu RST_BUS_OHCI3>,
+				 <&ccu RST_BUS_EHCI3>;
+			phys = <&usbphy 3>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci3: usb at 5311400 {
+			compatible = "allwinner,sun50i-h616-ohci",
+				     "generic-ohci";
+			reg = <0x05311400 0x100>;
+			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_OHCI3>,
+				 <&ccu CLK_USB_OHCI3>;
+			resets = <&ccu RST_BUS_OHCI3>;
+			phys = <&usbphy 3>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		rtc: rtc at 7000000 {
+			compatible = "allwinner,sun50i-h616-rtc",
+				     "allwinner,sun50i-h6-rtc";
+			reg = <0x07000000 0x400>;
+			interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+			clock-output-names = "osc32k", "osc32k-out", "iosc";
+			#clock-cells = <1>;
+		};
+
+		r_ccu: clock at 7010000 {
+			compatible = "allwinner,sun50i-h616-r-ccu";
+			reg = <0x07010000 0x400>;
+			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>,
+				 <&ccu CLK_PLL_PERIPH0>;
+			clock-names = "hosc", "losc", "iosc", "pll-periph";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		r_pio: pinctrl at 7022000 {
+			compatible = "allwinner,sun50i-h616-r-pinctrl";
+			reg = <0x07022000 0x400>;
+			interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>;
+			clock-names = "apb", "hosc", "losc";
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+
+			r_i2c_pins: r-i2c-pins {
+				pins = "PL0", "PL1";
+				function = "s_i2c";
+			};
+		};
+
+		ir: ir at 7040000 {
+				compatible = "allwinner,sun50i-h616-ir",
+					     "allwinner,sun6i-a31-ir";
+				reg = <0x07040000 0x400>;
+				interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&r_ccu CLK_R_APB1_IR>,
+					 <&r_ccu CLK_IR>;
+				clock-names = "apb", "ir";
+				resets = <&r_ccu RST_R_APB1_IR>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&ir_rx_pin>;
+				status = "disabled";
+		};
+
+		r_i2c: i2c at 7081400 {
+			compatible = "allwinner,sun50i-h616-i2c",
+				     "allwinner,sun6i-a31-i2c";
+			reg = <0x07081400 0x400>;
+			interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&r_ccu CLK_R_APB2_I2C>;
+			resets = <&r_ccu RST_R_APB2_I2C>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+};
diff --git a/include/dt-bindings/clock/sun50i-h616-ccu.h b/include/dt-bindings/clock/sun50i-h616-ccu.h
new file mode 100644
index 000000000000..4fc08b0df2f3
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_H616_H_
+#define _DT_BINDINGS_CLK_SUN50I_H616_H_
+
+#define CLK_PLL_PERIPH0		4
+
+#define CLK_CPUX		21
+
+#define CLK_APB1		26
+
+#define CLK_DE			29
+#define CLK_BUS_DE		30
+#define CLK_DEINTERLACE		31
+#define CLK_BUS_DEINTERLACE	32
+#define CLK_G2D			33
+#define CLK_BUS_G2D		34
+#define CLK_GPU0		35
+#define CLK_BUS_GPU		36
+#define CLK_GPU1		37
+#define CLK_CE			38
+#define CLK_BUS_CE		39
+#define CLK_VE			40
+#define CLK_BUS_VE		41
+#define CLK_BUS_DMA		42
+#define CLK_BUS_HSTIMER		43
+#define CLK_AVS			44
+#define CLK_BUS_DBG		45
+#define CLK_BUS_PSI		46
+#define CLK_BUS_PWM		47
+#define CLK_BUS_IOMMU		48
+
+#define CLK_MBUS_DMA		50
+#define CLK_MBUS_VE		51
+#define CLK_MBUS_CE		52
+#define CLK_MBUS_TS		53
+#define CLK_MBUS_NAND		54
+#define CLK_MBUS_G2D		55
+
+#define CLK_NAND0		57
+#define CLK_NAND1		58
+#define CLK_BUS_NAND		59
+#define CLK_MMC0		60
+#define CLK_MMC1		61
+#define CLK_MMC2		62
+#define CLK_BUS_MMC0		63
+#define CLK_BUS_MMC1		64
+#define CLK_BUS_MMC2		65
+#define CLK_BUS_UART0		66
+#define CLK_BUS_UART1		67
+#define CLK_BUS_UART2		68
+#define CLK_BUS_UART3		69
+#define CLK_BUS_UART4		70
+#define CLK_BUS_UART5		71
+#define CLK_BUS_I2C0		72
+#define CLK_BUS_I2C1		73
+#define CLK_BUS_I2C2		74
+#define CLK_BUS_I2C3		75
+#define CLK_BUS_I2C4		76
+#define CLK_SPI0		77
+#define CLK_SPI1		78
+#define CLK_BUS_SPI0		79
+#define CLK_BUS_SPI1		80
+#define CLK_EMAC_25M		81
+#define CLK_BUS_EMAC0		82
+#define CLK_BUS_EMAC1		83
+#define CLK_TS			84
+#define CLK_BUS_TS		85
+#define CLK_BUS_THS		86
+#define CLK_SPDIF		87
+#define CLK_BUS_SPDIF		88
+#define CLK_DMIC		89
+#define CLK_BUS_DMIC		90
+#define CLK_AUDIO_CODEC_1X	91
+#define CLK_AUDIO_CODEC_4X	92
+#define CLK_BUS_AUDIO_CODEC	93
+#define CLK_AUDIO_HUB		94
+#define CLK_BUS_AUDIO_HUB	95
+#define CLK_USB_OHCI0		96
+#define CLK_USB_PHY0		97
+#define CLK_USB_OHCI1		98
+#define CLK_USB_PHY1		99
+#define CLK_USB_OHCI2		100
+#define CLK_USB_PHY2		101
+#define CLK_USB_OHCI3		102
+#define CLK_USB_PHY3		103
+#define CLK_BUS_OHCI0		104
+#define CLK_BUS_OHCI1		105
+#define CLK_BUS_OHCI2		106
+#define CLK_BUS_OHCI3		107
+#define CLK_BUS_EHCI0		108
+#define CLK_BUS_EHCI1		109
+#define CLK_BUS_EHCI2		110
+#define CLK_BUS_EHCI3		111
+#define CLK_BUS_OTG		112
+#define CLK_BUS_KEYADC		113
+#define CLK_HDMI		114
+#define CLK_HDMI_SLOW		115
+#define CLK_HDMI_CEC		116
+#define CLK_BUS_HDMI		117
+#define CLK_BUS_TCON_TOP	118
+#define CLK_TCON_TV0		119
+#define CLK_TCON_TV1		120
+#define CLK_BUS_TCON_TV0	121
+#define CLK_BUS_TCON_TV1	122
+#define CLK_TVE0		123
+#define CLK_BUS_TVE_TOP		124
+#define CLK_BUS_TVE0		125
+#define CLK_HDCP		126
+#define CLK_BUS_HDCP		127
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_H616_H_ */
diff --git a/include/dt-bindings/reset/sun50i-h616-ccu.h b/include/dt-bindings/reset/sun50i-h616-ccu.h
new file mode 100644
index 000000000000..cb6285a8d128
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN50I_H616_H_
+#define _DT_BINDINGS_RESET_SUN50I_H616_H_
+
+#define RST_MBUS		0
+#define RST_BUS_DE		1
+#define RST_BUS_DEINTERLACE	2
+#define RST_BUS_GPU		3
+#define RST_BUS_CE		4
+#define RST_BUS_VE		5
+#define RST_BUS_DMA		6
+#define RST_BUS_HSTIMER		7
+#define RST_BUS_DBG		8
+#define RST_BUS_PSI		9
+#define RST_BUS_PWM		10
+#define RST_BUS_IOMMU		11
+#define RST_BUS_DRAM		12
+#define RST_BUS_NAND		13
+#define RST_BUS_MMC0		14
+#define RST_BUS_MMC1		15
+#define RST_BUS_MMC2		16
+#define RST_BUS_UART0		17
+#define RST_BUS_UART1		18
+#define RST_BUS_UART2		19
+#define RST_BUS_UART3		20
+#define RST_BUS_UART4		21
+#define RST_BUS_UART5		22
+#define RST_BUS_I2C0		23
+#define RST_BUS_I2C1		24
+#define RST_BUS_I2C2		25
+#define RST_BUS_I2C3		26
+#define RST_BUS_I2C4		27
+#define RST_BUS_SPI0		28
+#define RST_BUS_SPI1		29
+#define RST_BUS_EMAC0		30
+#define RST_BUS_EMAC1		31
+#define RST_BUS_TS		32
+#define RST_BUS_THS		33
+#define RST_BUS_SPDIF		34
+#define RST_BUS_DMIC		35
+#define RST_BUS_AUDIO_CODEC	36
+#define RST_BUS_AUDIO_HUB	37
+#define RST_USB_PHY0		38
+#define RST_USB_PHY1		39
+#define RST_USB_PHY2		40
+#define RST_USB_PHY3		41
+#define RST_BUS_OHCI0		42
+#define RST_BUS_OHCI1		43
+#define RST_BUS_OHCI2		44
+#define RST_BUS_OHCI3		45
+#define RST_BUS_EHCI0		46
+#define RST_BUS_EHCI1		47
+#define RST_BUS_EHCI2		48
+#define RST_BUS_EHCI3		49
+#define RST_BUS_OTG		50
+#define RST_BUS_HDMI		51
+#define RST_BUS_HDMI_SUB	52
+#define RST_BUS_TCON_TOP	53
+#define RST_BUS_TCON_TV0	54
+#define RST_BUS_TCON_TV1	55
+#define RST_BUS_TVE_TOP		56
+#define RST_BUS_TVE0		57
+#define RST_BUS_HDCP		58
+#define RST_BUS_KEYADC		59
+
+#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
-- 
2.30.0

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

* [PATCH 15/17] sunxi: gpio: introduce compatible for H616
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (13 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 14/17] arm: sunxi: add initial H616 DTSI and headers Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-11  0:36   ` André Przywara
  2021-01-03  9:26 ` [PATCH 16/17] clk: sunxi: Add support for H616 clocks Jernej Skrabec
  2021-01-03  9:26 ` [PATCH 17/17] sunxi: Add support for OrangePi Zero2 Jernej Skrabec
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

H616 pinctrl is no different configuration wise than others, so just add
compatible for it.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpio/sunxi_gpio.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index 02c3471b5684..1985ee5d2fc9 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -356,6 +356,7 @@ static const struct udevice_id sunxi_gpio_ids[] = {
 	ID("allwinner,sun9i-a80-pinctrl",	a_all),
 	ID("allwinner,sun50i-a64-pinctrl",	a_all),
 	ID("allwinner,sun50i-h6-pinctrl",	a_all),
+	ID("allwinner,sun50i-h616-pinctrl",	a_all),
 	ID("allwinner,sun6i-a31-r-pinctrl",	l_2),
 	ID("allwinner,sun8i-a23-r-pinctrl",	l_1),
 	ID("allwinner,sun8i-a83t-r-pinctrl",	l_1),
-- 
2.30.0

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

* [PATCH 16/17] clk: sunxi: Add support for H616 clocks
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (14 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 15/17] sunxi: gpio: introduce compatible for H616 Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  2021-01-11  0:44   ` André Przywara
  2021-01-03  9:26 ` [PATCH 17/17] sunxi: Add support for OrangePi Zero2 Jernej Skrabec
  16 siblings, 1 reply; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

This commit introduces DM H616 clock driver.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/clk/sunxi/Kconfig    |   7 ++
 drivers/clk/sunxi/Makefile   |   1 +
 drivers/clk/sunxi/clk_h616.c | 120 +++++++++++++++++++++++++++++++++++
 3 files changed, 128 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_h616.c

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index 5ff101b99305..bf084fa7a84a 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -79,6 +79,13 @@ config CLK_SUN50I_H6
 	  This enables common clock driver support for platforms based
 	  on Allwinner H6 SoC.
 
+config CLK_SUN50I_H616
+	bool "Clock driver for Allwinner H616"
+	default MACH_SUN50I_H616
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner H616 SoC.
+
 config CLK_SUN50I_A64
 	bool "Clock driver for Allwinner A64"
 	default MACH_SUN50I
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 36fb2aeb56c5..0dfc0593fb1c 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -16,4 +16,5 @@ obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o
 obj-$(CONFIG_CLK_SUN9I_A80) += clk_a80.o
 obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
 obj-$(CONFIG_CLK_SUN50I_H6) += clk_h6.o
+obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_h616.c b/drivers/clk/sunxi/clk_h616.c
new file mode 100644
index 000000000000..e2e3a5c78c95
--- /dev/null
+++ b/drivers/clk/sunxi/clk_h616.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2021 Jernej Skrabec <jernej.skrabec@siol.net>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/arch/ccu.h>
+#include <dt-bindings/clock/sun50i-h616-ccu.h>
+#include <dt-bindings/reset/sun50i-h616-ccu.h>
+#include <linux/bitops.h>
+
+static struct ccu_clk_gate h616_gates[] = {
+	[CLK_BUS_MMC0]		= GATE(0x84c, BIT(0)),
+	[CLK_BUS_MMC1]		= GATE(0x84c, BIT(1)),
+	[CLK_BUS_MMC2]		= GATE(0x84c, BIT(2)),
+
+	[CLK_BUS_UART0]		= GATE(0x90c, BIT(0)),
+	[CLK_BUS_UART1]		= GATE(0x90c, BIT(1)),
+	[CLK_BUS_UART2]		= GATE(0x90c, BIT(2)),
+	[CLK_BUS_UART3]		= GATE(0x90c, BIT(3)),
+	[CLK_BUS_UART4]		= GATE(0x90c, BIT(4)),
+	[CLK_BUS_UART5]		= GATE(0x90c, BIT(5)),
+
+	[CLK_SPI0]		= GATE(0x940, BIT(31)),
+	[CLK_SPI1]		= GATE(0x944, BIT(31)),
+
+	[CLK_BUS_SPI0]		= GATE(0x96c, BIT(0)),
+	[CLK_BUS_SPI1]		= GATE(0x96c, BIT(1)),
+
+	[CLK_BUS_EMAC0]		= GATE(0x97c, BIT(0)),
+	[CLK_BUS_EMAC1]		= GATE(0x97c, BIT(1)),
+
+	[CLK_USB_PHY0]		= GATE(0xa70, BIT(29)),
+	[CLK_USB_OHCI0]		= GATE(0xa70, BIT(31)),
+
+	[CLK_USB_PHY1]		= GATE(0xa74, BIT(29)),
+	[CLK_USB_OHCI1]		= GATE(0xa74, BIT(31)),
+
+	[CLK_USB_PHY2]		= GATE(0xa78, BIT(29)),
+	[CLK_USB_OHCI2]		= GATE(0xa78, BIT(31)),
+
+	[CLK_USB_PHY3]		= GATE(0xa7c, BIT(29)),
+	[CLK_USB_OHCI3]		= GATE(0xa7c, BIT(31)),
+
+	[CLK_BUS_OHCI0]		= GATE(0xa8c, BIT(0)),
+	[CLK_BUS_OHCI1]		= GATE(0xa8c, BIT(1)),
+	[CLK_BUS_OHCI2]		= GATE(0xa8c, BIT(2)),
+	[CLK_BUS_OHCI3]		= GATE(0xa8c, BIT(3)),
+	[CLK_BUS_EHCI0]		= GATE(0xa8c, BIT(4)),
+	[CLK_BUS_EHCI1]		= GATE(0xa8c, BIT(5)),
+	[CLK_BUS_EHCI2]		= GATE(0xa8c, BIT(6)),
+	[CLK_BUS_EHCI3]		= GATE(0xa8c, BIT(7)),
+	[CLK_BUS_OTG]		= GATE(0xa8c, BIT(8)),
+};
+
+static struct ccu_reset h616_resets[] = {
+	[RST_BUS_MMC0]		= RESET(0x84c, BIT(16)),
+	[RST_BUS_MMC1]		= RESET(0x84c, BIT(17)),
+	[RST_BUS_MMC2]		= RESET(0x84c, BIT(18)),
+
+	[RST_BUS_UART0]		= RESET(0x90c, BIT(16)),
+	[RST_BUS_UART1]		= RESET(0x90c, BIT(17)),
+	[RST_BUS_UART2]		= RESET(0x90c, BIT(18)),
+	[RST_BUS_UART3]		= RESET(0x90c, BIT(19)),
+	[RST_BUS_UART4]		= RESET(0x90c, BIT(20)),
+	[RST_BUS_UART5]		= RESET(0x90c, BIT(21)),
+
+	[RST_BUS_SPI0]		= RESET(0x96c, BIT(16)),
+	[RST_BUS_SPI1]		= RESET(0x96c, BIT(17)),
+
+	[RST_BUS_EMAC0]		= RESET(0x97c, BIT(16)),
+	[RST_BUS_EMAC1]		= RESET(0x97c, BIT(17)),
+
+	[RST_USB_PHY0]		= RESET(0xa70, BIT(30)),
+
+	[RST_USB_PHY1]		= RESET(0xa74, BIT(30)),
+
+	[RST_USB_PHY2]		= RESET(0xa78, BIT(30)),
+
+	[RST_USB_PHY3]		= RESET(0xa7c, BIT(30)),
+
+	[RST_BUS_OHCI0]		= RESET(0xa8c, BIT(16)),
+	[RST_BUS_OHCI1]		= RESET(0xa8c, BIT(17)),
+	[RST_BUS_OHCI2]		= RESET(0xa8c, BIT(18)),
+	[RST_BUS_OHCI3]		= RESET(0xa8c, BIT(19)),
+	[RST_BUS_EHCI0]		= RESET(0xa8c, BIT(20)),
+	[RST_BUS_EHCI1]		= RESET(0xa8c, BIT(21)),
+	[RST_BUS_EHCI2]		= RESET(0xa8c, BIT(22)),
+	[RST_BUS_EHCI3]		= RESET(0xa8c, BIT(23)),
+	[RST_BUS_OTG]		= RESET(0xa8c, BIT(24)),
+};
+
+static const struct ccu_desc h616_ccu_desc = {
+	.gates = h616_gates,
+	.resets = h616_resets,
+};
+
+static int h616_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, ARRAY_SIZE(h616_resets));
+}
+
+static const struct udevice_id h616_ccu_ids[] = {
+	{ .compatible = "allwinner,sun50i-h616-ccu",
+	  .data = (ulong)&h616_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun50i_h616) = {
+	.name		= "sun50i_h616_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= h616_ccu_ids,
+	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= h616_clk_bind,
+};
-- 
2.30.0

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

* [PATCH 17/17] sunxi: Add support for OrangePi Zero2
  2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
                   ` (15 preceding siblings ...)
  2021-01-03  9:26 ` [PATCH 16/17] clk: sunxi: Add support for H616 clocks Jernej Skrabec
@ 2021-01-03  9:26 ` Jernej Skrabec
  16 siblings, 0 replies; 48+ messages in thread
From: Jernej Skrabec @ 2021-01-03  9:26 UTC (permalink / raw)
  To: u-boot

OrangePi Zero2 is SBC based on Allwinner H616 with 1 GiB of RAM, SD card
support, gigabit ethernet, micro HDMI, WIFI, Bluetooth and 1 USB 2.0
port. It also has two GPIO headers which allows further peripherals to
be used.

Device Tree file is taken from initial OrangePi Zero2 Linux submission
and it's not yet merged.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/dts/Makefile                       |   2 +
 arch/arm/dts/sun50i-h616-orangepi-zero2.dts | 240 ++++++++++++++++++++
 board/sunxi/MAINTAINERS                     |   5 +
 configs/orangepi_zero2_defconfig            |  15 ++
 4 files changed, 262 insertions(+)
 create mode 100644 arch/arm/dts/sun50i-h616-orangepi-zero2.dts
 create mode 100644 configs/orangepi_zero2_defconfig

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index fd47e408f826..483502a1bd3c 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -608,6 +608,8 @@ dtb-$(CONFIG_MACH_SUN50I_H6) += \
 	sun50i-h6-orangepi-lite2.dtb \
 	sun50i-h6-orangepi-one-plus.dtb \
 	sun50i-h6-pine-h64.dtb
+dtb-$(CONFIG_MACH_SUN50I_H616) += \
+	sun50i-h616-orangepi-zero2.dtb
 dtb-$(CONFIG_MACH_SUN50I) += \
 	sun50i-a64-amarula-relic.dtb \
 	sun50i-a64-bananapi-m64.dtb \
diff --git a/arch/arm/dts/sun50i-h616-orangepi-zero2.dts b/arch/arm/dts/sun50i-h616-orangepi-zero2.dts
new file mode 100644
index 000000000000..2afc036059b4
--- /dev/null
+++ b/arch/arm/dts/sun50i-h616-orangepi-zero2.dts
@@ -0,0 +1,240 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+	model = "OrangePi Zero2";
+	compatible = "xunlong,orangepi-zero2", "allwinner,sun50i-h616";
+
+	aliases {
+		ethernet0 = &emac0;
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		power {
+			function = LED_FUNCTION_POWER;
+			color = <LED_COLOR_ID_RED>;
+			gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */
+			default-state = "on";
+		};
+
+		status {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+			gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */
+		};
+	};
+
+	reg_vcc5v: vcc5v {
+		/* board wide 5V supply directly from the USB-C socket */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	reg_usb1_vbus: usb1-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb1-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&reg_vcc5v>;
+		enable-active-high;
+		gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */
+		status = "okay";
+	};
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+/* USB 2 & 3 are on headers only. */
+
+&emac0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ext_rgmii_pins>;
+	phy-mode = "rgmii";
+	phy-handle = <&ext_rgmii_phy>;
+	phy-supply = <&reg_dcdce>;
+	allwinner,rx-delay-ps = <3100>;
+	allwinner,tx-delay-ps = <700>;
+	status = "okay";
+};
+
+&mdio0 {
+	ext_rgmii_phy: ethernet-phy at 1 {
+		compatible = "ethernet-phy-ieee802.3-c22";
+		reg = <1>;
+	};
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_dcdce>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;	/* PF6 */
+	bus-width = <4>;
+	status = "okay";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&r_i2c {
+	status = "okay";
+
+	axp305: pmic at 36 {
+		compatible = "x-powers,axp305", "x-powers,axp805",
+			     "x-powers,axp806";
+		reg = <0x36>;
+
+		x-powers,self-working-mode;
+		vina-supply = <&reg_vcc5v>;
+		vinb-supply = <&reg_vcc5v>;
+		vinc-supply = <&reg_vcc5v>;
+		vind-supply = <&reg_vcc5v>;
+		vine-supply = <&reg_vcc5v>;
+		aldoin-supply = <&reg_vcc5v>;
+		bldoin-supply = <&reg_vcc5v>;
+		cldoin-supply = <&reg_vcc5v>;
+
+		regulators {
+			reg_aldo1: aldo1 {
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-sys";
+			};
+
+			reg_aldo2: aldo2 {	/* 3.3V on headers */
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc3v3-ext";
+			};
+
+			reg_aldo3: aldo3 {	/* 3.3V on headers */
+				regulator-always-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc3v3-ext2";
+			};
+
+			reg_bldo1: bldo1 {
+				regulator-always-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc1v8";
+			};
+
+			bldo2 {
+				/* unused */
+			};
+
+			bldo3 {
+				/* unused */
+			};
+
+			bldo4 {
+				/* unused */
+			};
+
+			cldo1 {
+				/* reserved */
+			};
+
+			cldo2 {
+				/* unused */
+			};
+
+			cldo3 {
+				/* unused */
+			};
+
+			reg_dcdca: dcdca {
+				regulator-always-on;
+				regulator-min-microvolt = <810000>;
+				regulator-max-microvolt = <1080000>;
+				regulator-name = "vdd-cpu";
+			};
+
+			reg_dcdcc: dcdcc {
+				regulator-always-on;
+				regulator-min-microvolt = <810000>;
+				regulator-max-microvolt = <1080000>;
+				regulator-name = "vdd-gpu-sys";
+			};
+
+			reg_dcdcd: dcdcd {
+				regulator-always-on;
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-name = "vdd-dram";
+			};
+
+			reg_dcdce: dcdce {
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-eth-mmc";
+			};
+
+			sw {
+				/* unused */
+			};
+		};
+	};
+};
+
+&spi0  {
+	status = "okay";
+
+	flash at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <40000000>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_ph_pins>;
+	status = "okay";
+};
+
+&usbotg {
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usbphy {
+	usb1_vbus-supply = <&reg_usb1_vbus>;
+	status = "okay";
+};
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index d3755ae41a9d..90b9456ef80d 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -420,6 +420,11 @@ M:	Diego Rondini <diego.rondini@kynetics.com>
 S:	Maintained
 F:	configs/orangepi_zero_plus2_h3_defconfig
 
+ORANGEPI ZERO 2 BOARD
+M:	Jernej Skrabec <jernej.skrabec@siol.net>
+S:	Maintained
+F:	configs/orangepi_zero2_defconfig
+
 ORANGEPI PC 2 BOARD
 M:	Andre Przywara <andre.przywara@arm.com>
 S:	Maintained
diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig
new file mode 100644
index 000000000000..5af964bf100a
--- /dev/null
+++ b/configs/orangepi_zero2_defconfig
@@ -0,0 +1,15 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_SPL=y
+CONFIG_DRAM_SUN50I_H616_WRITE_LEVELING=y
+CONFIG_DRAM_SUN50I_H616_READ_CALIBRATION=y
+CONFIG_DRAM_SUN50I_H616_READ_TRAINING=y
+CONFIG_DRAM_SUN50I_H616_WRITE_TRAINING=y
+CONFIG_MACH_SUN50I_H616=y
+CONFIG_MMC0_CD_PIN="PF6"
+CONFIG_R_I2C_ENABLE=y
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-h616-orangepi-zero2"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_PHY_REALTEK=y
+CONFIG_SUN8I_EMAC=y
-- 
2.30.0

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

* [linux-sunxi] [PATCH 02/17] sunxi: Introduce common symbol for H6 like SoCs
  2021-01-03  9:26 ` [PATCH 02/17] sunxi: Introduce common symbol for H6 like SoCs Jernej Skrabec
@ 2021-01-03 23:43   ` Samuel Holland
  2021-01-04 10:35     ` André Przywara
  0 siblings, 1 reply; 48+ messages in thread
From: Samuel Holland @ 2021-01-03 23:43 UTC (permalink / raw)
  To: u-boot

On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> It turns out that there are at least 2 other SoCs which have basically
> the same memory map, similar clocks and other features as H6. It's very
> likely that we'll see more such SoCs in the future. In order to ease
> porting to new SoCs and lower ifdef clutter, introduce common symbol for
> them.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  arch/arm/include/asm/arch-sunxi/boot0.h |  2 +-
>  arch/arm/include/asm/arch-sunxi/clock.h |  2 +-
>  arch/arm/include/asm/arch-sunxi/cpu.h   |  2 +-
>  arch/arm/include/asm/arch-sunxi/timer.h |  2 +-
>  arch/arm/mach-sunxi/Kconfig             | 21 +++++++++++++--------
>  arch/arm/mach-sunxi/Makefile            |  2 +-
>  arch/arm/mach-sunxi/board.c             |  4 ++--
>  arch/arm/mach-sunxi/rmr_switch.S        |  2 +-
>  common/spl/Kconfig                      |  4 ++--
>  include/configs/sun50i.h                |  2 +-
>  10 files changed, 24 insertions(+), 19 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
> index 46d0f0666c2b..e8e8e38f0556 100644
> --- a/arch/arm/include/asm/arch-sunxi/boot0.h
> +++ b/arch/arm/include/asm/arch-sunxi/boot0.h
> @@ -39,7 +39,7 @@
>  	.word	0xf57ff06f	// isb     sy
>  	.word	0xe320f003	// wfi
>  	.word	0xeafffffd	// b       @wfi
> -#ifndef CONFIG_MACH_SUN50I_H6
> +#ifndef CONFIG_SUN50I_GEN_H6
>  	.word	0x017000a0	// writeable RVBAR mapping address
>  #else
>  	.word	0x09010040	// writeable RVBAR mapping address
> diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
> index 5994130e6b54..cbbe5c7a1e68 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock.h
> @@ -16,7 +16,7 @@
>  /* clock control module regs definition */
>  #if defined(CONFIG_MACH_SUN8I_A83T)
>  #include <asm/arch/clock_sun8i_a83t.h>
> -#elif defined(CONFIG_MACH_SUN50I_H6)
> +#elif defined(CONFIG_SUN50I_GEN_H6)
>  #include <asm/arch/clock_sun50i_h6.h>
>  #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
>        defined(CONFIG_MACH_SUN50I)
> diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
> index 8b57d24e2f0c..b08f2023748c 100644
> --- a/arch/arm/include/asm/arch-sunxi/cpu.h
> +++ b/arch/arm/include/asm/arch-sunxi/cpu.h
> @@ -8,7 +8,7 @@
>  
>  #if defined(CONFIG_MACH_SUN9I)
>  #include <asm/arch/cpu_sun9i.h>
> -#elif defined(CONFIG_MACH_SUN50I_H6)
> +#elif defined(CONFIG_SUN50I_GEN_H6)
>  #include <asm/arch/cpu_sun50i_h6.h>
>  #else
>  #include <asm/arch/cpu_sun4i.h>
> diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h
> index 6f138d04b806..bb5626d893bb 100644
> --- a/arch/arm/include/asm/arch-sunxi/timer.h
> +++ b/arch/arm/include/asm/arch-sunxi/timer.h
> @@ -76,7 +76,7 @@ struct sunxi_timer_reg {
>  	struct sunxi_tgp tgp[4];
>  	u8 res5[8];
>  	u32 cpu_cfg;
> -#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
> +#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
>  	u8 res3[16];
>  	struct sunxi_wdog wdog[5];	/* We have 5 watchdogs */
>  #endif
> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> index 49ef217f08c0..1cf79bad7cf6 100644
> --- a/arch/arm/mach-sunxi/Kconfig
> +++ b/arch/arm/mach-sunxi/Kconfig
> @@ -82,7 +82,7 @@ config SUN8I_RSB
>  config SUNXI_SRAM_ADDRESS
>  	hex
>  	default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
> -	default 0x20000 if MACH_SUN50I_H6
> +	default 0x20000 if SUN50I_GEN_H6
>  	default 0x0
>  	---help---
>  	Older Allwinner SoCs have their mask boot ROM mapped just below 4GB,
> @@ -108,6 +108,15 @@ config SUNXI_GEN_SUN6I
>  	separate ahb reset control registers, custom pmic bus, new style
>  	watchdog, etc.
>  
> +config SUN50I_GEN_H6

The new memory map is also used for 32-bit SoCs V5 (sun8iw12p1) and
newer. So this is not sun50i-specific, and I'd suggest SUNXI_GEN_H6 (or
even SUNXI_GEN_H6_V5). It is unfortunate there appears to be no name for
this family.

> +	bool
> +	select FIT
> +	select SPL_LOAD_FIT
> +	select SUPPORT_SPL
> +	---help---
> +	Select this for sunxi SoCs which have H6 like peripherals, clocks
> +	and memory map.
> +
>  config SUNXI_DRAM_DW
>  	bool
>  	---help---
> @@ -302,10 +311,7 @@ config MACH_SUN50I_H5
>  config MACH_SUN50I_H6
>  	bool "sun50i (Allwinner H6)"
>  	select ARM64
> -	select SUPPORT_SPL
> -	select FIT
>  	select PHY_SUN4I_USB
> -	select SPL_LOAD_FIT
>  	select DRAM_SUN50I_H6

I would expect this to select SUN50I_GEN_H6.

>  endchoice
> @@ -540,7 +546,6 @@ config SYS_CLK_FREQ
>  	default 816000000 if MACH_SUN50I || MACH_SUN50I_H5
>  	default 1008000000 if MACH_SUN8I
>  	default 1008000000 if MACH_SUN9I
> -	default 888000000 if MACH_SUN50I_H6

Was this removal intentional? You later add a different value for H616 only.

>  config SYS_CONFIG_NAME
>  	default "sun4i" if MACH_SUN4I
> @@ -756,7 +761,7 @@ config VIDEO_SUNXI
>  	depends on !MACH_SUN8I_V3S
>  	depends on !MACH_SUN9I
>  	depends on !MACH_SUN50I
> -	depends on !MACH_SUN50I_H6
> +	depends on !SUN50I_GEN_H6
>  	select VIDEO
>  	imply VIDEO_DT_SIMPLEFB
>  	default y
> @@ -989,11 +994,11 @@ config SPL_STACK_R_ADDR
>  	default 0x4fe00000 if MACH_SUN8I
>  	default 0x2fe00000 if MACH_SUN9I
>  	default 0x4fe00000 if MACH_SUN50I
> -	default 0x4fe00000 if MACH_SUN50I_H6
> +	default 0x4fe00000 if SUN50I_GEN_H6
>  
>  config SPL_SPI_SUNXI
>  	bool "Support for SPI Flash on Allwinner SoCs in SPL"
> -	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6
> +	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6
>  	help
>  	  Enable support for SPI Flash. This option allows SPL to read from
>  	  sunxi SPI Flash. It uses the same method as the boot ROM, so does
> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
> index d129f334798b..b8aca43d6630 100644
> --- a/arch/arm/mach-sunxi/Makefile
> +++ b/arch/arm/mach-sunxi/Makefile
> @@ -26,7 +26,7 @@ else
>  obj-$(CONFIG_MACH_SUN8I)	+= clock_sun6i.o
>  endif
>  obj-$(CONFIG_MACH_SUN9I)	+= clock_sun9i.o gtbus_sun9i.o
> -obj-$(CONFIG_MACH_SUN50I_H6)	+= clock_sun50i_h6.o
> +obj-$(CONFIG_SUN50I_GEN_H6)	+= clock_sun50i_h6.o
>  
>  ifdef CONFIG_SPL_BUILD
>  obj-$(CONFIG_DRAM_SUN4I)	+= dram_sun4i.o
> diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
> index f40fccd8f8b9..7a8b303f233c 100644
> --- a/arch/arm/mach-sunxi/board.c
> +++ b/arch/arm/mach-sunxi/board.c
> @@ -144,7 +144,7 @@ static int gpio_init(void)
>  #error Unsupported console port number. Please fix pin mux settings in board.c
>  #endif
>  
> -#ifdef CONFIG_MACH_SUN50I_H6
> +#ifdef CONFIG_SUN50I_GEN_H6
>  	/* Update PIO power bias configuration by copy hardware detected value */
>  	val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
>  	writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
> @@ -329,7 +329,7 @@ void reset_cpu(ulong addr)
>  		/* sun5i sometimes gets stuck without this */
>  		writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
>  	}
> -#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
> +#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
>  #if defined(CONFIG_MACH_SUN50I_H6)
>  	/* WDOG is broken for some H6 rev. use the R_WDOG instead */
>  	static const struct sunxi_wdog *wdog =
> diff --git a/arch/arm/mach-sunxi/rmr_switch.S b/arch/arm/mach-sunxi/rmr_switch.S
> index fafd306f95b1..33e55d496865 100644
> --- a/arch/arm/mach-sunxi/rmr_switch.S
> +++ b/arch/arm/mach-sunxi/rmr_switch.S
> @@ -30,7 +30,7 @@
>  
>  .text
>  
> -#ifndef CONFIG_MACH_SUN50I_H6
> +#ifndef CONFIG_SUN50I_GEN_H6
>  	ldr	r1, =0x017000a0		@ MMIO mapped RVBAR[0] register
>  #else
>  	ldr	r1, =0x09010040		@ MMIO mapped RVBAR[0] register
> diff --git a/common/spl/Kconfig b/common/spl/Kconfig
> index d8086bd9e874..bed715774d81 100644
> --- a/common/spl/Kconfig
> +++ b/common/spl/Kconfig
> @@ -150,7 +150,7 @@ config SPL_TEXT_BASE
>  	hex "SPL Text Base"
>  	default ISW_ENTRY_ADDR if AM43XX || AM33XX || OMAP54XX || ARCH_KEYSTONE
>  	default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I
> -	default 0x20060 if MACH_SUN50I_H6
> +	default 0x20060 if SUN50I_GEN_H6
>  	default 0x00060 if ARCH_SUNXI
>  	default 0xfffc0000 if ARCH_ZYNQMP
>  	default 0x0
> @@ -459,7 +459,7 @@ config SPL_SHA512_SUPPORT
>  config SPL_FIT_IMAGE_TINY
>  	bool "Remove functionality from SPL FIT loading to reduce size"
>  	depends on SPL_FIT
> -	default y if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6
> +	default y if MACH_SUN50I || MACH_SUN50I_H5 || SUN50I_GEN_H6

This can probably be simplified to ARCH_SUNXI.

>  	default y if ARCH_IMX8M
>  	help
>  	  Enable this to reduce the size of the FIT image loading code
> diff --git a/include/configs/sun50i.h b/include/configs/sun50i.h
> index e050a5299f3b..bc2e3a3d0088 100644
> --- a/include/configs/sun50i.h
> +++ b/include/configs/sun50i.h
> @@ -10,7 +10,7 @@
>   * A64 specific configuration
>   */
>  
> -#ifndef CONFIG_MACH_SUN50I_H6
> +#ifndef CONFIG_SUN50I_GEN_H6
>  #define GICD_BASE		0x1c81000
>  #define GICC_BASE		0x1c82000
>  #else
> 

Cheers,
Samuel

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

* [linux-sunxi] [PATCH 04/17] i2c: mvtwsi: sunxi: update macro
  2021-01-03  9:26 ` [PATCH 04/17] i2c: mvtwsi: sunxi: update macro Jernej Skrabec
@ 2021-01-03 23:55   ` Samuel Holland
  2021-01-04  5:57   ` Heiko Schocher
  1 sibling, 0 replies; 48+ messages in thread
From: Samuel Holland @ 2021-01-03 23:55 UTC (permalink / raw)
  To: u-boot

On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> While currently none of the newer Allwinner SoCs currently has I2C
> support implemented in U-Boot, this will change soon. mvtwsi driver is
> good as it is for them except one macro. Update it to be ready once I2C
> support lands for those SoCs.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>

Reviewed-by: Samuel Holland <samuel@sholland.org>

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

* [linux-sunxi] [PATCH 05/17] sunxi: prcm: Add memory map for H6 like SoCs
  2021-01-03  9:26 ` [PATCH 05/17] sunxi: prcm: Add memory map for H6 like SoCs Jernej Skrabec
@ 2021-01-04  0:03   ` Samuel Holland
  2021-01-11 16:13     ` Jernej Škrabec
  0 siblings, 1 reply; 48+ messages in thread
From: Samuel Holland @ 2021-01-04  0:03 UTC (permalink / raw)
  To: u-boot

On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> There was no need to have prcm definitions for H6 and similar SoCs till
> now. However, support R_I2C will be needed soon in SPL.
> 
> Move old definitions to prcm_sun6i.h and add new ones in prcm_sun50i.h.
> One of those files will be selected in common prcm.h based on defined
> macros.
> 
> This commit doesn't do any functional change.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  arch/arm/include/asm/arch-sunxi/prcm.h        | 249 +-----------------
>  arch/arm/include/asm/arch-sunxi/prcm_sun50i.h |  41 +++
>  arch/arm/include/asm/arch-sunxi/prcm_sun6i.h  | 247 +++++++++++++++++
>  3 files changed, 298 insertions(+), 239 deletions(-)
>  create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
>  create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun6i.h
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
> index 767d1ff98d74..5106076f5e91 100644
> --- a/arch/arm/include/asm/arch-sunxi/prcm.h
> +++ b/arch/arm/include/asm/arch-sunxi/prcm.h
> @@ -1,247 +1,18 @@
>  /* SPDX-License-Identifier: GPL-2.0+ */
>  /*
> - * Sunxi A31 Power Management Unit register definition.
> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
>   *
> - * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
> - * http://linux-sunxi.org
> - * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
> - * Berg Xing <bergxing@allwinnertech.com>
> - * Tom Cubie <tangliang@allwinnertech.com>
> + * Sunxi platform prcm register definition.
>   */
>  
>  #ifndef _SUNXI_PRCM_H
>  #define _SUNXI_PRCM_H
>  
> -#define __PRCM_CPUS_CFG_PRE(n) (((n) & 0x3) << 4)
> -#define PRCM_CPUS_CFG_PRE_MASK __PRCM_CPUS_CFG_PRE(0x3)
> -#define __PRCM_CPUS_CFG_PRE_DIV(n) (((n) >> 1) - 1)
> -#define PRCM_CPUS_CFG_PRE_DIV(n) \
> -	__PRCM_CPUS_CFG_PRE(__PRCM_CPUS_CFG_CLK_PRE(n))
> -#define __PRCM_CPUS_CFG_POST(n) (((n) & 0x1f) << 8)
> -#define PRCM_CPUS_CFG_POST_MASK __PRCM_CPUS_CFG_POST(0x1f)
> -#define __PRCM_CPUS_CFG_POST_DIV(n) ((n) - 1)
> -#define PRCM_CPUS_CFG_POST_DIV(n) \
> -	__PRCM_CPUS_CFG_POST_DIV(__PRCM_CPUS_CFG_POST_DIV(n))
> -#define __PRCM_CPUS_CFG_CLK_SRC(n) (((n) & 0x3) << 16)
> -#define PRCM_CPUS_CFG_CLK_SRC_MASK __PRCM_CPUS_CFG_CLK_SRC(0x3)
> -#define __PRCM_CPUS_CFG_CLK_SRC_LOSC 0x0
> -#define __PRCM_CPUS_CFG_CLK_SRC_HOSC 0x1
> -#define __PRCM_CPUS_CFG_CLK_SRC_PLL6 0x2
> -#define __PRCM_CPUS_CFG_CLK_SRC_PDIV 0x3
> -#define PRCM_CPUS_CFG_CLK_SRC_LOSC \
> -	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_LOSC)
> -#define PRCM_CPUS_CFG_CLK_SRC_HOSC \
> -	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_HOSC)
> -#define PRCM_CPUS_CFG_CLK_SRC_PLL6 \
> -	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PLL6)
> -#define PRCM_CPUS_CFG_CLK_SRC_PDIV \
> -	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PDIV)
> -
> -#define __PRCM_APB0_RATIO(n) (((n) & 0x3) << 0)
> -#define PRCM_APB0_RATIO_DIV_MASK __PRCM_APB0_RATIO_DIV(0x3)
> -#define __PRCM_APB0_RATIO_DIV(n) (((n) >> 1) - 1)
> -#define PRCM_APB0_RATIO_DIV(n) \
> -	__PRCM_APB0_RATIO(__PRCM_APB0_RATIO_DIV(n))
> -
> -#define PRCM_CPU_CFG_NEON_CLK_EN (0x1 << 0)
> -#define PRCM_CPU_CFG_CPU_CLK_EN (0x1 << 1)
> -
> -#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)		/* 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)
> -
> -#define PRCM_APB0_RESET_PIO (0x1 << 0)
> -#define PRCM_APB0_RESET_IR (0x1 << 1)
> -#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
> -#define PRCM_APB0_RESET_P2WI (0x1 << 3)
> -#define PRCM_APB0_RESET_UART (0x1 << 4)
> -#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
> -#define PRCM_APB0_RESET_I2C (0x1 << 6)
> -
> -#define PRCM_PLL_CTRL_PLL_BIAS (0x1 << 0)
> -#define PRCM_PLL_CTRL_HOSC_GAIN_ENH (0x1 << 1)
> -#define __PRCM_PLL_CTRL_USB_CLK_SRC(n) (((n) & 0x3) << 4)
> -#define PRCM_PLL_CTRL_USB_CLK_SRC_MASK \
> -	__PRCM_PLL_CTRL_USB_CLK_SRC(0x3)
> -#define __PRCM_PLL_CTRL_USB_CLK_0 0x0
> -#define __PRCM_PLL_CTRL_USB_CLK_1 0x1
> -#define __PRCM_PLL_CTRL_USB_CLK_2 0x2
> -#define __PRCM_PLL_CTRL_USB_CLK_3 0x3
> -#define PRCM_PLL_CTRL_USB_CLK_0 \
> -	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_0)
> -#define PRCM_PLL_CTRL_USB_CLK_1 \
> -	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_1)
> -#define PRCM_PLL_CTRL_USB_CLK_2 \
> -	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_2)
> -#define PRCM_PLL_CTRL_USB_CLK_3 \
> -	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_3)
> -#define __PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) (((n) & 0x3) << 12)
> -#define PRCM_PLL_CTRL_INT_PLL_IN_SEL_MASK \
> -	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(0x3)
> -#define PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) \
> -	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(n)
> -#define __PRCM_PLL_CTRL_HOSC_CLK_SEL(n) (((n) & 0x3) << 20)
> -#define PRCM_PLL_CTRL_HOSC_CLK_SEL_MASK \
> -	__PRCM_PLL_CTRL_HOSC_CLK_SEL(0x3)
> -#define __PRCM_PLL_CTRL_HOSC_CLK_0 0x0
> -#define __PRCM_PLL_CTRL_HOSC_CLK_1 0x1
> -#define __PRCM_PLL_CTRL_HOSC_CLK_2 0x2
> -#define __PRCM_PLL_CTRL_HOSC_CLK_3 0x3
> -#define PRCM_PLL_CTRL_HOSC_CLK_0 \
> -	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_0)
> -#define PRCM_PLL_CTRL_HOSC_CLK_1 \
> -	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_1)
> -#define PRCM_PLL_CTRL_HOSC_CLK_2 \
> -	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_2)
> -#define PRCM_PLL_CTRL_HOSC_CLK_3 \
> -	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_3)
> -#define PRCM_PLL_CTRL_PLL_TST_SRC_EXT (0x1 << 24)
> -#define PRCM_PLL_CTRL_LDO_DIGITAL_EN (0x1 << 0)
> -#define PRCM_PLL_CTRL_LDO_ANALOG_EN (0x1 << 1)
> -#define PRCM_PLL_CTRL_EXT_OSC_EN (0x1 << 2)
> -#define PRCM_PLL_CTRL_CLK_TST_EN (0x1 << 3)
> -#define PRCM_PLL_CTRL_IN_PWR_HIGH (0x1 << 15) /* 3.3 for hi 2.5 for lo */
> -#define __PRCM_PLL_CTRL_VDD_LDO_OUT(n) (((n) & 0x7) << 16)
> -#define PRCM_PLL_CTRL_LDO_OUT_MASK \
> -	__PRCM_PLL_CTRL_LDO_OUT(0x7)
> -/* When using the low voltage 20 mV steps, and high voltage 30 mV steps */
> -#define PRCM_PLL_CTRL_LDO_OUT_L(n) \
> -	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1000) / 20) & 0x7)
> -#define PRCM_PLL_CTRL_LDO_OUT_H(n) \
> -	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1160) / 30) & 0x7)
> -#define PRCM_PLL_CTRL_LDO_OUT_LV(n) \
> -	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 20) + 1000)
> -#define PRCM_PLL_CTRL_LDO_OUT_HV(n) \
> -	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 30) + 1160)
> -#define PRCM_PLL_CTRL_LDO_KEY (0xa7 << 24)
> -#define PRCM_PLL_CTRL_LDO_KEY_MASK (0xff << 24)
> -
> -#define PRCM_CLK_1WIRE_GATE (0x1 << 31)
> -
> -#define __PRCM_CLK_MOD0_M(n) (((n) & 0xf) << 0)
> -#define PRCM_CLK_MOD0_M_MASK __PRCM_CLK_MOD0_M(0xf)
> -#define __PRCM_CLK_MOD0_M_X(n) (n - 1)
> -#define PRCM_CLK_MOD0_M(n) __PRCM_CLK_MOD0_M(__PRCM_CLK_MOD0_M_X(n))
> -#define PRCM_CLK_MOD0_OUT_PHASE(n) (((n) & 0x7) << 8)
> -#define PRCM_CLK_MOD0_OUT_PHASE_MASK(n) PRCM_CLK_MOD0_OUT_PHASE(0x7)
> -#define _PRCM_CLK_MOD0_N(n) (((n) & 0x3) << 16)
> -#define PRCM_CLK_MOD0_N_MASK __PRCM_CLK_MOD_N(0x3)
> -#define __PRCM_CLK_MOD0_N_X(n) (((n) >> 1) - 1)
> -#define PRCM_CLK_MOD0_N(n) __PRCM_CLK_MOD0_N(__PRCM_CLK_MOD0_N_X(n))
> -#define PRCM_CLK_MOD0_SMPL_PHASE(n) (((n) & 0x7) << 20)
> -#define PRCM_CLK_MOD0_SMPL_PHASE_MASK PRCM_CLK_MOD0_SMPL_PHASE(0x7)
> -#define PRCM_CLK_MOD0_SRC_SEL(n) (((n) & 0x7) << 24)
> -#define PRCM_CLK_MOD0_SRC_SEL_MASK PRCM_CLK_MOD0_SRC_SEL(0x7)
> -#define PRCM_CLK_MOD0_GATE_EN (0x1 << 31)
> -
> -#define PRCM_APB0_RESET_PIO (0x1 << 0)
> -#define PRCM_APB0_RESET_IR (0x1 << 1)
> -#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
> -#define PRCM_APB0_RESET_P2WI (0x1 << 3)
> -#define PRCM_APB0_RESET_UART (0x1 << 4)
> -#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
> -#define PRCM_APB0_RESET_I2C (0x1 << 6)
> -
> -#define __PRCM_CLK_OUTD_M(n) (((n) & 0x7) << 8)
> -#define PRCM_CLK_OUTD_M_MASK __PRCM_CLK_OUTD_M(0x7)
> -#define __PRCM_CLK_OUTD_M_X() ((n) - 1)
> -#define PRCM_CLK_OUTD_M(n) __PRCM_CLK_OUTD_M(__PRCM_CLK_OUTD_M_X(n))
> -#define __PRCM_CLK_OUTD_N(n) (((n) & 0x7) << 20)
> -#define PRCM_CLK_OUTD_N_MASK __PRCM_CLK_OUTD_N(0x7)
> -#define __PRCM_CLK_OUTD_N_X(n) (((n) >> 1) - 1)
> -#define PRCM_CLK_OUTD_N(n) __PRCM_CLK_OUTD_N(__PRCM_CLK_OUTD_N_X(n)
> -#define __PRCM_CLK_OUTD_SRC_SEL(n) (((n) & 0x3) << 24)
> -#define PRCM_CLK_OUTD_SRC_SEL_MASK __PRCM_CLK_OUTD_SRC_SEL(0x3)
> -#define __PRCM_CLK_OUTD_SRC_LOSC2 0x0
> -#define __PRCM_CLK_OUTD_SRC_LOSC 0x1
> -#define __PRCM_CLK_OUTD_SRC_HOSC 0x2
> -#define __PRCM_CLK_OUTD_SRC_ERR 0x3
> -#define PRCM_CLK_OUTD_SRC_LOSC2 \
> -#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC2)
> -#define PRCM_CLK_OUTD_SRC_LOSC \
> -#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC)
> -#define PRCM_CLK_OUTD_SRC_HOSC \
> -#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_HOSC)
> -#define PRCM_CLK_OUTD_SRC_ERR \
> -#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_ERR)
> -#define PRCM_CLK_OUTD_EN (0x1 << 31)
> -
> -#define PRCM_CPU0_PWROFF (0x1 << 0)
> -#define PRCM_CPU1_PWROFF (0x1 << 1)
> -#define PRCM_CPU2_PWROFF (0x1 << 2)
> -#define PRCM_CPU3_PWROFF (0x1 << 3)
> -#define PRCM_CPU_ALL_PWROFF (0xf << 0)
> -
> -#define PRCM_VDD_SYS_DRAM_CH0_PAD_HOLD_PWROFF (0x1 << 0)
> -#define PRCM_VDD_SYS_DRAM_CH1_PAD_HOLD_PWROFF (0x1 << 1)
> -#define PRCM_VDD_SYS_AVCC_A_PWROFF (0x1 << 2)
> -#define PRCM_VDD_SYS_CPU0_VDD_PWROFF (0x1 << 3)
> -
> -#define PRCM_VDD_GPU_PWROFF (0x1 << 0)
> -
> -#define PRCM_VDD_SYS_RESET (0x1 << 0)
> -
> -#define PRCM_CPU1_PWR_CLAMP(n) (((n) & 0xff) << 0)
> -#define PRCM_CPU1_PWR_CLAMP_MASK PRCM_CPU1_PWR_CLAMP(0xff)
> -
> -#define PRCM_CPU2_PWR_CLAMP(n) (((n) & 0xff) << 0)
> -#define PRCM_CPU2_PWR_CLAMP_MASK PRCM_CPU2_PWR_CLAMP(0xff)
> -
> -#define PRCM_CPU3_PWR_CLAMP(n) (((n) & 0xff) << 0)
> -#define PRCM_CPU3_PWR_CLAMP_MASK PRCM_CPU3_PWR_CLAMP(0xff)
> -
> -#define PRCM_SEC_SWITCH_APB0_CLK_NONSEC (0x1 << 0)
> -#define PRCM_SEC_SWITCH_PLL_CFG_NONSEC (0x1 << 1)
> -#define PRCM_SEC_SWITCH_PWR_GATE_NONSEC (0x1 << 2)
> -
> -#ifndef __ASSEMBLY__
> -#include <linux/compiler.h>
> -
> -struct sunxi_prcm_reg {
> -	u32 cpus_cfg;		/* 0x000 */
> -	u8 res0[0x8];		/* 0x004 */
> -	u32 apb0_ratio;		/* 0x00c */
> -	u32 cpu0_cfg;		/* 0x010 */
> -	u32 cpu1_cfg;		/* 0x014 */
> -	u32 cpu2_cfg;		/* 0x018 */
> -	u32 cpu3_cfg;		/* 0x01c */
> -	u8 res1[0x8];		/* 0x020 */
> -	u32 apb0_gate;		/* 0x028 */
> -	u8 res2[0x14];		/* 0x02c */
> -	u32 pll_ctrl0;		/* 0x040 */
> -	u32 pll_ctrl1;		/* 0x044 */
> -	u8 res3[0x8];		/* 0x048 */
> -	u32 clk_1wire;		/* 0x050 */
> -	u32 clk_ir;		/* 0x054 */
> -	u8 res4[0x58];		/* 0x058 */
> -	u32 apb0_reset;		/* 0x0b0 */
> -	u8 res5[0x3c];		/* 0x0b4 */
> -	u32 clk_outd;		/* 0x0f0 */
> -	u8 res6[0xc];		/* 0x0f4 */
> -	u32 cpu_pwroff;		/* 0x100 */
> -	u8 res7[0xc];		/* 0x104 */
> -	u32 vdd_sys_pwroff;	/* 0x110 */
> -	u8 res8[0x4];		/* 0x114 */
> -	u32 gpu_pwroff;		/* 0x118 */
> -	u8 res9[0x4];		/* 0x11c */
> -	u32 vdd_pwr_reset;	/* 0x120 */
> -	u8 res10[0x1c];		/* 0x124 */
> -	u32 cpu_pwr_clamp[4];	/* 0x140 but first one is actually unused */
> -	u8 res11[0x30];		/* 0x150 */
> -	u32 dram_pwr;		/* 0x180 */
> -	u8 res12[0xc];		/* 0x184 */
> -	u32 dram_tst;		/* 0x190 */
> -	u8 res13[0x3c];		/* 0x194 */
> -	u32 prcm_sec_switch;	/* 0x1d0 */
> -};
> -
> -void prcm_apb0_enable(u32 flags);
> -void prcm_apb0_disable(u32 flags);
> -
> -#endif /* __ASSEMBLY__ */
> -#endif /* _PRCM_H */
> +/* prcm regs definition */
> +#if defined(CONFIG_SUN50I_GEN_H6)
> +#include <asm/arch/prcm_sun50i.h>
> +#else
> +#include <asm/arch/prcm_sun6i.h>
> +#endif
> +
> +#endif /* _SUNXI_PRCM_H */
> diff --git a/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h b/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
> new file mode 100644
> index 000000000000..68a78e50ce64
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
> @@ -0,0 +1,41 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Sunxi H6 Power Management Unit register definition.
> + *
> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
> + */
> +
> +#ifndef _SUN50I_PRCM_H
> +#define _SUN50I_PRCM_H
> +
> +#ifndef __ASSEMBLY__
> +#include <linux/compiler.h>
> +
> +struct sunxi_prcm_reg {
> +	u32 cpus_cfg;		/* 0x000 */
> +	u8 res0[0x8];		/* 0x004 */
> +	u32 apbs1_cfg;		/* 0x00c */
> +	u32 apbs2_cfg;		/* 0x010 */
> +	u8 res1[0x118];		/* 0x014 */
> +	u32 wdg_gate_reset;	/* 0x12c */

This is the register for R_TWD, not R_WDOG.

And out of curiosity, were you intending to include all PRCM registers,
or just those present on both H6 and H616? (H6 also has TIMER, PWM and
UART.)

> +	u8 res2[0x6c];		/* 0x130 */
> +	u32 twi_gate_reset;	/* 0x19c */
> +	u8 res3[0x1c];		/* 0x1a0 */
> +	u32 rsb_gate_reset;	/* 0x1bc */
> +	u32 cir_cfg;		/* 0x1c0 */
> +	u8 res4[0x8];		/* 0x1c4 */
> +	u32 cir_gate_reset;	/* 0x1cc */
> +	u8 res5[0x10];		/* 0x1d0 */
> +	u32 w1_cfg;		/* 0x1e0 */
> +	u8 res6[0x8];		/* 0x1e4 */
> +	u32 w1_gate_reset;	/* 0x1ec */
> +	u8 res7[0x1c];		/* 0x1f0 */
> +	u32 rtc_gate_reset;	/* 0x20c */
> +};
> +check_member(sunxi_prcm_reg, rtc_gate_reset, 0x20c);
> +
> +#define PRCM_TWI_GATE		(1 << 0)
> +#define PRCM_TWI_RESET		(1 << 16)
> +
> +#endif /* __ASSEMBLY__ */
> +#endif /* _PRCM_H */
> diff --git a/arch/arm/include/asm/arch-sunxi/prcm_sun6i.h b/arch/arm/include/asm/arch-sunxi/prcm_sun6i.h
> new file mode 100644
> index 000000000000..ab664e80bbe8
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-sunxi/prcm_sun6i.h
> @@ -0,0 +1,247 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Sunxi A31 Power Management Unit register definition.
> + *
> + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
> + * http://linux-sunxi.org
> + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
> + * Berg Xing <bergxing@allwinnertech.com>
> + * Tom Cubie <tangliang@allwinnertech.com>
> + */
> +
> +#ifndef _SUN6I_PRCM_H
> +#define _SUN6I_PRCM_H
> +
> +#define __PRCM_CPUS_CFG_PRE(n) (((n) & 0x3) << 4)
> +#define PRCM_CPUS_CFG_PRE_MASK __PRCM_CPUS_CFG_PRE(0x3)
> +#define __PRCM_CPUS_CFG_PRE_DIV(n) (((n) >> 1) - 1)
> +#define PRCM_CPUS_CFG_PRE_DIV(n) \
> +	__PRCM_CPUS_CFG_PRE(__PRCM_CPUS_CFG_CLK_PRE(n))
> +#define __PRCM_CPUS_CFG_POST(n) (((n) & 0x1f) << 8)
> +#define PRCM_CPUS_CFG_POST_MASK __PRCM_CPUS_CFG_POST(0x1f)
> +#define __PRCM_CPUS_CFG_POST_DIV(n) ((n) - 1)
> +#define PRCM_CPUS_CFG_POST_DIV(n) \
> +	__PRCM_CPUS_CFG_POST_DIV(__PRCM_CPUS_CFG_POST_DIV(n))
> +#define __PRCM_CPUS_CFG_CLK_SRC(n) (((n) & 0x3) << 16)
> +#define PRCM_CPUS_CFG_CLK_SRC_MASK __PRCM_CPUS_CFG_CLK_SRC(0x3)
> +#define __PRCM_CPUS_CFG_CLK_SRC_LOSC 0x0
> +#define __PRCM_CPUS_CFG_CLK_SRC_HOSC 0x1
> +#define __PRCM_CPUS_CFG_CLK_SRC_PLL6 0x2
> +#define __PRCM_CPUS_CFG_CLK_SRC_PDIV 0x3
> +#define PRCM_CPUS_CFG_CLK_SRC_LOSC \
> +	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_LOSC)
> +#define PRCM_CPUS_CFG_CLK_SRC_HOSC \
> +	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_HOSC)
> +#define PRCM_CPUS_CFG_CLK_SRC_PLL6 \
> +	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PLL6)
> +#define PRCM_CPUS_CFG_CLK_SRC_PDIV \
> +	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PDIV)
> +
> +#define __PRCM_APB0_RATIO(n) (((n) & 0x3) << 0)
> +#define PRCM_APB0_RATIO_DIV_MASK __PRCM_APB0_RATIO_DIV(0x3)
> +#define __PRCM_APB0_RATIO_DIV(n) (((n) >> 1) - 1)
> +#define PRCM_APB0_RATIO_DIV(n) \
> +	__PRCM_APB0_RATIO(__PRCM_APB0_RATIO_DIV(n))
> +
> +#define PRCM_CPU_CFG_NEON_CLK_EN (0x1 << 0)
> +#define PRCM_CPU_CFG_CPU_CLK_EN (0x1 << 1)
> +
> +#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)		/* 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)
> +
> +#define PRCM_APB0_RESET_PIO (0x1 << 0)
> +#define PRCM_APB0_RESET_IR (0x1 << 1)
> +#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
> +#define PRCM_APB0_RESET_P2WI (0x1 << 3)
> +#define PRCM_APB0_RESET_UART (0x1 << 4)
> +#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
> +#define PRCM_APB0_RESET_I2C (0x1 << 6)
> +
> +#define PRCM_PLL_CTRL_PLL_BIAS (0x1 << 0)
> +#define PRCM_PLL_CTRL_HOSC_GAIN_ENH (0x1 << 1)
> +#define __PRCM_PLL_CTRL_USB_CLK_SRC(n) (((n) & 0x3) << 4)
> +#define PRCM_PLL_CTRL_USB_CLK_SRC_MASK \
> +	__PRCM_PLL_CTRL_USB_CLK_SRC(0x3)
> +#define __PRCM_PLL_CTRL_USB_CLK_0 0x0
> +#define __PRCM_PLL_CTRL_USB_CLK_1 0x1
> +#define __PRCM_PLL_CTRL_USB_CLK_2 0x2
> +#define __PRCM_PLL_CTRL_USB_CLK_3 0x3
> +#define PRCM_PLL_CTRL_USB_CLK_0 \
> +	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_0)
> +#define PRCM_PLL_CTRL_USB_CLK_1 \
> +	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_1)
> +#define PRCM_PLL_CTRL_USB_CLK_2 \
> +	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_2)
> +#define PRCM_PLL_CTRL_USB_CLK_3 \
> +	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_3)
> +#define __PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) (((n) & 0x3) << 12)
> +#define PRCM_PLL_CTRL_INT_PLL_IN_SEL_MASK \
> +	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(0x3)
> +#define PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) \
> +	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(n)
> +#define __PRCM_PLL_CTRL_HOSC_CLK_SEL(n) (((n) & 0x3) << 20)
> +#define PRCM_PLL_CTRL_HOSC_CLK_SEL_MASK \
> +	__PRCM_PLL_CTRL_HOSC_CLK_SEL(0x3)
> +#define __PRCM_PLL_CTRL_HOSC_CLK_0 0x0
> +#define __PRCM_PLL_CTRL_HOSC_CLK_1 0x1
> +#define __PRCM_PLL_CTRL_HOSC_CLK_2 0x2
> +#define __PRCM_PLL_CTRL_HOSC_CLK_3 0x3
> +#define PRCM_PLL_CTRL_HOSC_CLK_0 \
> +	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_0)
> +#define PRCM_PLL_CTRL_HOSC_CLK_1 \
> +	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_1)
> +#define PRCM_PLL_CTRL_HOSC_CLK_2 \
> +	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_2)
> +#define PRCM_PLL_CTRL_HOSC_CLK_3 \
> +	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_3)
> +#define PRCM_PLL_CTRL_PLL_TST_SRC_EXT (0x1 << 24)
> +#define PRCM_PLL_CTRL_LDO_DIGITAL_EN (0x1 << 0)
> +#define PRCM_PLL_CTRL_LDO_ANALOG_EN (0x1 << 1)
> +#define PRCM_PLL_CTRL_EXT_OSC_EN (0x1 << 2)
> +#define PRCM_PLL_CTRL_CLK_TST_EN (0x1 << 3)
> +#define PRCM_PLL_CTRL_IN_PWR_HIGH (0x1 << 15) /* 3.3 for hi 2.5 for lo */
> +#define __PRCM_PLL_CTRL_VDD_LDO_OUT(n) (((n) & 0x7) << 16)
> +#define PRCM_PLL_CTRL_LDO_OUT_MASK \
> +	__PRCM_PLL_CTRL_LDO_OUT(0x7)
> +/* When using the low voltage 20 mV steps, and high voltage 30 mV steps */
> +#define PRCM_PLL_CTRL_LDO_OUT_L(n) \
> +	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1000) / 20) & 0x7)
> +#define PRCM_PLL_CTRL_LDO_OUT_H(n) \
> +	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1160) / 30) & 0x7)
> +#define PRCM_PLL_CTRL_LDO_OUT_LV(n) \
> +	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 20) + 1000)
> +#define PRCM_PLL_CTRL_LDO_OUT_HV(n) \
> +	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 30) + 1160)
> +#define PRCM_PLL_CTRL_LDO_KEY (0xa7 << 24)
> +#define PRCM_PLL_CTRL_LDO_KEY_MASK (0xff << 24)
> +
> +#define PRCM_CLK_1WIRE_GATE (0x1 << 31)
> +
> +#define __PRCM_CLK_MOD0_M(n) (((n) & 0xf) << 0)
> +#define PRCM_CLK_MOD0_M_MASK __PRCM_CLK_MOD0_M(0xf)
> +#define __PRCM_CLK_MOD0_M_X(n) (n - 1)
> +#define PRCM_CLK_MOD0_M(n) __PRCM_CLK_MOD0_M(__PRCM_CLK_MOD0_M_X(n))
> +#define PRCM_CLK_MOD0_OUT_PHASE(n) (((n) & 0x7) << 8)
> +#define PRCM_CLK_MOD0_OUT_PHASE_MASK(n) PRCM_CLK_MOD0_OUT_PHASE(0x7)
> +#define _PRCM_CLK_MOD0_N(n) (((n) & 0x3) << 16)
> +#define PRCM_CLK_MOD0_N_MASK __PRCM_CLK_MOD_N(0x3)
> +#define __PRCM_CLK_MOD0_N_X(n) (((n) >> 1) - 1)
> +#define PRCM_CLK_MOD0_N(n) __PRCM_CLK_MOD0_N(__PRCM_CLK_MOD0_N_X(n))
> +#define PRCM_CLK_MOD0_SMPL_PHASE(n) (((n) & 0x7) << 20)
> +#define PRCM_CLK_MOD0_SMPL_PHASE_MASK PRCM_CLK_MOD0_SMPL_PHASE(0x7)
> +#define PRCM_CLK_MOD0_SRC_SEL(n) (((n) & 0x7) << 24)
> +#define PRCM_CLK_MOD0_SRC_SEL_MASK PRCM_CLK_MOD0_SRC_SEL(0x7)
> +#define PRCM_CLK_MOD0_GATE_EN (0x1 << 31)
> +
> +#define PRCM_APB0_RESET_PIO (0x1 << 0)
> +#define PRCM_APB0_RESET_IR (0x1 << 1)
> +#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
> +#define PRCM_APB0_RESET_P2WI (0x1 << 3)
> +#define PRCM_APB0_RESET_UART (0x1 << 4)
> +#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
> +#define PRCM_APB0_RESET_I2C (0x1 << 6)
> +
> +#define __PRCM_CLK_OUTD_M(n) (((n) & 0x7) << 8)
> +#define PRCM_CLK_OUTD_M_MASK __PRCM_CLK_OUTD_M(0x7)
> +#define __PRCM_CLK_OUTD_M_X() ((n) - 1)
> +#define PRCM_CLK_OUTD_M(n) __PRCM_CLK_OUTD_M(__PRCM_CLK_OUTD_M_X(n))
> +#define __PRCM_CLK_OUTD_N(n) (((n) & 0x7) << 20)
> +#define PRCM_CLK_OUTD_N_MASK __PRCM_CLK_OUTD_N(0x7)
> +#define __PRCM_CLK_OUTD_N_X(n) (((n) >> 1) - 1)
> +#define PRCM_CLK_OUTD_N(n) __PRCM_CLK_OUTD_N(__PRCM_CLK_OUTD_N_X(n)
> +#define __PRCM_CLK_OUTD_SRC_SEL(n) (((n) & 0x3) << 24)
> +#define PRCM_CLK_OUTD_SRC_SEL_MASK __PRCM_CLK_OUTD_SRC_SEL(0x3)
> +#define __PRCM_CLK_OUTD_SRC_LOSC2 0x0
> +#define __PRCM_CLK_OUTD_SRC_LOSC 0x1
> +#define __PRCM_CLK_OUTD_SRC_HOSC 0x2
> +#define __PRCM_CLK_OUTD_SRC_ERR 0x3
> +#define PRCM_CLK_OUTD_SRC_LOSC2 \
> +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC2)
> +#define PRCM_CLK_OUTD_SRC_LOSC \
> +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC)
> +#define PRCM_CLK_OUTD_SRC_HOSC \
> +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_HOSC)
> +#define PRCM_CLK_OUTD_SRC_ERR \
> +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_ERR)
> +#define PRCM_CLK_OUTD_EN (0x1 << 31)
> +
> +#define PRCM_CPU0_PWROFF (0x1 << 0)
> +#define PRCM_CPU1_PWROFF (0x1 << 1)
> +#define PRCM_CPU2_PWROFF (0x1 << 2)
> +#define PRCM_CPU3_PWROFF (0x1 << 3)
> +#define PRCM_CPU_ALL_PWROFF (0xf << 0)
> +
> +#define PRCM_VDD_SYS_DRAM_CH0_PAD_HOLD_PWROFF (0x1 << 0)
> +#define PRCM_VDD_SYS_DRAM_CH1_PAD_HOLD_PWROFF (0x1 << 1)
> +#define PRCM_VDD_SYS_AVCC_A_PWROFF (0x1 << 2)
> +#define PRCM_VDD_SYS_CPU0_VDD_PWROFF (0x1 << 3)
> +
> +#define PRCM_VDD_GPU_PWROFF (0x1 << 0)
> +
> +#define PRCM_VDD_SYS_RESET (0x1 << 0)
> +
> +#define PRCM_CPU1_PWR_CLAMP(n) (((n) & 0xff) << 0)
> +#define PRCM_CPU1_PWR_CLAMP_MASK PRCM_CPU1_PWR_CLAMP(0xff)
> +
> +#define PRCM_CPU2_PWR_CLAMP(n) (((n) & 0xff) << 0)
> +#define PRCM_CPU2_PWR_CLAMP_MASK PRCM_CPU2_PWR_CLAMP(0xff)
> +
> +#define PRCM_CPU3_PWR_CLAMP(n) (((n) & 0xff) << 0)
> +#define PRCM_CPU3_PWR_CLAMP_MASK PRCM_CPU3_PWR_CLAMP(0xff)
> +
> +#define PRCM_SEC_SWITCH_APB0_CLK_NONSEC (0x1 << 0)
> +#define PRCM_SEC_SWITCH_PLL_CFG_NONSEC (0x1 << 1)
> +#define PRCM_SEC_SWITCH_PWR_GATE_NONSEC (0x1 << 2)
> +
> +#ifndef __ASSEMBLY__
> +#include <linux/compiler.h>
> +
> +struct sunxi_prcm_reg {
> +	u32 cpus_cfg;		/* 0x000 */
> +	u8 res0[0x8];		/* 0x004 */
> +	u32 apb0_ratio;		/* 0x00c */
> +	u32 cpu0_cfg;		/* 0x010 */
> +	u32 cpu1_cfg;		/* 0x014 */
> +	u32 cpu2_cfg;		/* 0x018 */
> +	u32 cpu3_cfg;		/* 0x01c */
> +	u8 res1[0x8];		/* 0x020 */
> +	u32 apb0_gate;		/* 0x028 */
> +	u8 res2[0x14];		/* 0x02c */
> +	u32 pll_ctrl0;		/* 0x040 */
> +	u32 pll_ctrl1;		/* 0x044 */
> +	u8 res3[0x8];		/* 0x048 */
> +	u32 clk_1wire;		/* 0x050 */
> +	u32 clk_ir;		/* 0x054 */
> +	u8 res4[0x58];		/* 0x058 */
> +	u32 apb0_reset;		/* 0x0b0 */
> +	u8 res5[0x3c];		/* 0x0b4 */
> +	u32 clk_outd;		/* 0x0f0 */
> +	u8 res6[0xc];		/* 0x0f4 */
> +	u32 cpu_pwroff;		/* 0x100 */
> +	u8 res7[0xc];		/* 0x104 */
> +	u32 vdd_sys_pwroff;	/* 0x110 */
> +	u8 res8[0x4];		/* 0x114 */
> +	u32 gpu_pwroff;		/* 0x118 */
> +	u8 res9[0x4];		/* 0x11c */
> +	u32 vdd_pwr_reset;	/* 0x120 */
> +	u8 res10[0x1c];		/* 0x124 */
> +	u32 cpu_pwr_clamp[4];	/* 0x140 but first one is actually unused */
> +	u8 res11[0x30];		/* 0x150 */
> +	u32 dram_pwr;		/* 0x180 */
> +	u8 res12[0xc];		/* 0x184 */
> +	u32 dram_tst;		/* 0x190 */
> +	u8 res13[0x3c];		/* 0x194 */
> +	u32 prcm_sec_switch;	/* 0x1d0 */
> +};
> +
> +void prcm_apb0_enable(u32 flags);
> +void prcm_apb0_disable(u32 flags);
> +
> +#endif /* __ASSEMBLY__ */
> +#endif /* _PRCM_H */
> 

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

* [linux-sunxi] [PATCH 06/17] sunxi: Add support for I2C on H6 like SoCs
  2021-01-03  9:26 ` [PATCH 06/17] sunxi: Add support for I2C on " Jernej Skrabec
@ 2021-01-04  0:04   ` Samuel Holland
  0 siblings, 0 replies; 48+ messages in thread
From: Samuel Holland @ 2021-01-04  0:04 UTC (permalink / raw)
  To: u-boot

On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> I2C support, especially R_I2C port, will be needed in future. Upcoming
> support for H616 will need R_I2C to adjust DRAM voltage.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>

Reviewed-by: Samuel Holland <samuel@sholland.org>

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

* [linux-sunxi] [PATCH 07/17] sunxi: support loading with SPL > 32KB
  2021-01-03  9:26 ` [PATCH 07/17] sunxi: support loading with SPL > 32KB Jernej Skrabec
@ 2021-01-04  2:02   ` Samuel Holland
  2021-01-11 18:17     ` Jernej Škrabec
  0 siblings, 1 reply; 48+ messages in thread
From: Samuel Holland @ 2021-01-04  2:02 UTC (permalink / raw)
  To: u-boot

On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> From: Andre Przywara <andre.przywara@arm.com>
> 
> H616 supports and needs bigger SPL than 32 KiB, mostly due to big DRAM
> driver and need for PMIC configuration, which pull several drivers which
> are not needed otherwise.
> 
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  arch/arm/mach-sunxi/board.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
> index 7a8b303f233c..296efd615769 100644
> --- a/arch/arm/mach-sunxi/board.c
> +++ b/arch/arm/mach-sunxi/board.c
> @@ -277,6 +277,14 @@ uint32_t sunxi_get_boot_device(void)
>  }
>  
>  #ifdef CONFIG_SPL_BUILD
> +static u32 sunxi_get_spl_size(void)
> +{
> +	if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */
> +		return 32768;
In the context of the suggestion below, this case could return 0.

> +
> +	return readl(SPL_ADDR + 0x10);
> +}
> +
>  /*
>   * The eGON SPL image can be located at 8KB or at 128KB into an SD card or
>   * an eMMC device. The boot source has bit 4 set in the latter case.
> @@ -286,6 +294,7 @@ uint32_t sunxi_get_boot_device(void)
>  unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc)

As a side note, the prototype for this function was changed in commit
cf0082559698 ("spl: mmc: Fix spl_mmc_get_uboot_raw_sector()
implementation"), but nobody noticed since it is not in a header.

>  {
>  	unsigned long sector = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR;
> +	u32 spl_size = sunxi_get_spl_size();
>  
>  	switch (sunxi_get_boot_source()) {
>  	case SUNXI_BOOTED_FROM_MMC0_HIGH:
> @@ -294,6 +303,9 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc)
>  		break;
>  	}
>  
> +	if (spl_size > 32768)
> +		sector += (spl_size - 32768) / 512;
> +

What I would suggest doing instead of this is setting
SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x40,
SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET=0x10, and then before the
switch statement doing:

        sector = max(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR,
                     spl_size / 512);

Not only does this get rid of the magic 32768 constant (which is
meaningless on new platforms), but it also works cleanly for eMMC boot
partitions (where there's no 0x10 sector offset).

>  	return sector;
>  }
>  
> 

Cheers,
Samuel

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

* [linux-sunxi] [PATCH 08/17] sunxi: introduce support for H616 clocks
  2021-01-03  9:26 ` [PATCH 08/17] sunxi: introduce support for H616 clocks Jernej Skrabec
@ 2021-01-04  2:28   ` Samuel Holland
  0 siblings, 0 replies; 48+ messages in thread
From: Samuel Holland @ 2021-01-04  2:28 UTC (permalink / raw)
  To: u-boot

On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> H616 has mostly the same clocks as H6 with some small differences. Just
> reuse H6 clocks for H616 and handle differences with macros.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  .../include/asm/arch-sunxi/clock_sun50i_h6.h   | 18 +++++++++++++++++-
>  arch/arm/mach-sunxi/clock_sun50i_h6.c          | 10 +++++++++-
>  2 files changed, 26 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
> index e83e84ab6cab..62abfc4ef6bd 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
> @@ -230,6 +230,7 @@ struct sunxi_ccm_reg {
>  #define CCM_PLL1_CTRL_EN		BIT(31)
>  #define CCM_PLL1_LOCK_EN		BIT(29)
>  #define CCM_PLL1_LOCK			BIT(28)
> +#define CCM_PLL1_OUT_EN			BIT(27)
>  #define CCM_PLL1_CLOCK_TIME_2		(2 << 24)
>  #define CCM_PLL1_CTRL_P(p)		((p) << 16)
>  #define CCM_PLL1_CTRL_N(n)		((n) << 8)
> @@ -238,6 +239,7 @@ struct sunxi_ccm_reg {
>  #define CCM_PLL5_CTRL_EN		BIT(31)
>  #define CCM_PLL5_LOCK_EN		BIT(29)
>  #define CCM_PLL5_LOCK			BIT(28)
> +#define CCM_PLL5_OUT_EN			BIT(27)
>  #define CCM_PLL5_CTRL_N(n)		((n) << 8)
>  #define CCM_PLL5_CTRL_DIV1(div1)	((div1) << 0)
>  #define CCM_PLL5_CTRL_DIV2(div0)	((div0) << 1)
> @@ -252,7 +254,6 @@ struct sunxi_ccm_reg {
>  #define CCM_PLL6_CTRL_DIV1_MASK		(0x1 << CCM_PLL6_CTRL_DIV1_SHIFT)
>  #define CCM_PLL6_CTRL_DIV2_SHIFT	1
>  #define CCM_PLL6_CTRL_DIV2_MASK		(0x1 << CCM_PLL6_CTRL_DIV2_SHIFT)
> -#define CCM_PLL6_DEFAULT		0xa0006300
>  
>  /* cpu_axi bit field*/
>  #define CCM_CPU_AXI_MUX_MASK		(0x3 << 24)
> @@ -262,6 +263,9 @@ struct sunxi_ccm_reg {
>  #define CCM_CPU_AXI_AXI_MASK		0x3
>  #define CCM_CPU_AXI_DEFAULT_FACTORS	0x301
>  
> +#ifdef CONFIG_MACH_SUN50I_H6
> +#define CCM_PLL6_DEFAULT		0xa0006300
> +
>  /* psi_ahb1_ahb2 bit field */
>  #define CCM_PSI_AHB1_AHB2_DEFAULT	0x03000102
>  
> @@ -270,6 +274,18 @@ struct sunxi_ccm_reg {
>  
>  /* apb1 bit field */
>  #define CCM_APB1_DEFAULT		0x03000102
> +#elif CONFIG_MACH_SUN50I_H616
> +#define CCM_PLL6_DEFAULT		0xa8003100
> +
> +/* psi_ahb1_ahb2 bit field */
> +#define CCM_PSI_AHB1_AHB2_DEFAULT	0x03000002
> +
> +/* ahb3 bit field */
> +#define CCM_AHB3_DEFAULT		0x03000002
> +
> +/* apb1 bit field */
> +#define CCM_APB1_DEFAULT		0x03000102
> +#endif
>  
>  /* apb2 bit field */
>  #define APB2_CLK_SRC_OSC24M		(0x0 << 24)
> diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
> index 6bd466915c11..a4cc1b53728b 100644
> --- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
> +++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
> @@ -68,6 +68,9 @@ void clock_set_pll1(unsigned int clk)
>  
>  	/* clk = 24*n/p, p is ignored if clock is >288MHz */
>  	writel(CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2 |
> +#ifdef CONFIG_MACH_SUN50I_H616
> +	       CCM_PLL1_OUT_EN |
> +#endif
>  	       CCM_PLL1_CTRL_N(clk / 24000000), &ccm->pll1_cfg);
>  	while (!(readl(&ccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
>  
> @@ -83,6 +86,11 @@ unsigned int clock_get_pll6(void)
>  {
>  	struct sunxi_ccm_reg *const ccm =
>  		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> +#ifdef CONFIG_MACH_SUN50I_H6
> +	int m = 4;
> +#else
> +	int m = 2;
> +#endif

This looks like a good place for an IS_ENABLED ternary.

>  	uint32_t rval = readl(&ccm->pll6_cfg);
>  	int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT);
> @@ -91,7 +99,7 @@ unsigned int clock_get_pll6(void)
>  	int div2 = ((rval & CCM_PLL6_CTRL_DIV2_MASK) >>
>  			CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
>  	/* The register defines PLL6-4X, not plain PLL6 */

Now it is PLL6-2X or PLL6-4X.

With those adjustments:

Reviewed-by: Samuel Holland <samuel@sholland.org>

> -	return 24000000 / 4 * n / div1 / div2;
> +	return 24000000 / m * n / div1 / div2;
>  }
>  
>  int clock_twi_onoff(int port, int state)
> 

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

* [linux-sunxi] [PATCH 09/17] sunxi: add support for H616 uart0
  2021-01-03  9:26 ` [PATCH 09/17] sunxi: add support for H616 uart0 Jernej Skrabec
@ 2021-01-04  2:30   ` Samuel Holland
  0 siblings, 0 replies; 48+ messages in thread
From: Samuel Holland @ 2021-01-04  2:30 UTC (permalink / raw)
  To: u-boot

On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> This port is used for debug terminal on all known H616 boards.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>

Reviewed-by: Samuel Holland <samuel@sholland.org>

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

* [linux-sunxi] [PATCH 10/17] sunxi: add support for R_I2C on H616
  2021-01-03  9:26 ` [PATCH 10/17] sunxi: add support for R_I2C on H616 Jernej Skrabec
@ 2021-01-04  2:33   ` Samuel Holland
  2021-01-04 18:36     ` Jernej Škrabec
  0 siblings, 1 reply; 48+ messages in thread
From: Samuel Holland @ 2021-01-04  2:33 UTC (permalink / raw)
  To: u-boot

On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> This port is needed for communication with PMIC. SPL uses it to set DRAM
> voltage on H616 boards.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  arch/arm/include/asm/arch-sunxi/gpio.h | 1 +
>  board/sunxi/board.c                    | 4 ++++
>  2 files changed, 5 insertions(+)
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
> index cdb7dbd5b8e5..de77bf638e21 100644
> --- a/arch/arm/include/asm/arch-sunxi/gpio.h
> +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
> @@ -220,6 +220,7 @@ enum sunxi_gpio_number {
>  #define SUN8I_A23_GPL_R_TWI	3
>  #define SUN8I_GPL_R_UART	2
>  #define SUN50I_GPL_R_TWI	2
> +#define SUN50I_H616_GPL_R_TWI	3

The fact that I2C is at function 3 makes me suspicious that there is RSB
at function 2. Have you checked if that is the case?

Either way:

Reviewed-by: Samuel Holland <samuel@sholland.org>

>  #define SUN9I_GPN_R_RSB		3
>  
> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> index 54ff9bc92396..727e8320318f 100644
> --- a/board/sunxi/board.c
> +++ b/board/sunxi/board.c
> @@ -196,6 +196,10 @@ void i2c_init_board(void)
>  	clock_twi_onoff(5, 1);
>  	sunxi_gpio_set_cfgpin(SUNXI_GPL(8), SUN50I_GPL_R_TWI);
>  	sunxi_gpio_set_cfgpin(SUNXI_GPL(9), SUN50I_GPL_R_TWI);
> +#elif CONFIG_MACH_SUN50I_H616
> +	clock_twi_onoff(5, 1);
> +	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN50I_H616_GPL_R_TWI);
> +	sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN50I_H616_GPL_R_TWI);
>  #else
>  	clock_twi_onoff(5, 1);
>  	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_H3_GPL_R_TWI);
> 

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

* [linux-sunxi] [PATCH 11/17] sunxi: Add H616 DRAM support
  2021-01-03  9:26 ` [PATCH 11/17] sunxi: Add H616 DRAM support Jernej Skrabec
@ 2021-01-04  2:39   ` Samuel Holland
  2021-01-04 18:39     ` Jernej Škrabec
  0 siblings, 1 reply; 48+ messages in thread
From: Samuel Holland @ 2021-01-04  2:39 UTC (permalink / raw)
  To: u-boot

On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> Allwinner H616 supports many types of DRAM. Most notably it supports
> LPDDR4. However, all commercially available boards at this time use
> only DDR3, so this commit adds only DDR3 support.
> 
> Controller and MBUS are very similar to H6 but PHY is completely
> unknown.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  arch/arm/include/asm/arch-sunxi/dram.h        |    2 +
>  .../include/asm/arch-sunxi/dram_sun50i_h616.h |  159 +++
>  arch/arm/mach-sunxi/Kconfig                   |   43 +
>  arch/arm/mach-sunxi/Makefile                  |    2 +
>  arch/arm/mach-sunxi/dram_sun50i_h616.c        | 1023 +++++++++++++++++
>  arch/arm/mach-sunxi/dram_timings/Makefile     |    2 +
>  .../mach-sunxi/dram_timings/h616_ddr3_1333.c  |   94 ++
>  7 files changed, 1325 insertions(+)
>  create mode 100644 arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
>  create mode 100644 arch/arm/mach-sunxi/dram_sun50i_h616.c
>  create mode 100644 arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> index 8002b7efdc19..c3b3e1f512b2 100644
> --- a/arch/arm/include/asm/arch-sunxi/dram.h
> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> @@ -29,6 +29,8 @@
>  #include <asm/arch/dram_sun9i.h>
>  #elif defined(CONFIG_MACH_SUN50I_H6)
>  #include <asm/arch/dram_sun50i_h6.h>
> +#elif defined(CONFIG_MACH_SUN50I_H616)
> +#include <asm/arch/dram_sun50i_h616.h>
>  #else
>  #include <asm/arch/dram_sun4i.h>
>  #endif
> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
> new file mode 100644
> index 000000000000..5d105afd6110
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
> @@ -0,0 +1,159 @@
> +/*
> + * H616 dram controller register and constant defines
> + *
> + * (C) Copyright 2020  Jernej Skrabec <jernej.skrabec@siol.net>
> + *
> + * Based on H6 one, which is:
> + * (C) Copyright 2017  Icenowy Zheng <icenowy@aosc.io>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef _SUNXI_DRAM_SUN50I_H616_H
> +#define _SUNXI_DRAM_SUN50I_H616_H
> +
> +#include <stdbool.h>
> +#ifndef __ASSEMBLY__
> +#include <linux/bitops.h>
> +#endif
> +
> +enum sunxi_dram_type {
> +	SUNXI_DRAM_TYPE_DDR3 = 3,
> +	SUNXI_DRAM_TYPE_DDR4,
> +	SUNXI_DRAM_TYPE_LPDDR3 = 7,
> +	SUNXI_DRAM_TYPE_LPDDR4
> +};
> +
> +/* MBUS part is largely the same as in H6, except for one special register */
> +struct sunxi_mctl_com_reg {
> +	u32 cr;			/* 0x000 control register */
> +	u8 reserved_0x004[4];	/* 0x004 */
> +	u32 unk_0x008;		/* 0x008 */
> +	u32 tmr;		/* 0x00c timer register */
> +	u8 reserved_0x010[4];	/* 0x010 */
> +	u32 unk_0x014;		/* 0x014 */
> +	u8 reserved_0x018[8];	/* 0x018 */
> +	u32 maer0;		/* 0x020 master enable register 0 */
> +	u32 maer1;		/* 0x024 master enable register 1 */
> +	u32 maer2;		/* 0x028 master enable register 2 */
> +	u8 reserved_0x02c[468];	/* 0x02c */
> +	u32 bwcr;		/* 0x200 bandwidth control register */
> +	u8 reserved_0x204[12];	/* 0x204 */
> +	/*
> +	 * The last master configured by BSP libdram is at 0x49x, so the
> +	 * size of this struct array is set to 41 (0x29) now.
> +	 */
> +	struct {
> +		u32 cfg0;		/* 0x0 */
> +		u32 cfg1;		/* 0x4 */
> +		u8 reserved_0x8[8];	/* 0x8 */
> +	} master[41];		/* 0x210 + index * 0x10 */
> +	u8 reserved_0x4a0[96];	/* 0x4a0 */
> +	u32 unk_0x500;		/* 0x500 */
> +};
> +check_member(sunxi_mctl_com_reg, unk_0x500, 0x500);
> +
> +/*
> + * Controller registers seems to be the same or at least very similar
> + * to those in H6.
> + */
> +struct sunxi_mctl_ctl_reg {
> +	u32 mstr;		/* 0x000 */
> +	u32 statr;		/* 0x004 unused */
> +	u32 mstr1;		/* 0x008 unused */
> +	u32 unk_0x00c;		/* 0x00c */

This is clken (and the same on H6). It is obvious when looking at the
standby power-down sequence.

> +	u32 mrctrl0;		/* 0x010 unused */
> +	u32 mrctrl1;		/* 0x014 unused */
> +	u32 mrstatr;		/* 0x018 unused */
> +	u32 mrctrl2;		/* 0x01c unused */
> +	u32 derateen;		/* 0x020 unused */
> +	u32 derateint;		/* 0x024 unused */
> +	u8 reserved_0x028[8];	/* 0x028 */
> +	u32 pwrctl;		/* 0x030 unused */
> +	u32 pwrtmg;		/* 0x034 unused */
> +	u32 hwlpctl;		/* 0x038 unused */
> +	u8 reserved_0x03c[20];	/* 0x03c */
> +	u32 rfshctl0;		/* 0x050 unused */
> +	u32 rfshctl1;		/* 0x054 unused */
> +	u8 reserved_0x058[8];	/* 0x05c */
> +	u32 rfshctl3;		/* 0x060 */
> +	u32 rfshtmg;		/* 0x064 */
> +	u8 reserved_0x068[104];	/* 0x068 */
> +	u32 init[8];		/* 0x0d0 */
> +	u32 dimmctl;		/* 0x0f0 unused */
> +	u32 rankctl;		/* 0x0f4 */
> +	u8 reserved_0x0f8[8];	/* 0x0f8 */
> +	u32 dramtmg[17];	/* 0x100 */
> +	u8 reserved_0x144[60];	/* 0x144 */
> +	u32 zqctl[3];		/* 0x180 */
> +	u32 zqstat;		/* 0x18c unused */
> +	u32 dfitmg0;		/* 0x190 */
> +	u32 dfitmg1;		/* 0x194 */
> +	u32 dfilpcfg[2];	/* 0x198 unused */
> +	u32 dfiupd[3];		/* 0x1a0 */
> +	u32 reserved_0x1ac;	/* 0x1ac */
> +	u32 dfimisc;		/* 0x1b0 */
> +	u32 dfitmg2;		/* 0x1b4 unused */
> +	u32 dfitmg3;		/* 0x1b8 unused */
> +	u32 dfistat;		/* 0x1bc */
> +	u32 dbictl;		/* 0x1c0 */
> +	u8 reserved_0x1c4[60];	/* 0x1c4 */
> +	u32 addrmap[12];	/* 0x200 */
> +	u8 reserved_0x230[16];	/* 0x230 */
> +	u32 odtcfg;		/* 0x240 */
> +	u32 odtmap;		/* 0x244 */
> +	u8 reserved_0x248[8];	/* 0x248 */
> +	u32 sched[2];		/* 0x250 */
> +	u8 reserved_0x258[180];	/* 0x258 */
> +	u32 dbgcmd;		/* 0x30c unused */
> +	u32 dbgstat;		/* 0x310 unused */
> +	u8 reserved_0x314[12];	/* 0x314 */
> +	u32 swctl;		/* 0x320 */
> +	u32 swstat;		/* 0x324 */
> +	u8 reserved_0x328[7768];/* 0x328 */
> +	u32 unk_0x2180;		/* 0x2180 */
> +	u8 reserved_0x2184[188];/* 0x2184 */
> +	u32 unk_0x2240;		/* 0x2240 */
> +	u8 reserved_0x2244[3900];/* 0x2244 */
> +	u32 unk_0x3180;		/* 0x3180 */
> +	u8 reserved_0x3184[188];/* 0x3184 */
> +	u32 unk_0x3240;		/* 0x3240 */
> +	u8 reserved_0x3244[3900];/* 0x3244 */
> +	u32 unk_0x4180;		/* 0x4180 */
> +	u8 reserved_0x4184[188];/* 0x4184 */
> +	u32 unk_0x4240;		/* 0x4240 */
> +};
> +check_member(sunxi_mctl_ctl_reg, swstat, 0x324);
> +check_member(sunxi_mctl_ctl_reg, unk_0x4240, 0x4240);
> +
> +#define MSTR_DEVICETYPE_DDR3	BIT(0)
> +#define MSTR_DEVICETYPE_LPDDR2	BIT(2)
> +#define MSTR_DEVICETYPE_LPDDR3	BIT(3)
> +#define MSTR_DEVICETYPE_DDR4	BIT(4)
> +#define MSTR_DEVICETYPE_MASK	GENMASK(5, 0)
> +#define MSTR_2TMODE		BIT(10)
> +#define MSTR_BUSWIDTH_FULL	(0 << 12)
> +#define MSTR_BUSWIDTH_HALF	(1 << 12)
> +#define MSTR_ACTIVE_RANKS(x)	(((x == 2) ? 3 : 1) << 24)
> +#define MSTR_BURST_LENGTH(x)	(((x) >> 1) << 16)
> +
> +struct dram_para {
> +	u32 clk;
> +	enum sunxi_dram_type type;
> +	u8 cols;
> +	u8 rows;
> +	u8 ranks;
> +	u8 bus_full_width;
> +};
> +
> +
> +static inline int ns_to_t(int nanoseconds)
> +{
> +	const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
> +
> +	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
> +}
> +
> +void mctl_set_timing_params(struct dram_para *para);
> +
> +#endif /* _SUNXI_DRAM_SUN50I_H616_H */
> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> index 69ab670abf39..1a5497989f04 100644
> --- a/arch/arm/mach-sunxi/Kconfig
> +++ b/arch/arm/mach-sunxi/Kconfig
> @@ -48,6 +48,46 @@ config DRAM_SUN50I_H6
>  	  Select this dram controller driver for some sun50i platforms,
>  	  like H6.
>  
> +config DRAM_SUN50I_H616
> +	bool
> +	help
> +	  Select this dram controller driver for some sun50i platforms,
> +	  like H616.
> +
> +if DRAM_SUN50I_H616
> +config DRAM_SUN50I_H616_WRITE_LEVELING
> +	bool "H616 DRAM write leveling"
> +	---help---
> +	  Select this when DRAM on your H616 board needs write leveling.
> +
> +config DRAM_SUN50I_H616_READ_CALIBRATION
> +	bool"H616 DRAM read calibration"

Missing a space here.

> +	---help---
> +	  Select this when DRAM on your H616 board needs read calibration.
> +
> +config DRAM_SUN50I_H616_READ_TRAINING
> +	bool "H616 DRAM read training"
> +	---help---
> +	  Select this when DRAM on your H616 board needs read training.
> +
> +config DRAM_SUN50I_H616_WRITE_TRAINING
> +	bool "H616 DRAM write training"
> +	---help---
> +	  Select this when DRAM on your H616 board needs write training.
> +
> +config DRAM_SUN50I_H616_BIT_DELAY_COMPENSATION
> +	bool "H616 DRAM bit delay compensation"
> +	---help---
> +	  Select this when DRAM on your H616 board needs bit delay
> +	  compensation.
> +
> +config DRAM_SUN50I_H616_UNKNOWN_FEATURE
> +	bool "H616 DRAM unknown feature"
> +	---help---
> +	  Select this when DRAM on your H616 board needs this unknown
> +	  feature.
> +endif
> +
>  config SUN6I_P2WI
>  	bool "Allwinner sun6i internal P2WI controller"
>  	help
> @@ -423,6 +463,7 @@ config DRAM_CLK
>  		       MACH_SUN8I_V3S
>  	default 672 if MACH_SUN50I
>  	default 744 if MACH_SUN50I_H6
> +	default 720 if MACH_SUN50I_H616
>  	---help---
>  	Set the dram clock speed, valid range 240 - 480 (prior to sun9i),
>  	must be a multiple of 24. For the sun9i (A80), the tested values
> @@ -439,6 +480,7 @@ endif
>  
>  config DRAM_ZQ
>  	int "sunxi dram zq value"
> +	depends on !MACH_SUN50I_H616
>  	default 123 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || \
>  		       MACH_SUN8I_A23 || MACH_SUN8I_A33 || MACH_SUN8I_A83T
>  	default 127 if MACH_SUN7I
> @@ -456,6 +498,7 @@ config DRAM_ODT_EN
>  	default y if MACH_SUN8I_R40
>  	default y if MACH_SUN50I
>  	default y if MACH_SUN50I_H6
> +	default y if MACH_SUN50I_H616
>  	---help---
>  	Select this to enable dram odt (on die termination).
>  
> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
> index b8aca43d6630..3f081d92f379 100644
> --- a/arch/arm/mach-sunxi/Makefile
> +++ b/arch/arm/mach-sunxi/Makefile
> @@ -40,4 +40,6 @@ obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_sunxi_dw.o
>  obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_timings/
>  obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_sun50i_h6.o
>  obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_timings/
> +obj-$(CONFIG_DRAM_SUN50I_H616)	+= dram_sun50i_h616.o
> +obj-$(CONFIG_DRAM_SUN50I_H616)	+= dram_timings/
>  endif
> diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
> new file mode 100644
> index 000000000000..0c86f54b8a73[...]

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

* [linux-sunxi] [PATCH 12/17] sunxi: Add support for H616 SoC
  2021-01-03  9:26 ` [PATCH 12/17] sunxi: Add support for H616 SoC Jernej Skrabec
@ 2021-01-04  2:47   ` Samuel Holland
  2021-01-04 18:43     ` Jernej Škrabec
  0 siblings, 1 reply; 48+ messages in thread
From: Samuel Holland @ 2021-01-04  2:47 UTC (permalink / raw)
  To: u-boot

On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> H616 is very similar to H6 so most of the infrastructure can be reused.
> However, two big differences are that it doesn't have functional SRAM A2
> which is usually used for TF-A and it doesn't have ARISC co-processor.
> It also needs bigger SPL size - 48 KiB.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  arch/arm/dts/sunxi-u-boot.dtsi                  |  9 +++++++++
>  arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h |  7 +++++++
>  arch/arm/mach-sunxi/Kconfig                     | 11 ++++++++++-
>  arch/arm/mach-sunxi/cpu_info.c                  |  2 ++
>  drivers/power/Kconfig                           |  1 +
>  include/configs/sunxi-common.h                  | 10 ++++++++++
>  6 files changed, 39 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
> index c77cf7cacf0c..7e8644f390a8 100644
> --- a/arch/arm/dts/sunxi-u-boot.dtsi
> +++ b/arch/arm/dts/sunxi-u-boot.dtsi
> @@ -3,6 +3,9 @@
>  #ifdef CONFIG_MACH_SUN50I_H6
>  #define BL31_ADDR 0x104000
>  #define  SCP_ADDR 0x114000
> +#elif defined(CONFIG_MACH_SUN50I_H616)
> +#define BL31_ADDR 0x40004000
> +#define  SCP_ADDR 0x028000

There should be no SCP_ADDR if there is no SCP firmware.

>  #else
>  #define BL31_ADDR  0x44000
>  #define  SCP_ADDR  0x50000
> @@ -61,6 +64,7 @@
>  					};
>  				};
>  
> +#ifndef CONFIG_MACH_SUN50I_H616
>  				scp {
>  					description = "SCP firmware";
>  					type = "firmware";
> @@ -73,6 +77,7 @@
>  						missing-msg = "scp-sunxi";
>  					};
>  				};
> +#endif
>  
>  				@fdt-SEQ {
>  					description = "NAME";
> @@ -87,7 +92,11 @@
>  				@config-SEQ {
>  					description = "NAME";
>  					firmware = "atf";
> +#ifdef CONFIG_MACH_SUN50I_H616
> +					loadables = "uboot";
> +#else
>  					loadables = "scp", "uboot";
> +#endif
>  					fdt = "fdt-SEQ";
>  				};
>  			};
> diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
> index 6392cb07b472..d9cf8ae04288 100644
> --- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
> +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
> @@ -28,13 +28,20 @@
>  #define SUNXI_GIC400_BASE		0x03020000
>  #define SUNXI_IOMMU_BASE		0x030F0000
>  
> +#ifdef CONFIG_MACH_SUN50I_H6
>  #define SUNXI_DRAM_COM_BASE		0x04002000
>  #define SUNXI_DRAM_CTL0_BASE		0x04003000
>  #define SUNXI_DRAM_PHY0_BASE		0x04005000
> +#endif
>  #define SUNXI_NFC_BASE			0x04011000
>  #define SUNXI_MMC0_BASE			0x04020000
>  #define SUNXI_MMC1_BASE			0x04021000
>  #define SUNXI_MMC2_BASE			0x04022000
> +#ifdef CONFIG_MACH_SUN50I_H616
> +#define SUNXI_DRAM_COM_BASE		0x047FA000
> +#define SUNXI_DRAM_CTL0_BASE		0x047FB000
> +#define SUNXI_DRAM_PHY0_BASE		0x04800000
> +#endif
>  
>  #define SUNXI_UART0_BASE		0x05000000
>  #define SUNXI_UART1_BASE		0x05000400
> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> index 1a5497989f04..859b30d74ceb 100644
> --- a/arch/arm/mach-sunxi/Kconfig
> +++ b/arch/arm/mach-sunxi/Kconfig
> @@ -190,9 +190,10 @@ config MACH_SUNXI_H3_H5
>  	select SUPPORT_SPL
>  
>  # TODO: try out A80's 8GiB DRAM space
> +# TODO: H616 supports 4 GiB DRAM space
>  config SUNXI_DRAM_MAX_SIZE
>  	hex
> -	default 0xC0000000 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6
> +	default 0xC0000000 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6 || MACH_SUN50I_H616
>  	default 0x80000000
>  
>  choice
> @@ -354,6 +355,12 @@ config MACH_SUN50I_H6
>  	select PHY_SUN4I_USB
>  	select DRAM_SUN50I_H6
>  
> +config MACH_SUN50I_H616
> +	bool "sun50i (Allwinner H616)"
> +	select ARM64
> +	select DRAM_SUN50I_H616
> +	select SUN50I_GEN_H6
> +
>  endchoice
>  
>  # The sun8i SoCs share a lot, this helps to avoid a lot of "if A23 || A33"
> @@ -589,6 +596,7 @@ config SYS_CLK_FREQ
>  	default 816000000 if MACH_SUN50I || MACH_SUN50I_H5
>  	default 1008000000 if MACH_SUN8I
>  	default 1008000000 if MACH_SUN9I
> +	default 1008000000 if MACH_SUN50I_H616
>  
>  config SYS_CONFIG_NAME
>  	default "sun4i" if MACH_SUN4I
> @@ -599,6 +607,7 @@ config SYS_CONFIG_NAME
>  	default "sun9i" if MACH_SUN9I
>  	default "sun50i" if MACH_SUN50I
>  	default "sun50i" if MACH_SUN50I_H6
> +	default "sun50i" if MACH_SUN50I_H616
>  
>  config SYS_BOARD
>  	default "sunxi"
> diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
> index 875e5a1a8a8e..ba33ef24300c 100644
> --- a/arch/arm/mach-sunxi/cpu_info.c
> +++ b/arch/arm/mach-sunxi/cpu_info.c
> @@ -99,6 +99,8 @@ int print_cpuinfo(void)
>  	puts("CPU:   Allwinner H5 (SUN50I)\n");
>  #elif defined CONFIG_MACH_SUN50I_H6
>  	puts("CPU:   Allwinner H6 (SUN50I)\n");
> +#elif defined CONFIG_MACH_SUN50I_H616
> +	puts("CPU:   Allwinner H616 (SUN50I)\n");
>  #else
>  #warning Please update cpu_info.c with correct CPU information
>  	puts("CPU:   SUNXI Family\n");
> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> index d17cf2d9112a..c5fbf1f832a9 100644
> --- a/drivers/power/Kconfig
> +++ b/drivers/power/Kconfig
> @@ -13,6 +13,7 @@ choice
>  	depends on ARCH_SUNXI
>  	default AXP209_POWER if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
>  	default AXP221_POWER if MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33 || MACH_SUN8I_R40
> +	default AXP305_POWER if MACH_SUN50I_H616
>  	default AXP818_POWER if MACH_SUN8I_A83T
>  	default SUNXI_NO_PMIC if MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_V3S
>  
> diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
> index 203cb10fbabc..6e8f547214d6 100644
> --- a/include/configs/sunxi-common.h
> +++ b/include/configs/sunxi-common.h
> @@ -178,9 +178,14 @@
>  #define LOW_LEVEL_SRAM_STACK		0x00018000
>  #endif /* !CONFIG_ARM64 */
>  #elif CONFIG_SUNXI_SRAM_ADDRESS == 0x20000
> +#ifdef CONFIG_MACH_SUN50I_H616
> +#define CONFIG_SPL_MAX_SIZE		0xbfa0		/* 48 KiB */
> +#define LOW_LEVEL_SRAM_STACK		0x58000
> +#else
>  #define CONFIG_SPL_MAX_SIZE		0x7fa0		/* 32 KiB */
>  /* end of SRAM A2 on H6 for now */
>  #define LOW_LEVEL_SRAM_STACK		0x00118000
> +#endif
>  #else
>  #define CONFIG_SPL_MAX_SIZE		0x5fa0		/* 24KB on sun4i/sun7i */
>  #define LOW_LEVEL_SRAM_STACK		0x00008000	/* End of sram */
> @@ -188,7 +193,12 @@
>  
>  #define CONFIG_SPL_STACK		LOW_LEVEL_SRAM_STACK
>  
> +/* H616 supports 48 KiB SPL */
> +#ifdef CONFIG_MACH_SUN50I_H616
> +#define CONFIG_SPL_PAD_TO		49152		/* decimal for 'dd' */

H616 supports much larger SPLs than 48 KiB, and CONFIG_SPL_PAD_TO
enforces both a minimum and maximum size. So please leave
CONFIG_SPL_PAD_TO undefined on the new platform (or for all
SUN50I_GEN_H6, where the SPL size restriction was removed).

> +#else
>  #define CONFIG_SPL_PAD_TO		32768		/* decimal for 'dd' */
> +#endif
>  
>  
>  /* I2C */
> 

Cheers,
Samuel

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

* [PATCH 04/17] i2c: mvtwsi: sunxi: update macro
  2021-01-03  9:26 ` [PATCH 04/17] i2c: mvtwsi: sunxi: update macro Jernej Skrabec
  2021-01-03 23:55   ` [linux-sunxi] " Samuel Holland
@ 2021-01-04  5:57   ` Heiko Schocher
  1 sibling, 0 replies; 48+ messages in thread
From: Heiko Schocher @ 2021-01-04  5:57 UTC (permalink / raw)
  To: u-boot

Hello Jernej,

Am 03.01.21 um 10:26 schrieb Jernej Skrabec:
> While currently none of the newer Allwinner SoCs currently has I2C
> support implemented in U-Boot, this will change soon. mvtwsi driver is
> good as it is for them except one macro. Update it to be ready once I2C
> support lands for those SoCs.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  drivers/i2c/mvtwsi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Heiko Schocher <hs@denx.de>

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs at denx.de

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

* [linux-sunxi] [PATCH 02/17] sunxi: Introduce common symbol for H6 like SoCs
  2021-01-03 23:43   ` [linux-sunxi] " Samuel Holland
@ 2021-01-04 10:35     ` André Przywara
  2021-01-04 18:28       ` Jernej Škrabec
  0 siblings, 1 reply; 48+ messages in thread
From: André Przywara @ 2021-01-04 10:35 UTC (permalink / raw)
  To: u-boot

On 03/01/2021 23:43, Samuel Holland wrote:

Hi Jernej,

thanks for that patch, that's a nice solution to avoid those long #ifdef
chains!

> On 1/3/21 3:26 AM, Jernej Skrabec wrote:
>> It turns out that there are at least 2 other SoCs which have basically
>> the same memory map, similar clocks and other features as H6. It's very
>> likely that we'll see more such SoCs in the future. In order to ease
>> porting to new SoCs and lower ifdef clutter, introduce common symbol for
>> them.
>>
>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>> ---
>>  arch/arm/include/asm/arch-sunxi/boot0.h |  2 +-
>>  arch/arm/include/asm/arch-sunxi/clock.h |  2 +-
>>  arch/arm/include/asm/arch-sunxi/cpu.h   |  2 +-
>>  arch/arm/include/asm/arch-sunxi/timer.h |  2 +-
>>  arch/arm/mach-sunxi/Kconfig             | 21 +++++++++++++--------
>>  arch/arm/mach-sunxi/Makefile            |  2 +-
>>  arch/arm/mach-sunxi/board.c             |  4 ++--
>>  arch/arm/mach-sunxi/rmr_switch.S        |  2 +-
>>  common/spl/Kconfig                      |  4 ++--
>>  include/configs/sun50i.h                |  2 +-
>>  10 files changed, 24 insertions(+), 19 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
>> index 46d0f0666c2b..e8e8e38f0556 100644
>> --- a/arch/arm/include/asm/arch-sunxi/boot0.h
>> +++ b/arch/arm/include/asm/arch-sunxi/boot0.h
>> @@ -39,7 +39,7 @@
>>  	.word	0xf57ff06f	// isb     sy
>>  	.word	0xe320f003	// wfi
>>  	.word	0xeafffffd	// b       @wfi
>> -#ifndef CONFIG_MACH_SUN50I_H6
>> +#ifndef CONFIG_SUN50I_GEN_H6
>>  	.word	0x017000a0	// writeable RVBAR mapping address
>>  #else
>>  	.word	0x09010040	// writeable RVBAR mapping address
>> diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
>> index 5994130e6b54..cbbe5c7a1e68 100644
>> --- a/arch/arm/include/asm/arch-sunxi/clock.h
>> +++ b/arch/arm/include/asm/arch-sunxi/clock.h
>> @@ -16,7 +16,7 @@
>>  /* clock control module regs definition */
>>  #if defined(CONFIG_MACH_SUN8I_A83T)
>>  #include <asm/arch/clock_sun8i_a83t.h>
>> -#elif defined(CONFIG_MACH_SUN50I_H6)
>> +#elif defined(CONFIG_SUN50I_GEN_H6)
>>  #include <asm/arch/clock_sun50i_h6.h>
>>  #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
>>        defined(CONFIG_MACH_SUN50I)
>> diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
>> index 8b57d24e2f0c..b08f2023748c 100644
>> --- a/arch/arm/include/asm/arch-sunxi/cpu.h
>> +++ b/arch/arm/include/asm/arch-sunxi/cpu.h
>> @@ -8,7 +8,7 @@
>>  
>>  #if defined(CONFIG_MACH_SUN9I)
>>  #include <asm/arch/cpu_sun9i.h>
>> -#elif defined(CONFIG_MACH_SUN50I_H6)
>> +#elif defined(CONFIG_SUN50I_GEN_H6)
>>  #include <asm/arch/cpu_sun50i_h6.h>
>>  #else
>>  #include <asm/arch/cpu_sun4i.h>
>> diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h
>> index 6f138d04b806..bb5626d893bb 100644
>> --- a/arch/arm/include/asm/arch-sunxi/timer.h
>> +++ b/arch/arm/include/asm/arch-sunxi/timer.h
>> @@ -76,7 +76,7 @@ struct sunxi_timer_reg {
>>  	struct sunxi_tgp tgp[4];
>>  	u8 res5[8];
>>  	u32 cpu_cfg;
>> -#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
>> +#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
>>  	u8 res3[16];
>>  	struct sunxi_wdog wdog[5];	/* We have 5 watchdogs */
>>  #endif
>> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
>> index 49ef217f08c0..1cf79bad7cf6 100644
>> --- a/arch/arm/mach-sunxi/Kconfig
>> +++ b/arch/arm/mach-sunxi/Kconfig
>> @@ -82,7 +82,7 @@ config SUN8I_RSB
>>  config SUNXI_SRAM_ADDRESS
>>  	hex
>>  	default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
>> -	default 0x20000 if MACH_SUN50I_H6
>> +	default 0x20000 if SUN50I_GEN_H6
>>  	default 0x0
>>  	---help---
>>  	Older Allwinner SoCs have their mask boot ROM mapped just below 4GB,
>> @@ -108,6 +108,15 @@ config SUNXI_GEN_SUN6I
>>  	separate ahb reset control registers, custom pmic bus, new style
>>  	watchdog, etc.
>>  
>> +config SUN50I_GEN_H6
> 
> The new memory map is also used for 32-bit SoCs V5 (sun8iw12p1) and
> newer. So this is not sun50i-specific, and I'd suggest SUNXI_GEN_H6 (or
> even SUNXI_GEN_H6_V5). It is unfortunate there appears to be no name for
> this family.

Yeah, the Allwinner generation naming being *core* dependent is really
annyoing and not helpful.
I am fine with a rename, but then it would be very close to
"CONFIG_SUNXI_GEN_SUN6I", which is quite confusing to any readers
(already stumbled upon it myself in patch 04/17).

Any opinions?

> 
>> +	bool
>> +	select FIT
>> +	select SPL_LOAD_FIT
>> +	select SUPPORT_SPL
>> +	---help---
>> +	Select this for sunxi SoCs which have H6 like peripherals, clocks
>> +	and memory map.
>> +
>>  config SUNXI_DRAM_DW
>>  	bool
>>  	---help---
>> @@ -302,10 +311,7 @@ config MACH_SUN50I_H5
>>  config MACH_SUN50I_H6
>>  	bool "sun50i (Allwinner H6)"
>>  	select ARM64
>> -	select SUPPORT_SPL
>> -	select FIT
>>  	select PHY_SUN4I_USB
>> -	select SPL_LOAD_FIT
>>  	select DRAM_SUN50I_H6
> 
> I would expect this to select SUN50I_GEN_H6.

Indeed, that breaks H6 builds.

>>  endchoice
>> @@ -540,7 +546,6 @@ config SYS_CLK_FREQ
>>  	default 816000000 if MACH_SUN50I || MACH_SUN50I_H5
>>  	default 1008000000 if MACH_SUN8I
>>  	default 1008000000 if MACH_SUN9I
>> -	default 888000000 if MACH_SUN50I_H6
> 
> Was this removal intentional? You later add a different value for H616 only.
> 
>>  config SYS_CONFIG_NAME
>>  	default "sun4i" if MACH_SUN4I
>> @@ -756,7 +761,7 @@ config VIDEO_SUNXI
>>  	depends on !MACH_SUN8I_V3S
>>  	depends on !MACH_SUN9I
>>  	depends on !MACH_SUN50I
>> -	depends on !MACH_SUN50I_H6
>> +	depends on !SUN50I_GEN_H6
>>  	select VIDEO
>>  	imply VIDEO_DT_SIMPLEFB
>>  	default y
>> @@ -989,11 +994,11 @@ config SPL_STACK_R_ADDR
>>  	default 0x4fe00000 if MACH_SUN8I
>>  	default 0x2fe00000 if MACH_SUN9I
>>  	default 0x4fe00000 if MACH_SUN50I
>> -	default 0x4fe00000 if MACH_SUN50I_H6
>> +	default 0x4fe00000 if SUN50I_GEN_H6
>>  
>>  config SPL_SPI_SUNXI
>>  	bool "Support for SPI Flash on Allwinner SoCs in SPL"
>> -	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6
>> +	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6

I know I suggested this, but it was a bit premature. The SPL SPI code
needs some adjustments first. I have a patch, will send it ASAP. But for
now you can just drop this change.

Thanks!
Andre


>>  	help
>>  	  Enable support for SPI Flash. This option allows SPL to read from
>>  	  sunxi SPI Flash. It uses the same method as the boot ROM, so does
>> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
>> index d129f334798b..b8aca43d6630 100644
>> --- a/arch/arm/mach-sunxi/Makefile
>> +++ b/arch/arm/mach-sunxi/Makefile
>> @@ -26,7 +26,7 @@ else
>>  obj-$(CONFIG_MACH_SUN8I)	+= clock_sun6i.o
>>  endif
>>  obj-$(CONFIG_MACH_SUN9I)	+= clock_sun9i.o gtbus_sun9i.o
>> -obj-$(CONFIG_MACH_SUN50I_H6)	+= clock_sun50i_h6.o
>> +obj-$(CONFIG_SUN50I_GEN_H6)	+= clock_sun50i_h6.o
>>  
>>  ifdef CONFIG_SPL_BUILD
>>  obj-$(CONFIG_DRAM_SUN4I)	+= dram_sun4i.o
>> diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
>> index f40fccd8f8b9..7a8b303f233c 100644
>> --- a/arch/arm/mach-sunxi/board.c
>> +++ b/arch/arm/mach-sunxi/board.c
>> @@ -144,7 +144,7 @@ static int gpio_init(void)
>>  #error Unsupported console port number. Please fix pin mux settings in board.c
>>  #endif
>>  
>> -#ifdef CONFIG_MACH_SUN50I_H6
>> +#ifdef CONFIG_SUN50I_GEN_H6
>>  	/* Update PIO power bias configuration by copy hardware detected value */
>>  	val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
>>  	writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
>> @@ -329,7 +329,7 @@ void reset_cpu(ulong addr)
>>  		/* sun5i sometimes gets stuck without this */
>>  		writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
>>  	}
>> -#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
>> +#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
>>  #if defined(CONFIG_MACH_SUN50I_H6)
>>  	/* WDOG is broken for some H6 rev. use the R_WDOG instead */
>>  	static const struct sunxi_wdog *wdog =
>> diff --git a/arch/arm/mach-sunxi/rmr_switch.S b/arch/arm/mach-sunxi/rmr_switch.S
>> index fafd306f95b1..33e55d496865 100644
>> --- a/arch/arm/mach-sunxi/rmr_switch.S
>> +++ b/arch/arm/mach-sunxi/rmr_switch.S
>> @@ -30,7 +30,7 @@
>>  
>>  .text
>>  
>> -#ifndef CONFIG_MACH_SUN50I_H6
>> +#ifndef CONFIG_SUN50I_GEN_H6
>>  	ldr	r1, =0x017000a0		@ MMIO mapped RVBAR[0] register
>>  #else
>>  	ldr	r1, =0x09010040		@ MMIO mapped RVBAR[0] register
>> diff --git a/common/spl/Kconfig b/common/spl/Kconfig
>> index d8086bd9e874..bed715774d81 100644
>> --- a/common/spl/Kconfig
>> +++ b/common/spl/Kconfig
>> @@ -150,7 +150,7 @@ config SPL_TEXT_BASE
>>  	hex "SPL Text Base"
>>  	default ISW_ENTRY_ADDR if AM43XX || AM33XX || OMAP54XX || ARCH_KEYSTONE
>>  	default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I
>> -	default 0x20060 if MACH_SUN50I_H6
>> +	default 0x20060 if SUN50I_GEN_H6
>>  	default 0x00060 if ARCH_SUNXI
>>  	default 0xfffc0000 if ARCH_ZYNQMP
>>  	default 0x0
>> @@ -459,7 +459,7 @@ config SPL_SHA512_SUPPORT
>>  config SPL_FIT_IMAGE_TINY
>>  	bool "Remove functionality from SPL FIT loading to reduce size"
>>  	depends on SPL_FIT
>> -	default y if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6
>> +	default y if MACH_SUN50I || MACH_SUN50I_H5 || SUN50I_GEN_H6
> 
> This can probably be simplified to ARCH_SUNXI.
> 
>>  	default y if ARCH_IMX8M
>>  	help
>>  	  Enable this to reduce the size of the FIT image loading code
>> diff --git a/include/configs/sun50i.h b/include/configs/sun50i.h
>> index e050a5299f3b..bc2e3a3d0088 100644
>> --- a/include/configs/sun50i.h
>> +++ b/include/configs/sun50i.h
>> @@ -10,7 +10,7 @@
>>   * A64 specific configuration
>>   */
>>  
>> -#ifndef CONFIG_MACH_SUN50I_H6
>> +#ifndef CONFIG_SUN50I_GEN_H6
>>  #define GICD_BASE		0x1c81000
>>  #define GICC_BASE		0x1c82000
>>  #else
>>
> 
> Cheers,
> Samuel
> 

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

* [linux-sunxi] [PATCH 02/17] sunxi: Introduce common symbol for H6 like SoCs
  2021-01-04 10:35     ` André Przywara
@ 2021-01-04 18:28       ` Jernej Škrabec
  2021-01-11  0:13         ` André Przywara
  0 siblings, 1 reply; 48+ messages in thread
From: Jernej Škrabec @ 2021-01-04 18:28 UTC (permalink / raw)
  To: u-boot

Dne ponedeljek, 04. januar 2021 ob 11:35:41 CET je Andr? Przywara napisal(a):
> On 03/01/2021 23:43, Samuel Holland wrote:
> 
> Hi Jernej,
> 
> thanks for that patch, that's a nice solution to avoid those long #ifdef
> chains!
> 
> > On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> >> It turns out that there are at least 2 other SoCs which have basically
> >> the same memory map, similar clocks and other features as H6. It's very
> >> likely that we'll see more such SoCs in the future. In order to ease
> >> porting to new SoCs and lower ifdef clutter, introduce common symbol for
> >> them.
> >> 
> >> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> >> ---
> >> 
> >>  arch/arm/include/asm/arch-sunxi/boot0.h |  2 +-
> >>  arch/arm/include/asm/arch-sunxi/clock.h |  2 +-
> >>  arch/arm/include/asm/arch-sunxi/cpu.h   |  2 +-
> >>  arch/arm/include/asm/arch-sunxi/timer.h |  2 +-
> >>  arch/arm/mach-sunxi/Kconfig             | 21 +++++++++++++--------
> >>  arch/arm/mach-sunxi/Makefile            |  2 +-
> >>  arch/arm/mach-sunxi/board.c             |  4 ++--
> >>  arch/arm/mach-sunxi/rmr_switch.S        |  2 +-
> >>  common/spl/Kconfig                      |  4 ++--
> >>  include/configs/sun50i.h                |  2 +-
> >>  10 files changed, 24 insertions(+), 19 deletions(-)
> >> 
> >> diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h
> >> b/arch/arm/include/asm/arch-sunxi/boot0.h index
> >> 46d0f0666c2b..e8e8e38f0556 100644
> >> --- a/arch/arm/include/asm/arch-sunxi/boot0.h
> >> +++ b/arch/arm/include/asm/arch-sunxi/boot0.h
> >> @@ -39,7 +39,7 @@
> >> 
> >>  	.word	0xf57ff06f	// isb     sy
> >>  	.word	0xe320f003	// wfi
> >>  	.word	0xeafffffd	// b       @wfi
> >> 
> >> -#ifndef CONFIG_MACH_SUN50I_H6
> >> +#ifndef CONFIG_SUN50I_GEN_H6
> >> 
> >>  	.word	0x017000a0	// writeable RVBAR mapping address
> >>  
> >>  #else
> >>  
> >>  	.word	0x09010040	// writeable RVBAR mapping address
> >> 
> >> diff --git a/arch/arm/include/asm/arch-sunxi/clock.h
> >> b/arch/arm/include/asm/arch-sunxi/clock.h index
> >> 5994130e6b54..cbbe5c7a1e68 100644
> >> --- a/arch/arm/include/asm/arch-sunxi/clock.h
> >> +++ b/arch/arm/include/asm/arch-sunxi/clock.h
> >> @@ -16,7 +16,7 @@
> >> 
> >>  /* clock control module regs definition */
> >>  #if defined(CONFIG_MACH_SUN8I_A83T)
> >>  #include <asm/arch/clock_sun8i_a83t.h>
> >> 
> >> -#elif defined(CONFIG_MACH_SUN50I_H6)
> >> +#elif defined(CONFIG_SUN50I_GEN_H6)
> >> 
> >>  #include <asm/arch/clock_sun50i_h6.h>
> >>  #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
> >>  
> >>        defined(CONFIG_MACH_SUN50I)
> >> 
> >> diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h
> >> b/arch/arm/include/asm/arch-sunxi/cpu.h index 8b57d24e2f0c..b08f2023748c
> >> 100644
> >> --- a/arch/arm/include/asm/arch-sunxi/cpu.h
> >> +++ b/arch/arm/include/asm/arch-sunxi/cpu.h
> >> @@ -8,7 +8,7 @@
> >> 
> >>  #if defined(CONFIG_MACH_SUN9I)
> >>  #include <asm/arch/cpu_sun9i.h>
> >> 
> >> -#elif defined(CONFIG_MACH_SUN50I_H6)
> >> +#elif defined(CONFIG_SUN50I_GEN_H6)
> >> 
> >>  #include <asm/arch/cpu_sun50i_h6.h>
> >>  #else
> >>  #include <asm/arch/cpu_sun4i.h>
> >> 
> >> diff --git a/arch/arm/include/asm/arch-sunxi/timer.h
> >> b/arch/arm/include/asm/arch-sunxi/timer.h index
> >> 6f138d04b806..bb5626d893bb 100644
> >> --- a/arch/arm/include/asm/arch-sunxi/timer.h
> >> +++ b/arch/arm/include/asm/arch-sunxi/timer.h
> >> @@ -76,7 +76,7 @@ struct sunxi_timer_reg {
> >> 
> >>  	struct sunxi_tgp tgp[4];
> >>  	u8 res5[8];
> >>  	u32 cpu_cfg;
> >> 
> >> -#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
> >> +#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
> >> 
> >>  	u8 res3[16];
> >>  	struct sunxi_wdog wdog[5];	/* We have 5 watchdogs */
> >>  
> >>  #endif
> >> 
> >> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> >> index 49ef217f08c0..1cf79bad7cf6 100644
> >> --- a/arch/arm/mach-sunxi/Kconfig
> >> +++ b/arch/arm/mach-sunxi/Kconfig
> >> @@ -82,7 +82,7 @@ config SUN8I_RSB
> >> 
> >>  config SUNXI_SRAM_ADDRESS
> >>  
> >>  	hex
> >>  	default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
> >> 
> >> -	default 0x20000 if MACH_SUN50I_H6
> >> +	default 0x20000 if SUN50I_GEN_H6
> >> 
> >>  	default 0x0
> >>  	---help---
> >>  	Older Allwinner SoCs have their mask boot ROM mapped just below 
4GB,
> >> 
> >> @@ -108,6 +108,15 @@ config SUNXI_GEN_SUN6I
> >> 
> >>  	separate ahb reset control registers, custom pmic bus, new style
> >>  	watchdog, etc.
> >> 
> >> +config SUN50I_GEN_H6
> > 
> > The new memory map is also used for 32-bit SoCs V5 (sun8iw12p1) and
> > newer. So this is not sun50i-specific, and I'd suggest SUNXI_GEN_H6 (or
> > even SUNXI_GEN_H6_V5). It is unfortunate there appears to be no name for
> > this family.
> 
> Yeah, the Allwinner generation naming being *core* dependent is really
> annyoing and not helpful.
> I am fine with a rename, but then it would be very close to
> "CONFIG_SUNXI_GEN_SUN6I", which is quite confusing to any readers
> (already stumbled upon it myself in patch 04/17).
> 
> Any opinions?

I would leave it as it is, it's common to name something, usually driver, but 
in this case symbol, after first known device that implemented particular 
feature.

> 
> >> +	bool
> >> +	select FIT
> >> +	select SPL_LOAD_FIT
> >> +	select SUPPORT_SPL
> >> +	---help---
> >> +	Select this for sunxi SoCs which have H6 like peripherals, clocks
> >> +	and memory map.
> >> +
> >> 
> >>  config SUNXI_DRAM_DW
> >>  
> >>  	bool
> >>  	---help---
> >> 
> >> @@ -302,10 +311,7 @@ config MACH_SUN50I_H5
> >> 
> >>  config MACH_SUN50I_H6
> >>  
> >>  	bool "sun50i (Allwinner H6)"
> >>  	select ARM64
> >> 
> >> -	select SUPPORT_SPL
> >> -	select FIT
> >> 
> >>  	select PHY_SUN4I_USB
> >> 
> >> -	select SPL_LOAD_FIT
> >> 
> >>  	select DRAM_SUN50I_H6
> > 
> > I would expect this to select SUN50I_GEN_H6.
> 
> Indeed, that breaks H6 builds.

Ops, leftover after refactoring.

> 
> >>  endchoice
> >> 
> >> @@ -540,7 +546,6 @@ config SYS_CLK_FREQ
> >> 
> >>  	default 816000000 if MACH_SUN50I || MACH_SUN50I_H5
> >>  	default 1008000000 if MACH_SUN8I
> >>  	default 1008000000 if MACH_SUN9I
> >> 
> >> -	default 888000000 if MACH_SUN50I_H6
> > 
> > Was this removal intentional? You later add a different value for H616
> > only.> 

That's also an oversight after refactoring.

> >>  config SYS_CONFIG_NAME
> >>  
> >>  	default "sun4i" if MACH_SUN4I
> >> 
> >> @@ -756,7 +761,7 @@ config VIDEO_SUNXI
> >> 
> >>  	depends on !MACH_SUN8I_V3S
> >>  	depends on !MACH_SUN9I
> >>  	depends on !MACH_SUN50I
> >> 
> >> -	depends on !MACH_SUN50I_H6
> >> +	depends on !SUN50I_GEN_H6
> >> 
> >>  	select VIDEO
> >>  	imply VIDEO_DT_SIMPLEFB
> >>  	default y
> >> 
> >> @@ -989,11 +994,11 @@ config SPL_STACK_R_ADDR
> >> 
> >>  	default 0x4fe00000 if MACH_SUN8I
> >>  	default 0x2fe00000 if MACH_SUN9I
> >>  	default 0x4fe00000 if MACH_SUN50I
> >> 
> >> -	default 0x4fe00000 if MACH_SUN50I_H6
> >> +	default 0x4fe00000 if SUN50I_GEN_H6
> >> 
> >>  config SPL_SPI_SUNXI
> >>  
> >>  	bool "Support for SPI Flash on Allwinner SoCs in SPL"
> >> 
> >> -	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || 
MACH_SUNXI_H3_H5
> >> || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6 +	depends on
> >> MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 ||
> >> MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6
> I know I suggested this, but it was a bit premature. The SPL SPI code
> needs some adjustments first. I have a patch, will send it ASAP. But for
> now you can just drop this change.

Ok,

Best regards,
Jernej

> 
> Thanks!
> Andre
> 
> >>  	help
> >>  	
> >>  	  Enable support for SPI Flash. This option allows SPL to read 
from
> >>  	  sunxi SPI Flash. It uses the same method as the boot ROM, so 
does
> >> 
> >> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
> >> index d129f334798b..b8aca43d6630 100644
> >> --- a/arch/arm/mach-sunxi/Makefile
> >> +++ b/arch/arm/mach-sunxi/Makefile
> >> @@ -26,7 +26,7 @@ else
> >> 
> >>  obj-$(CONFIG_MACH_SUN8I)	+= clock_sun6i.o
> >>  endif
> >>  obj-$(CONFIG_MACH_SUN9I)	+= clock_sun9i.o gtbus_sun9i.o
> >> 
> >> -obj-$(CONFIG_MACH_SUN50I_H6)	+= clock_sun50i_h6.o
> >> +obj-$(CONFIG_SUN50I_GEN_H6)	+= clock_sun50i_h6.o
> >> 
> >>  ifdef CONFIG_SPL_BUILD
> >>  obj-$(CONFIG_DRAM_SUN4I)	+= dram_sun4i.o
> >> 
> >> diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
> >> index f40fccd8f8b9..7a8b303f233c 100644
> >> --- a/arch/arm/mach-sunxi/board.c
> >> +++ b/arch/arm/mach-sunxi/board.c
> >> @@ -144,7 +144,7 @@ static int gpio_init(void)
> >> 
> >>  #error Unsupported console port number. Please fix pin mux settings in
> >>  board.c #endif
> >> 
> >> -#ifdef CONFIG_MACH_SUN50I_H6
> >> +#ifdef CONFIG_SUN50I_GEN_H6
> >> 
> >>  	/* Update PIO power bias configuration by copy hardware detected 
value
> >>  	*/
> >>  	val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
> >>  	writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
> >> 
> >> @@ -329,7 +329,7 @@ void reset_cpu(ulong addr)
> >> 
> >>  		/* sun5i sometimes gets stuck without this */
> >>  		writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
> >>  	
> >>  	}
> >> 
> >> -#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
> >> +#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
> >> 
> >>  #if defined(CONFIG_MACH_SUN50I_H6)
> >>  
> >>  	/* WDOG is broken for some H6 rev. use the R_WDOG instead */
> >>  	static const struct sunxi_wdog *wdog =
> >> 
> >> diff --git a/arch/arm/mach-sunxi/rmr_switch.S
> >> b/arch/arm/mach-sunxi/rmr_switch.S index fafd306f95b1..33e55d496865
> >> 100644
> >> --- a/arch/arm/mach-sunxi/rmr_switch.S
> >> +++ b/arch/arm/mach-sunxi/rmr_switch.S
> >> @@ -30,7 +30,7 @@
> >> 
> >>  .text
> >> 
> >> -#ifndef CONFIG_MACH_SUN50I_H6
> >> +#ifndef CONFIG_SUN50I_GEN_H6
> >> 
> >>  	ldr	r1, =0x017000a0		@ MMIO mapped 
RVBAR[0] register
> >>  
> >>  #else
> >>  
> >>  	ldr	r1, =0x09010040		@ MMIO mapped 
RVBAR[0] register
> >> 
> >> diff --git a/common/spl/Kconfig b/common/spl/Kconfig
> >> index d8086bd9e874..bed715774d81 100644
> >> --- a/common/spl/Kconfig
> >> +++ b/common/spl/Kconfig
> >> @@ -150,7 +150,7 @@ config SPL_TEXT_BASE
> >> 
> >>  	hex "SPL Text Base"
> >>  	default ISW_ENTRY_ADDR if AM43XX || AM33XX || OMAP54XX || 
ARCH_KEYSTONE
> >>  	default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I
> >> 
> >> -	default 0x20060 if MACH_SUN50I_H6
> >> +	default 0x20060 if SUN50I_GEN_H6
> >> 
> >>  	default 0x00060 if ARCH_SUNXI
> >>  	default 0xfffc0000 if ARCH_ZYNQMP
> >>  	default 0x0
> >> 
> >> @@ -459,7 +459,7 @@ config SPL_SHA512_SUPPORT
> >> 
> >>  config SPL_FIT_IMAGE_TINY
> >>  
> >>  	bool "Remove functionality from SPL FIT loading to reduce size"
> >>  	depends on SPL_FIT
> >> 
> >> -	default y if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6
> >> +	default y if MACH_SUN50I || MACH_SUN50I_H5 || SUN50I_GEN_H6
> > 
> > This can probably be simplified to ARCH_SUNXI.
> > 
> >>  	default y if ARCH_IMX8M
> >>  	help
> >>  	
> >>  	  Enable this to reduce the size of the FIT image loading code
> >> 
> >> diff --git a/include/configs/sun50i.h b/include/configs/sun50i.h
> >> index e050a5299f3b..bc2e3a3d0088 100644
> >> --- a/include/configs/sun50i.h
> >> +++ b/include/configs/sun50i.h
> >> @@ -10,7 +10,7 @@
> >> 
> >>   * A64 specific configuration
> >>   */
> >> 
> >> -#ifndef CONFIG_MACH_SUN50I_H6
> >> +#ifndef CONFIG_SUN50I_GEN_H6
> >> 
> >>  #define GICD_BASE		0x1c81000
> >>  #define GICC_BASE		0x1c82000
> >>  #else
> > 
> > Cheers,
> > Samuel

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

* [linux-sunxi] [PATCH 10/17] sunxi: add support for R_I2C on H616
  2021-01-04  2:33   ` [linux-sunxi] " Samuel Holland
@ 2021-01-04 18:36     ` Jernej Škrabec
  0 siblings, 0 replies; 48+ messages in thread
From: Jernej Škrabec @ 2021-01-04 18:36 UTC (permalink / raw)
  To: u-boot

Dne ponedeljek, 04. januar 2021 ob 03:33:12 CET je Samuel Holland napisal(a):
> On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> > This port is needed for communication with PMIC. SPL uses it to set DRAM
> > voltage on H616 boards.
> > 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> > 
> >  arch/arm/include/asm/arch-sunxi/gpio.h | 1 +
> >  board/sunxi/board.c                    | 4 ++++
> >  2 files changed, 5 insertions(+)
> > 
> > diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h
> > b/arch/arm/include/asm/arch-sunxi/gpio.h index cdb7dbd5b8e5..de77bf638e21
> > 100644
> > --- a/arch/arm/include/asm/arch-sunxi/gpio.h
> > +++ b/arch/arm/include/asm/arch-sunxi/gpio.h
> > @@ -220,6 +220,7 @@ enum sunxi_gpio_number {
> > 
> >  #define SUN8I_A23_GPL_R_TWI	3
> >  #define SUN8I_GPL_R_UART	2
> >  #define SUN50I_GPL_R_TWI	2
> > 
> > +#define SUN50I_H616_GPL_R_TWI	3
> 
> The fact that I2C is at function 3 makes me suspicious that there is RSB
> at function 2. Have you checked if that is the case?

BSP Linux pinctrl has function 2 s_rsb0, so yes, that should be the case. 
However, it doesn't have RSB DT node anywhere. Datasheet mentions RSB only in 
CCU diagram, so no details anywhere. I didn't test it.

Best regards,
Jernej

> 
> Either way:
> 
> Reviewed-by: Samuel Holland <samuel@sholland.org>
> 
> >  #define SUN9I_GPN_R_RSB		3
> > 
> > diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> > index 54ff9bc92396..727e8320318f 100644
> > --- a/board/sunxi/board.c
> > +++ b/board/sunxi/board.c
> > @@ -196,6 +196,10 @@ void i2c_init_board(void)
> > 
> >  	clock_twi_onoff(5, 1);
> >  	sunxi_gpio_set_cfgpin(SUNXI_GPL(8), SUN50I_GPL_R_TWI);
> >  	sunxi_gpio_set_cfgpin(SUNXI_GPL(9), SUN50I_GPL_R_TWI);
> > 
> > +#elif CONFIG_MACH_SUN50I_H616
> > +	clock_twi_onoff(5, 1);
> > +	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN50I_H616_GPL_R_TWI);
> > +	sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN50I_H616_GPL_R_TWI);
> > 
> >  #else
> >  
> >  	clock_twi_onoff(5, 1);
> >  	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_H3_GPL_R_TWI);

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

* [linux-sunxi] [PATCH 11/17] sunxi: Add H616 DRAM support
  2021-01-04  2:39   ` [linux-sunxi] " Samuel Holland
@ 2021-01-04 18:39     ` Jernej Škrabec
  2021-01-05  3:14       ` Samuel Holland
  0 siblings, 1 reply; 48+ messages in thread
From: Jernej Škrabec @ 2021-01-04 18:39 UTC (permalink / raw)
  To: u-boot

Dne ponedeljek, 04. januar 2021 ob 03:39:52 CET je Samuel Holland napisal(a):
> On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> > Allwinner H616 supports many types of DRAM. Most notably it supports
> > LPDDR4. However, all commercially available boards at this time use
> > only DDR3, so this commit adds only DDR3 support.
> > 
> > Controller and MBUS are very similar to H6 but PHY is completely
> > unknown.
> > 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> > 
> >  arch/arm/include/asm/arch-sunxi/dram.h        |    2 +
> >  .../include/asm/arch-sunxi/dram_sun50i_h616.h |  159 +++
> >  arch/arm/mach-sunxi/Kconfig                   |   43 +
> >  arch/arm/mach-sunxi/Makefile                  |    2 +
> >  arch/arm/mach-sunxi/dram_sun50i_h616.c        | 1023 +++++++++++++++++
> >  arch/arm/mach-sunxi/dram_timings/Makefile     |    2 +
> >  .../mach-sunxi/dram_timings/h616_ddr3_1333.c  |   94 ++
> >  7 files changed, 1325 insertions(+)
> >  create mode 100644 arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
> >  create mode 100644 arch/arm/mach-sunxi/dram_sun50i_h616.c
> >  create mode 100644 arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
> > 
> > diff --git a/arch/arm/include/asm/arch-sunxi/dram.h
> > b/arch/arm/include/asm/arch-sunxi/dram.h index 8002b7efdc19..c3b3e1f512b2
> > 100644
> > --- a/arch/arm/include/asm/arch-sunxi/dram.h
> > +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> > @@ -29,6 +29,8 @@
> > 
> >  #include <asm/arch/dram_sun9i.h>
> >  #elif defined(CONFIG_MACH_SUN50I_H6)
> >  #include <asm/arch/dram_sun50i_h6.h>
> > 
> > +#elif defined(CONFIG_MACH_SUN50I_H616)
> > +#include <asm/arch/dram_sun50i_h616.h>
> > 
> >  #else
> >  #include <asm/arch/dram_sun4i.h>
> >  #endif
> > 
> > diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
> > b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h new file mode 100644
> > index 000000000000..5d105afd6110
> > --- /dev/null
> > +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
> > @@ -0,0 +1,159 @@
> > +/*
> > + * H616 dram controller register and constant defines
> > + *
> > + * (C) Copyright 2020  Jernej Skrabec <jernej.skrabec@siol.net>
> > + *
> > + * Based on H6 one, which is:
> > + * (C) Copyright 2017  Icenowy Zheng <icenowy@aosc.io>
> > + *
> > + * SPDX-License-Identifier:	GPL-2.0+
> > + */
> > +
> > +#ifndef _SUNXI_DRAM_SUN50I_H616_H
> > +#define _SUNXI_DRAM_SUN50I_H616_H
> > +
> > +#include <stdbool.h>
> > +#ifndef __ASSEMBLY__
> > +#include <linux/bitops.h>
> > +#endif
> > +
> > +enum sunxi_dram_type {
> > +	SUNXI_DRAM_TYPE_DDR3 = 3,
> > +	SUNXI_DRAM_TYPE_DDR4,
> > +	SUNXI_DRAM_TYPE_LPDDR3 = 7,
> > +	SUNXI_DRAM_TYPE_LPDDR4
> > +};
> > +
> > +/* MBUS part is largely the same as in H6, except for one special
> > register */ +struct sunxi_mctl_com_reg {
> > +	u32 cr;			/* 0x000 control register */
> > +	u8 reserved_0x004[4];	/* 0x004 */
> > +	u32 unk_0x008;		/* 0x008 */
> > +	u32 tmr;		/* 0x00c timer register */
> > +	u8 reserved_0x010[4];	/* 0x010 */
> > +	u32 unk_0x014;		/* 0x014 */
> > +	u8 reserved_0x018[8];	/* 0x018 */
> > +	u32 maer0;		/* 0x020 master enable register 0 */
> > +	u32 maer1;		/* 0x024 master enable register 1 */
> > +	u32 maer2;		/* 0x028 master enable register 2 */
> > +	u8 reserved_0x02c[468];	/* 0x02c */
> > +	u32 bwcr;		/* 0x200 bandwidth control register */
> > +	u8 reserved_0x204[12];	/* 0x204 */
> > +	/*
> > +	 * The last master configured by BSP libdram is at 0x49x, so the
> > +	 * size of this struct array is set to 41 (0x29) now.
> > +	 */
> > +	struct {
> > +		u32 cfg0;		/* 0x0 */
> > +		u32 cfg1;		/* 0x4 */
> > +		u8 reserved_0x8[8];	/* 0x8 */
> > +	} master[41];		/* 0x210 + index * 0x10 */
> > +	u8 reserved_0x4a0[96];	/* 0x4a0 */
> > +	u32 unk_0x500;		/* 0x500 */
> > +};
> > +check_member(sunxi_mctl_com_reg, unk_0x500, 0x500);
> > +
> > +/*
> > + * Controller registers seems to be the same or at least very similar
> > + * to those in H6.
> > + */
> > +struct sunxi_mctl_ctl_reg {
> > +	u32 mstr;		/* 0x000 */
> > +	u32 statr;		/* 0x004 unused */
> > +	u32 mstr1;		/* 0x008 unused */
> > +	u32 unk_0x00c;		/* 0x00c */
> 
> This is clken (and the same on H6). It is obvious when looking at the
> standby power-down sequence.

Where is that sequence? I mostly consulted H6 and Zynq docs where this 
register is not explained. I'll update it in next revision.

Best regards,
Jernej

> 
> > +	u32 mrctrl0;		/* 0x010 unused */
> > +	u32 mrctrl1;		/* 0x014 unused */
> > +	u32 mrstatr;		/* 0x018 unused */
> > +	u32 mrctrl2;		/* 0x01c unused */
> > +	u32 derateen;		/* 0x020 unused */
> > +	u32 derateint;		/* 0x024 unused */
> > +	u8 reserved_0x028[8];	/* 0x028 */
> > +	u32 pwrctl;		/* 0x030 unused */
> > +	u32 pwrtmg;		/* 0x034 unused */
> > +	u32 hwlpctl;		/* 0x038 unused */
> > +	u8 reserved_0x03c[20];	/* 0x03c */
> > +	u32 rfshctl0;		/* 0x050 unused */
> > +	u32 rfshctl1;		/* 0x054 unused */
> > +	u8 reserved_0x058[8];	/* 0x05c */
> > +	u32 rfshctl3;		/* 0x060 */
> > +	u32 rfshtmg;		/* 0x064 */
> > +	u8 reserved_0x068[104];	/* 0x068 */
> > +	u32 init[8];		/* 0x0d0 */
> > +	u32 dimmctl;		/* 0x0f0 unused */
> > +	u32 rankctl;		/* 0x0f4 */
> > +	u8 reserved_0x0f8[8];	/* 0x0f8 */
> > +	u32 dramtmg[17];	/* 0x100 */
> > +	u8 reserved_0x144[60];	/* 0x144 */
> > +	u32 zqctl[3];		/* 0x180 */
> > +	u32 zqstat;		/* 0x18c unused */
> > +	u32 dfitmg0;		/* 0x190 */
> > +	u32 dfitmg1;		/* 0x194 */
> > +	u32 dfilpcfg[2];	/* 0x198 unused */
> > +	u32 dfiupd[3];		/* 0x1a0 */
> > +	u32 reserved_0x1ac;	/* 0x1ac */
> > +	u32 dfimisc;		/* 0x1b0 */
> > +	u32 dfitmg2;		/* 0x1b4 unused */
> > +	u32 dfitmg3;		/* 0x1b8 unused */
> > +	u32 dfistat;		/* 0x1bc */
> > +	u32 dbictl;		/* 0x1c0 */
> > +	u8 reserved_0x1c4[60];	/* 0x1c4 */
> > +	u32 addrmap[12];	/* 0x200 */
> > +	u8 reserved_0x230[16];	/* 0x230 */
> > +	u32 odtcfg;		/* 0x240 */
> > +	u32 odtmap;		/* 0x244 */
> > +	u8 reserved_0x248[8];	/* 0x248 */
> > +	u32 sched[2];		/* 0x250 */
> > +	u8 reserved_0x258[180];	/* 0x258 */
> > +	u32 dbgcmd;		/* 0x30c unused */
> > +	u32 dbgstat;		/* 0x310 unused */
> > +	u8 reserved_0x314[12];	/* 0x314 */
> > +	u32 swctl;		/* 0x320 */
> > +	u32 swstat;		/* 0x324 */
> > +	u8 reserved_0x328[7768];/* 0x328 */
> > +	u32 unk_0x2180;		/* 0x2180 */
> > +	u8 reserved_0x2184[188];/* 0x2184 */
> > +	u32 unk_0x2240;		/* 0x2240 */
> > +	u8 reserved_0x2244[3900];/* 0x2244 */
> > +	u32 unk_0x3180;		/* 0x3180 */
> > +	u8 reserved_0x3184[188];/* 0x3184 */
> > +	u32 unk_0x3240;		/* 0x3240 */
> > +	u8 reserved_0x3244[3900];/* 0x3244 */
> > +	u32 unk_0x4180;		/* 0x4180 */
> > +	u8 reserved_0x4184[188];/* 0x4184 */
> > +	u32 unk_0x4240;		/* 0x4240 */
> > +};
> > +check_member(sunxi_mctl_ctl_reg, swstat, 0x324);
> > +check_member(sunxi_mctl_ctl_reg, unk_0x4240, 0x4240);
> > +
> > +#define MSTR_DEVICETYPE_DDR3	BIT(0)
> > +#define MSTR_DEVICETYPE_LPDDR2	BIT(2)
> > +#define MSTR_DEVICETYPE_LPDDR3	BIT(3)
> > +#define MSTR_DEVICETYPE_DDR4	BIT(4)
> > +#define MSTR_DEVICETYPE_MASK	GENMASK(5, 0)
> > +#define MSTR_2TMODE		BIT(10)
> > +#define MSTR_BUSWIDTH_FULL	(0 << 12)
> > +#define MSTR_BUSWIDTH_HALF	(1 << 12)
> > +#define MSTR_ACTIVE_RANKS(x)	(((x == 2) ? 3 : 1) << 24)
> > +#define MSTR_BURST_LENGTH(x)	(((x) >> 1) << 16)
> > +
> > +struct dram_para {
> > +	u32 clk;
> > +	enum sunxi_dram_type type;
> > +	u8 cols;
> > +	u8 rows;
> > +	u8 ranks;
> > +	u8 bus_full_width;
> > +};
> > +
> > +
> > +static inline int ns_to_t(int nanoseconds)
> > +{
> > +	const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
> > +
> > +	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
> > +}
> > +
> > +void mctl_set_timing_params(struct dram_para *para);
> > +
> > +#endif /* _SUNXI_DRAM_SUN50I_H616_H */
> > diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> > index 69ab670abf39..1a5497989f04 100644
> > --- a/arch/arm/mach-sunxi/Kconfig
> > +++ b/arch/arm/mach-sunxi/Kconfig
> > @@ -48,6 +48,46 @@ config DRAM_SUN50I_H6
> > 
> >  	  Select this dram controller driver for some sun50i platforms,
> >  	  like H6.
> > 
> > +config DRAM_SUN50I_H616
> > +	bool
> > +	help
> > +	  Select this dram controller driver for some sun50i platforms,
> > +	  like H616.
> > +
> > +if DRAM_SUN50I_H616
> > +config DRAM_SUN50I_H616_WRITE_LEVELING
> > +	bool "H616 DRAM write leveling"
> > +	---help---
> > +	  Select this when DRAM on your H616 board needs write leveling.
> > +
> > +config DRAM_SUN50I_H616_READ_CALIBRATION
> > +	bool"H616 DRAM read calibration"
> 
> Missing a space here.
> 
> > +	---help---
> > +	  Select this when DRAM on your H616 board needs read calibration.
> > +
> > +config DRAM_SUN50I_H616_READ_TRAINING
> > +	bool "H616 DRAM read training"
> > +	---help---
> > +	  Select this when DRAM on your H616 board needs read training.
> > +
> > +config DRAM_SUN50I_H616_WRITE_TRAINING
> > +	bool "H616 DRAM write training"
> > +	---help---
> > +	  Select this when DRAM on your H616 board needs write training.
> > +
> > +config DRAM_SUN50I_H616_BIT_DELAY_COMPENSATION
> > +	bool "H616 DRAM bit delay compensation"
> > +	---help---
> > +	  Select this when DRAM on your H616 board needs bit delay
> > +	  compensation.
> > +
> > +config DRAM_SUN50I_H616_UNKNOWN_FEATURE
> > +	bool "H616 DRAM unknown feature"
> > +	---help---
> > +	  Select this when DRAM on your H616 board needs this unknown
> > +	  feature.
> > +endif
> > +
> > 
> >  config SUN6I_P2WI
> >  
> >  	bool "Allwinner sun6i internal P2WI controller"
> >  	help
> > 
> > @@ -423,6 +463,7 @@ config DRAM_CLK
> > 
> >  		       MACH_SUN8I_V3S
> >  	
> >  	default 672 if MACH_SUN50I
> >  	default 744 if MACH_SUN50I_H6
> > 
> > +	default 720 if MACH_SUN50I_H616
> > 
> >  	---help---
> >  	Set the dram clock speed, valid range 240 - 480 (prior to sun9i),
> >  	must be a multiple of 24. For the sun9i (A80), the tested values
> > 
> > @@ -439,6 +480,7 @@ endif
> > 
> >  config DRAM_ZQ
> >  
> >  	int "sunxi dram zq value"
> > 
> > +	depends on !MACH_SUN50I_H616
> > 
> >  	default 123 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || \
> >  	
> >  		       MACH_SUN8I_A23 || MACH_SUN8I_A33 || 
MACH_SUN8I_A83T
> >  	
> >  	default 127 if MACH_SUN7I
> > 
> > @@ -456,6 +498,7 @@ config DRAM_ODT_EN
> > 
> >  	default y if MACH_SUN8I_R40
> >  	default y if MACH_SUN50I
> >  	default y if MACH_SUN50I_H6
> > 
> > +	default y if MACH_SUN50I_H616
> > 
> >  	---help---
> >  	Select this to enable dram odt (on die termination).
> > 
> > diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
> > index b8aca43d6630..3f081d92f379 100644
> > --- a/arch/arm/mach-sunxi/Makefile
> > +++ b/arch/arm/mach-sunxi/Makefile
> > @@ -40,4 +40,6 @@ obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_sunxi_dw.o
> > 
> >  obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_timings/
> >  obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_sun50i_h6.o
> >  obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_timings/
> > 
> > +obj-$(CONFIG_DRAM_SUN50I_H616)	+= dram_sun50i_h616.o
> > +obj-$(CONFIG_DRAM_SUN50I_H616)	+= dram_timings/
> > 
> >  endif
> > 
> > diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c
> > b/arch/arm/mach-sunxi/dram_sun50i_h616.c new file mode 100644
> > index 000000000000..0c86f54b8a73[...]

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

* [linux-sunxi] [PATCH 12/17] sunxi: Add support for H616 SoC
  2021-01-04  2:47   ` [linux-sunxi] " Samuel Holland
@ 2021-01-04 18:43     ` Jernej Škrabec
  0 siblings, 0 replies; 48+ messages in thread
From: Jernej Škrabec @ 2021-01-04 18:43 UTC (permalink / raw)
  To: u-boot

Dne ponedeljek, 04. januar 2021 ob 03:47:06 CET je Samuel Holland napisal(a):
> On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> > H616 is very similar to H6 so most of the infrastructure can be reused.
> > However, two big differences are that it doesn't have functional SRAM A2
> > which is usually used for TF-A and it doesn't have ARISC co-processor.
> > It also needs bigger SPL size - 48 KiB.
> > 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> > 
> >  arch/arm/dts/sunxi-u-boot.dtsi                  |  9 +++++++++
> >  arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h |  7 +++++++
> >  arch/arm/mach-sunxi/Kconfig                     | 11 ++++++++++-
> >  arch/arm/mach-sunxi/cpu_info.c                  |  2 ++
> >  drivers/power/Kconfig                           |  1 +
> >  include/configs/sunxi-common.h                  | 10 ++++++++++
> >  6 files changed, 39 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm/dts/sunxi-u-boot.dtsi
> > b/arch/arm/dts/sunxi-u-boot.dtsi index c77cf7cacf0c..7e8644f390a8 100644
> > --- a/arch/arm/dts/sunxi-u-boot.dtsi
> > +++ b/arch/arm/dts/sunxi-u-boot.dtsi
> > @@ -3,6 +3,9 @@
> > 
> >  #ifdef CONFIG_MACH_SUN50I_H6
> >  #define BL31_ADDR 0x104000
> >  #define  SCP_ADDR 0x114000
> > 
> > +#elif defined(CONFIG_MACH_SUN50I_H616)
> > +#define BL31_ADDR 0x40004000
> > +#define  SCP_ADDR 0x028000
> 
> There should be no SCP_ADDR if there is no SCP firmware.

Nice catch!

> 
> >  #else
> >  #define BL31_ADDR  0x44000
> >  #define  SCP_ADDR  0x50000
> > 
> > @@ -61,6 +64,7 @@
> > 
> >  					};
> >  				
> >  				};
> > 
> > +#ifndef CONFIG_MACH_SUN50I_H616
> > 
> >  				scp {
> >  				
> >  					description = "SCP 
firmware";
> >  					type = "firmware";
> > 
> > @@ -73,6 +77,7 @@
> > 
> >  						missing-msg 
= "scp-sunxi";
> >  					
> >  					};
> >  				
> >  				};
> > 
> > +#endif
> > 
> >  				@fdt-SEQ {
> >  				
> >  					description = "NAME";
> > 
> > @@ -87,7 +92,11 @@
> > 
> >  				@config-SEQ {
> >  				
> >  					description = "NAME";
> >  					firmware = "atf";
> > 
> > +#ifdef CONFIG_MACH_SUN50I_H616
> > +					loadables = "uboot";
> > +#else
> > 
> >  					loadables = "scp", 
"uboot";
> > 
> > +#endif
> > 
> >  					fdt = "fdt-SEQ";
> >  				
> >  				};
> >  			
> >  			};
> > 
> > diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
> > b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h index
> > 6392cb07b472..d9cf8ae04288 100644
> > --- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
> > +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
> > @@ -28,13 +28,20 @@
> > 
> >  #define SUNXI_GIC400_BASE		0x03020000
> >  #define SUNXI_IOMMU_BASE		0x030F0000
> > 
> > +#ifdef CONFIG_MACH_SUN50I_H6
> > 
> >  #define SUNXI_DRAM_COM_BASE		0x04002000
> >  #define SUNXI_DRAM_CTL0_BASE		0x04003000
> >  #define SUNXI_DRAM_PHY0_BASE		0x04005000
> > 
> > +#endif
> > 
> >  #define SUNXI_NFC_BASE			0x04011000
> >  #define SUNXI_MMC0_BASE			0x04020000
> >  #define SUNXI_MMC1_BASE			0x04021000
> >  #define SUNXI_MMC2_BASE			0x04022000
> > 
> > +#ifdef CONFIG_MACH_SUN50I_H616
> > +#define SUNXI_DRAM_COM_BASE		0x047FA000
> > +#define SUNXI_DRAM_CTL0_BASE		0x047FB000
> > +#define SUNXI_DRAM_PHY0_BASE		0x04800000
> > +#endif
> > 
> >  #define SUNXI_UART0_BASE		0x05000000
> >  #define SUNXI_UART1_BASE		0x05000400
> > 
> > diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> > index 1a5497989f04..859b30d74ceb 100644
> > --- a/arch/arm/mach-sunxi/Kconfig
> > +++ b/arch/arm/mach-sunxi/Kconfig
> > @@ -190,9 +190,10 @@ config MACH_SUNXI_H3_H5
> > 
> >  	select SUPPORT_SPL
> >  
> >  # TODO: try out A80's 8GiB DRAM space
> > 
> > +# TODO: H616 supports 4 GiB DRAM space
> > 
> >  config SUNXI_DRAM_MAX_SIZE
> >  
> >  	hex
> > 
> > -	default 0xC0000000 if MACH_SUN50I || MACH_SUN50I_H5 || 
MACH_SUN50I_H6
> > +	default 0xC0000000 if MACH_SUN50I || MACH_SUN50I_H5 || 
MACH_SUN50I_H6 ||
> > MACH_SUN50I_H616> 
> >  	default 0x80000000
> >  
> >  choice
> > 
> > @@ -354,6 +355,12 @@ config MACH_SUN50I_H6
> > 
> >  	select PHY_SUN4I_USB
> >  	select DRAM_SUN50I_H6
> > 
> > +config MACH_SUN50I_H616
> > +	bool "sun50i (Allwinner H616)"
> > +	select ARM64
> > +	select DRAM_SUN50I_H616
> > +	select SUN50I_GEN_H6
> > +
> > 
> >  endchoice
> >  
> >  # The sun8i SoCs share a lot, this helps to avoid a lot of "if A23 ||
> >  A33"
> > 
> > @@ -589,6 +596,7 @@ config SYS_CLK_FREQ
> > 
> >  	default 816000000 if MACH_SUN50I || MACH_SUN50I_H5
> >  	default 1008000000 if MACH_SUN8I
> >  	default 1008000000 if MACH_SUN9I
> > 
> > +	default 1008000000 if MACH_SUN50I_H616
> > 
> >  config SYS_CONFIG_NAME
> >  
> >  	default "sun4i" if MACH_SUN4I
> > 
> > @@ -599,6 +607,7 @@ config SYS_CONFIG_NAME
> > 
> >  	default "sun9i" if MACH_SUN9I
> >  	default "sun50i" if MACH_SUN50I
> >  	default "sun50i" if MACH_SUN50I_H6
> > 
> > +	default "sun50i" if MACH_SUN50I_H616
> > 
> >  config SYS_BOARD
> >  
> >  	default "sunxi"
> > 
> > diff --git a/arch/arm/mach-sunxi/cpu_info.c
> > b/arch/arm/mach-sunxi/cpu_info.c index 875e5a1a8a8e..ba33ef24300c 100644
> > --- a/arch/arm/mach-sunxi/cpu_info.c
> > +++ b/arch/arm/mach-sunxi/cpu_info.c
> > @@ -99,6 +99,8 @@ int print_cpuinfo(void)
> > 
> >  	puts("CPU:   Allwinner H5 (SUN50I)\n");
> >  
> >  #elif defined CONFIG_MACH_SUN50I_H6
> >  
> >  	puts("CPU:   Allwinner H6 (SUN50I)\n");
> > 
> > +#elif defined CONFIG_MACH_SUN50I_H616
> > +	puts("CPU:   Allwinner H616 (SUN50I)\n");
> > 
> >  #else
> >  #warning Please update cpu_info.c with correct CPU information
> >  
> >  	puts("CPU:   SUNXI Family\n");
> > 
> > diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> > index d17cf2d9112a..c5fbf1f832a9 100644
> > --- a/drivers/power/Kconfig
> > +++ b/drivers/power/Kconfig
> > @@ -13,6 +13,7 @@ choice
> > 
> >  	depends on ARCH_SUNXI
> >  	default AXP209_POWER if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
> >  	default AXP221_POWER if MACH_SUN6I || MACH_SUN8I_A23 || 
MACH_SUN8I_A33
> >  	|| MACH_SUN8I_R40> 
> > +	default AXP305_POWER if MACH_SUN50I_H616
> > 
> >  	default AXP818_POWER if MACH_SUN8I_A83T
> >  	default SUNXI_NO_PMIC if MACH_SUNXI_H3_H5 || MACH_SUN50I ||
> >  	MACH_SUN8I_V3S
> > 
> > diff --git a/include/configs/sunxi-common.h
> > b/include/configs/sunxi-common.h index 203cb10fbabc..6e8f547214d6 100644
> > --- a/include/configs/sunxi-common.h
> > +++ b/include/configs/sunxi-common.h
> > @@ -178,9 +178,14 @@
> > 
> >  #define LOW_LEVEL_SRAM_STACK		0x00018000
> >  #endif /* !CONFIG_ARM64 */
> >  #elif CONFIG_SUNXI_SRAM_ADDRESS == 0x20000
> > 
> > +#ifdef CONFIG_MACH_SUN50I_H616
> > +#define CONFIG_SPL_MAX_SIZE		0xbfa0		/* 48 KiB 
*/
> > +#define LOW_LEVEL_SRAM_STACK		0x58000
> > +#else
> > 
> >  #define CONFIG_SPL_MAX_SIZE		0x7fa0		/* 32 KiB 
*/
> >  /* end of SRAM A2 on H6 for now */
> >  #define LOW_LEVEL_SRAM_STACK		0x00118000
> > 
> > +#endif
> > 
> >  #else
> >  #define CONFIG_SPL_MAX_SIZE		0x5fa0		/* 24KB on 
sun4i/sun7i */
> >  #define LOW_LEVEL_SRAM_STACK		0x00008000	/* End of sram */
> > 
> > @@ -188,7 +193,12 @@
> > 
> >  #define CONFIG_SPL_STACK		LOW_LEVEL_SRAM_STACK
> > 
> > +/* H616 supports 48 KiB SPL */
> > +#ifdef CONFIG_MACH_SUN50I_H616
> > +#define CONFIG_SPL_PAD_TO		49152		/* decimal 
for 'dd' */
> 
> H616 supports much larger SPLs than 48 KiB, and CONFIG_SPL_PAD_TO
> enforces both a minimum and maximum size. So please leave
> CONFIG_SPL_PAD_TO undefined on the new platform (or for all
> SUN50I_GEN_H6, where the SPL size restriction was removed).

I thought padding is required for proper build. I'll test that.

Best regards,
Jernej

> 
> > +#else
> > 
> >  #define CONFIG_SPL_PAD_TO		32768		/* decimal 
for 'dd' */
> > 
> > +#endif
> > 
> >  /* I2C */
> 
> Cheers,
> Samuel

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

* [linux-sunxi] [PATCH 11/17] sunxi: Add H616 DRAM support
  2021-01-04 18:39     ` Jernej Škrabec
@ 2021-01-05  3:14       ` Samuel Holland
  0 siblings, 0 replies; 48+ messages in thread
From: Samuel Holland @ 2021-01-05  3:14 UTC (permalink / raw)
  To: u-boot

On 1/4/21 12:39 PM, Jernej ?krabec wrote:
> Dne ponedeljek, 04. januar 2021 ob 03:39:52 CET je Samuel Holland napisal(a):
>> On 1/3/21 3:26 AM, Jernej Skrabec wrote:
>>> Allwinner H616 supports many types of DRAM. Most notably it supports
>>> LPDDR4. However, all commercially available boards at this time use
>>> only DDR3, so this commit adds only DDR3 support.
>>>
>>> Controller and MBUS are very similar to H6 but PHY is completely
>>> unknown.
>>>
>>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>>> ---
>>>
>>>  arch/arm/include/asm/arch-sunxi/dram.h        |    2 +
>>>  .../include/asm/arch-sunxi/dram_sun50i_h616.h |  159 +++
>>>  arch/arm/mach-sunxi/Kconfig                   |   43 +
>>>  arch/arm/mach-sunxi/Makefile                  |    2 +
>>>  arch/arm/mach-sunxi/dram_sun50i_h616.c        | 1023 +++++++++++++++++
>>>  arch/arm/mach-sunxi/dram_timings/Makefile     |    2 +
>>>  .../mach-sunxi/dram_timings/h616_ddr3_1333.c  |   94 ++
>>>  7 files changed, 1325 insertions(+)
>>>  create mode 100644 arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
>>>  create mode 100644 arch/arm/mach-sunxi/dram_sun50i_h616.c
>>>  create mode 100644 arch/arm/mach-sunxi/dram_timings/h616_ddr3_1333.c
>>>
>>> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h
>>> b/arch/arm/include/asm/arch-sunxi/dram.h index 8002b7efdc19..c3b3e1f512b2
>>> 100644
>>> --- a/arch/arm/include/asm/arch-sunxi/dram.h
>>> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
>>> @@ -29,6 +29,8 @@
>>>
>>>  #include <asm/arch/dram_sun9i.h>
>>>  #elif defined(CONFIG_MACH_SUN50I_H6)
>>>  #include <asm/arch/dram_sun50i_h6.h>
>>>
>>> +#elif defined(CONFIG_MACH_SUN50I_H616)
>>> +#include <asm/arch/dram_sun50i_h616.h>
>>>
>>>  #else
>>>  #include <asm/arch/dram_sun4i.h>
>>>  #endif
>>>
>>> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
>>> b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h new file mode 100644
>>> index 000000000000..5d105afd6110
>>> --- /dev/null
>>> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
>>> @@ -0,0 +1,159 @@
>>> +/*
>>> + * H616 dram controller register and constant defines
>>> + *
>>> + * (C) Copyright 2020  Jernej Skrabec <jernej.skrabec@siol.net>
>>> + *
>>> + * Based on H6 one, which is:
>>> + * (C) Copyright 2017  Icenowy Zheng <icenowy@aosc.io>
>>> + *
>>> + * SPDX-License-Identifier:	GPL-2.0+
>>> + */
>>> +
>>> +#ifndef _SUNXI_DRAM_SUN50I_H616_H
>>> +#define _SUNXI_DRAM_SUN50I_H616_H
>>> +
>>> +#include <stdbool.h>
>>> +#ifndef __ASSEMBLY__
>>> +#include <linux/bitops.h>
>>> +#endif
>>> +
>>> +enum sunxi_dram_type {
>>> +	SUNXI_DRAM_TYPE_DDR3 = 3,
>>> +	SUNXI_DRAM_TYPE_DDR4,
>>> +	SUNXI_DRAM_TYPE_LPDDR3 = 7,
>>> +	SUNXI_DRAM_TYPE_LPDDR4
>>> +};
>>> +
>>> +/* MBUS part is largely the same as in H6, except for one special
>>> register */ +struct sunxi_mctl_com_reg {
>>> +	u32 cr;			/* 0x000 control register */
>>> +	u8 reserved_0x004[4];	/* 0x004 */
>>> +	u32 unk_0x008;		/* 0x008 */
>>> +	u32 tmr;		/* 0x00c timer register */
>>> +	u8 reserved_0x010[4];	/* 0x010 */
>>> +	u32 unk_0x014;		/* 0x014 */
>>> +	u8 reserved_0x018[8];	/* 0x018 */
>>> +	u32 maer0;		/* 0x020 master enable register 0 */
>>> +	u32 maer1;		/* 0x024 master enable register 1 */
>>> +	u32 maer2;		/* 0x028 master enable register 2 */
>>> +	u8 reserved_0x02c[468];	/* 0x02c */
>>> +	u32 bwcr;		/* 0x200 bandwidth control register */
>>> +	u8 reserved_0x204[12];	/* 0x204 */
>>> +	/*
>>> +	 * The last master configured by BSP libdram is at 0x49x, so the
>>> +	 * size of this struct array is set to 41 (0x29) now.
>>> +	 */
>>> +	struct {
>>> +		u32 cfg0;		/* 0x0 */
>>> +		u32 cfg1;		/* 0x4 */
>>> +		u8 reserved_0x8[8];	/* 0x8 */
>>> +	} master[41];		/* 0x210 + index * 0x10 */
>>> +	u8 reserved_0x4a0[96];	/* 0x4a0 */
>>> +	u32 unk_0x500;		/* 0x500 */
>>> +};
>>> +check_member(sunxi_mctl_com_reg, unk_0x500, 0x500);
>>> +
>>> +/*
>>> + * Controller registers seems to be the same or at least very similar
>>> + * to those in H6.
>>> + */
>>> +struct sunxi_mctl_ctl_reg {
>>> +	u32 mstr;		/* 0x000 */
>>> +	u32 statr;		/* 0x004 unused */
>>> +	u32 mstr1;		/* 0x008 unused */
>>> +	u32 unk_0x00c;		/* 0x00c */
>>
>> This is clken (and the same on H6). It is obvious when looking at the
>> standby power-down sequence.
> 
> Where is that sequence? I mostly consulted H6 and Zynq docs where this 
> register is not explained. I'll update it in next revision.

This is from the H6 ARISC firmware, which has a similar structure to earlier
generations with known registers.

Cheers,
Samuel

> Best regards,
> Jernej
> 
>>
>>> +	u32 mrctrl0;		/* 0x010 unused */
>>> +	u32 mrctrl1;		/* 0x014 unused */
>>> +	u32 mrstatr;		/* 0x018 unused */
>>> +	u32 mrctrl2;		/* 0x01c unused */
>>> +	u32 derateen;		/* 0x020 unused */
>>> +	u32 derateint;		/* 0x024 unused */
>>> +	u8 reserved_0x028[8];	/* 0x028 */
>>> +	u32 pwrctl;		/* 0x030 unused */
>>> +	u32 pwrtmg;		/* 0x034 unused */
>>> +	u32 hwlpctl;		/* 0x038 unused */
>>> +	u8 reserved_0x03c[20];	/* 0x03c */
>>> +	u32 rfshctl0;		/* 0x050 unused */
>>> +	u32 rfshctl1;		/* 0x054 unused */
>>> +	u8 reserved_0x058[8];	/* 0x05c */
>>> +	u32 rfshctl3;		/* 0x060 */
>>> +	u32 rfshtmg;		/* 0x064 */
>>> +	u8 reserved_0x068[104];	/* 0x068 */
>>> +	u32 init[8];		/* 0x0d0 */
>>> +	u32 dimmctl;		/* 0x0f0 unused */
>>> +	u32 rankctl;		/* 0x0f4 */
>>> +	u8 reserved_0x0f8[8];	/* 0x0f8 */
>>> +	u32 dramtmg[17];	/* 0x100 */
>>> +	u8 reserved_0x144[60];	/* 0x144 */
>>> +	u32 zqctl[3];		/* 0x180 */
>>> +	u32 zqstat;		/* 0x18c unused */
>>> +	u32 dfitmg0;		/* 0x190 */
>>> +	u32 dfitmg1;		/* 0x194 */
>>> +	u32 dfilpcfg[2];	/* 0x198 unused */
>>> +	u32 dfiupd[3];		/* 0x1a0 */
>>> +	u32 reserved_0x1ac;	/* 0x1ac */
>>> +	u32 dfimisc;		/* 0x1b0 */
>>> +	u32 dfitmg2;		/* 0x1b4 unused */
>>> +	u32 dfitmg3;		/* 0x1b8 unused */
>>> +	u32 dfistat;		/* 0x1bc */
>>> +	u32 dbictl;		/* 0x1c0 */
>>> +	u8 reserved_0x1c4[60];	/* 0x1c4 */
>>> +	u32 addrmap[12];	/* 0x200 */
>>> +	u8 reserved_0x230[16];	/* 0x230 */
>>> +	u32 odtcfg;		/* 0x240 */
>>> +	u32 odtmap;		/* 0x244 */
>>> +	u8 reserved_0x248[8];	/* 0x248 */
>>> +	u32 sched[2];		/* 0x250 */
>>> +	u8 reserved_0x258[180];	/* 0x258 */
>>> +	u32 dbgcmd;		/* 0x30c unused */
>>> +	u32 dbgstat;		/* 0x310 unused */
>>> +	u8 reserved_0x314[12];	/* 0x314 */
>>> +	u32 swctl;		/* 0x320 */
>>> +	u32 swstat;		/* 0x324 */
>>> +	u8 reserved_0x328[7768];/* 0x328 */
>>> +	u32 unk_0x2180;		/* 0x2180 */
>>> +	u8 reserved_0x2184[188];/* 0x2184 */
>>> +	u32 unk_0x2240;		/* 0x2240 */
>>> +	u8 reserved_0x2244[3900];/* 0x2244 */
>>> +	u32 unk_0x3180;		/* 0x3180 */
>>> +	u8 reserved_0x3184[188];/* 0x3184 */
>>> +	u32 unk_0x3240;		/* 0x3240 */
>>> +	u8 reserved_0x3244[3900];/* 0x3244 */
>>> +	u32 unk_0x4180;		/* 0x4180 */
>>> +	u8 reserved_0x4184[188];/* 0x4184 */
>>> +	u32 unk_0x4240;		/* 0x4240 */
>>> +};
>>> +check_member(sunxi_mctl_ctl_reg, swstat, 0x324);
>>> +check_member(sunxi_mctl_ctl_reg, unk_0x4240, 0x4240);
>>> +
>>> +#define MSTR_DEVICETYPE_DDR3	BIT(0)
>>> +#define MSTR_DEVICETYPE_LPDDR2	BIT(2)
>>> +#define MSTR_DEVICETYPE_LPDDR3	BIT(3)
>>> +#define MSTR_DEVICETYPE_DDR4	BIT(4)
>>> +#define MSTR_DEVICETYPE_MASK	GENMASK(5, 0)
>>> +#define MSTR_2TMODE		BIT(10)
>>> +#define MSTR_BUSWIDTH_FULL	(0 << 12)
>>> +#define MSTR_BUSWIDTH_HALF	(1 << 12)
>>> +#define MSTR_ACTIVE_RANKS(x)	(((x == 2) ? 3 : 1) << 24)
>>> +#define MSTR_BURST_LENGTH(x)	(((x) >> 1) << 16)
>>> +
>>> +struct dram_para {
>>> +	u32 clk;
>>> +	enum sunxi_dram_type type;
>>> +	u8 cols;
>>> +	u8 rows;
>>> +	u8 ranks;
>>> +	u8 bus_full_width;
>>> +};
>>> +
>>> +
>>> +static inline int ns_to_t(int nanoseconds)
>>> +{
>>> +	const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
>>> +
>>> +	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
>>> +}
>>> +
>>> +void mctl_set_timing_params(struct dram_para *para);
>>> +
>>> +#endif /* _SUNXI_DRAM_SUN50I_H616_H */
>>> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
>>> index 69ab670abf39..1a5497989f04 100644
>>> --- a/arch/arm/mach-sunxi/Kconfig
>>> +++ b/arch/arm/mach-sunxi/Kconfig
>>> @@ -48,6 +48,46 @@ config DRAM_SUN50I_H6
>>>
>>>  	  Select this dram controller driver for some sun50i platforms,
>>>  	  like H6.
>>>
>>> +config DRAM_SUN50I_H616
>>> +	bool
>>> +	help
>>> +	  Select this dram controller driver for some sun50i platforms,
>>> +	  like H616.
>>> +
>>> +if DRAM_SUN50I_H616
>>> +config DRAM_SUN50I_H616_WRITE_LEVELING
>>> +	bool "H616 DRAM write leveling"
>>> +	---help---
>>> +	  Select this when DRAM on your H616 board needs write leveling.
>>> +
>>> +config DRAM_SUN50I_H616_READ_CALIBRATION
>>> +	bool"H616 DRAM read calibration"
>>
>> Missing a space here.
>>
>>> +	---help---
>>> +	  Select this when DRAM on your H616 board needs read calibration.
>>> +
>>> +config DRAM_SUN50I_H616_READ_TRAINING
>>> +	bool "H616 DRAM read training"
>>> +	---help---
>>> +	  Select this when DRAM on your H616 board needs read training.
>>> +
>>> +config DRAM_SUN50I_H616_WRITE_TRAINING
>>> +	bool "H616 DRAM write training"
>>> +	---help---
>>> +	  Select this when DRAM on your H616 board needs write training.
>>> +
>>> +config DRAM_SUN50I_H616_BIT_DELAY_COMPENSATION
>>> +	bool "H616 DRAM bit delay compensation"
>>> +	---help---
>>> +	  Select this when DRAM on your H616 board needs bit delay
>>> +	  compensation.
>>> +
>>> +config DRAM_SUN50I_H616_UNKNOWN_FEATURE
>>> +	bool "H616 DRAM unknown feature"
>>> +	---help---
>>> +	  Select this when DRAM on your H616 board needs this unknown
>>> +	  feature.
>>> +endif
>>> +
>>>
>>>  config SUN6I_P2WI
>>>  
>>>  	bool "Allwinner sun6i internal P2WI controller"
>>>  	help
>>>
>>> @@ -423,6 +463,7 @@ config DRAM_CLK
>>>
>>>  		       MACH_SUN8I_V3S
>>>  	
>>>  	default 672 if MACH_SUN50I
>>>  	default 744 if MACH_SUN50I_H6
>>>
>>> +	default 720 if MACH_SUN50I_H616
>>>
>>>  	---help---
>>>  	Set the dram clock speed, valid range 240 - 480 (prior to sun9i),
>>>  	must be a multiple of 24. For the sun9i (A80), the tested values
>>>
>>> @@ -439,6 +480,7 @@ endif
>>>
>>>  config DRAM_ZQ
>>>  
>>>  	int "sunxi dram zq value"
>>>
>>> +	depends on !MACH_SUN50I_H616
>>>
>>>  	default 123 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || \
>>>  	
>>>  		       MACH_SUN8I_A23 || MACH_SUN8I_A33 || 
> MACH_SUN8I_A83T
>>>  	
>>>  	default 127 if MACH_SUN7I
>>>
>>> @@ -456,6 +498,7 @@ config DRAM_ODT_EN
>>>
>>>  	default y if MACH_SUN8I_R40
>>>  	default y if MACH_SUN50I
>>>  	default y if MACH_SUN50I_H6
>>>
>>> +	default y if MACH_SUN50I_H616
>>>
>>>  	---help---
>>>  	Select this to enable dram odt (on die termination).
>>>
>>> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
>>> index b8aca43d6630..3f081d92f379 100644
>>> --- a/arch/arm/mach-sunxi/Makefile
>>> +++ b/arch/arm/mach-sunxi/Makefile
>>> @@ -40,4 +40,6 @@ obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_sunxi_dw.o
>>>
>>>  obj-$(CONFIG_SUNXI_DRAM_DW)	+= dram_timings/
>>>  obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_sun50i_h6.o
>>>  obj-$(CONFIG_DRAM_SUN50I_H6)	+= dram_timings/
>>>
>>> +obj-$(CONFIG_DRAM_SUN50I_H616)	+= dram_sun50i_h616.o
>>> +obj-$(CONFIG_DRAM_SUN50I_H616)	+= dram_timings/
>>>
>>>  endif
>>>
>>> diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c
>>> b/arch/arm/mach-sunxi/dram_sun50i_h616.c new file mode 100644
>>> index 000000000000..0c86f54b8a73[...]

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

* [PATCH 01/17] sunxi: Add support for AXP305 PMIC
  2021-01-03  9:26 ` [PATCH 01/17] sunxi: Add support for AXP305 PMIC Jernej Skrabec
@ 2021-01-05 22:36   ` Jaehoon Chung
  2021-01-06 10:11     ` André Przywara
  2021-01-11  0:02   ` André Przywara
  1 sibling, 1 reply; 48+ messages in thread
From: Jaehoon Chung @ 2021-01-05 22:36 UTC (permalink / raw)
  To: u-boot

Hi Jernej

On 1/3/21 6:26 PM, Jernej Skrabec wrote:
> This PMIC can be found on H616 boards and it's very similar to AXP805
> and AXP806.

Is there any plan to cleanup codes?

> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  arch/arm/mach-sunxi/pmic_bus.c |  6 +++
>  board/sunxi/board.c            | 10 +++--
>  drivers/power/Kconfig          | 13 +++++-
>  drivers/power/Makefile         |  1 +
>  drivers/power/axp305.c         | 80 ++++++++++++++++++++++++++++++++++
>  include/axp305.h               | 17 ++++++++
>  include/axp_pmic.h             |  3 ++
>  7 files changed, 126 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/power/axp305.c
>  create mode 100644 include/axp305.h
> 
> diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
> index dea42de833f1..0394ce856448 100644
> --- a/arch/arm/mach-sunxi/pmic_bus.c
> +++ b/arch/arm/mach-sunxi/pmic_bus.c
> @@ -18,6 +18,8 @@
>  
>  #define AXP209_I2C_ADDR			0x34
>  
> +#define AXP305_I2C_ADDR			0x36
> +
>  #define AXP221_CHIP_ADDR		0x68
>  #define AXP221_CTRL_ADDR		0x3e
>  #define AXP221_INIT_DATA		0x3e
> @@ -64,6 +66,8 @@ int pmic_bus_read(u8 reg, u8 *data)
>  	return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1);
>  #elif defined CONFIG_AXP209_POWER
>  	return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
> +#elif defined CONFIG_AXP305_POWER
> +	return i2c_read(AXP305_I2C_ADDR, reg, 1, data, 1);
>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>  # ifdef CONFIG_MACH_SUN6I
>  	return p2wi_read(reg, data);
> @@ -81,6 +85,8 @@ int pmic_bus_write(u8 reg, u8 data)
>  	return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1);
>  #elif defined CONFIG_AXP209_POWER
>  	return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
> +#elif defined CONFIG_AXP305_POWER
> +	return i2c_write(AXP305_I2C_ADDR, reg, 1, &data, 1);
>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>  # ifdef CONFIG_MACH_SUN6I
>  	return p2wi_write(reg, data);
> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> index 708a27ed78e9..54ff9bc92396 100644
> --- a/board/sunxi/board.c
> +++ b/board/sunxi/board.c
> @@ -634,16 +634,18 @@ void sunxi_board_init(void)
>  #endif
>  
>  #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
> -	defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
> -	defined CONFIG_AXP818_POWER
> +	defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
> +	defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>  	power_failed = axp_init();
>  
>  #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
>  	defined CONFIG_AXP818_POWER
>  	power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
>  #endif
> +#if !defined(CONFIG_AXP305_POWER)
>  	power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
>  	power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
> +#endif
>  #if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
>  	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
>  #endif
> @@ -656,8 +658,10 @@ void sunxi_board_init(void)
>  	defined CONFIG_AXP818_POWER
>  	power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
>  #endif
> +#if !defined(CONFIG_AXP305_POWER)
>  	power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
> -#if !defined(CONFIG_AXP152_POWER)
> +#endif
> +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER)
>  	power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
>  #endif
>  #ifdef CONFIG_AXP209_POWER
> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> index 02050f6f3569..d17cf2d9112a 100644
> --- a/drivers/power/Kconfig
> +++ b/drivers/power/Kconfig
> @@ -48,6 +48,15 @@ config AXP221_POWER
>  	Select this to enable support for the axp221/axp223 pmic found on most
>  	A23 and A31 boards.
>  
> +config AXP305_POWER
> +	bool "axp305 pmic support"
> +	depends on MACH_SUN50I_H616
> +	select AXP_PMIC_BUS
> +	select CMD_POWEROFF
> +	---help---
> +	Select this to enable support for the axp305 pmic found on most
> +	H616 boards.
> +
>  config AXP809_POWER
>  	bool "axp809 pmic support"
>  	depends on MACH_SUN9I
> @@ -127,11 +136,12 @@ config AXP_DCDC3_VOLT
>  
>  config AXP_DCDC4_VOLT
>  	int "axp pmic dcdc4 voltage"
> -	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
> +	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP305_POWER
>  	default 1250 if AXP152_POWER
>  	default 1200 if MACH_SUN6I
>  	default 0 if MACH_SUN8I
>  	default 900 if MACH_SUN9I
> +	default 1500 if AXP305_POWER
>  	---help---
>  	Set the voltage (mV) to program the axp pmic dcdc4 at, set to 0 to
>  	disable dcdc4.
> @@ -140,6 +150,7 @@ config AXP_DCDC4_VOLT
>  	On A23 / A33 boards dcdc4 is unused and should be disabled.
>  	On A80 boards dcdc4 powers VDD-SYS, HDMI, USB OTG and should be 0.9V.
>  	On A83T boards dcdc4 is used for VDD-GPU.
> +	On H616 boards dcdcd is used for VCC-DRAM.
>  
>  config AXP_DCDC5_VOLT
>  	int "axp pmic dcdc5 voltage"
> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
> index 2dcc7bb99d02..0bef06920a7d 100644
> --- a/drivers/power/Makefile
> +++ b/drivers/power/Makefile
> @@ -6,6 +6,7 @@
>  obj-$(CONFIG_AXP152_POWER)	+= axp152.o
>  obj-$(CONFIG_AXP209_POWER)	+= axp209.o
>  obj-$(CONFIG_AXP221_POWER)	+= axp221.o
> +obj-$(CONFIG_AXP305_POWER)	+= axp305.o
>  obj-$(CONFIG_AXP809_POWER)	+= axp809.o
>  obj-$(CONFIG_AXP818_POWER)	+= axp818.o
>  obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
> diff --git a/drivers/power/axp305.c b/drivers/power/axp305.c
> new file mode 100644
> index 000000000000..f620798bb1d7
> --- /dev/null
> +++ b/drivers/power/axp305.c
> @@ -0,0 +1,80 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * AXP305 driver
> + *
> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
> + *
> + * Based on axp221.c
> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
> + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <errno.h>
> +#include <asm/arch/pmic_bus.h>
> +#include <axp_pmic.h>
> +
> +static u8 axp305_mvolt_to_cfg(int mvolt, int min, int max, int div)
> +{
> +	if (mvolt < min)
> +		mvolt = min;
> +	else if (mvolt > max)
> +		mvolt = max;
> +
> +	return  (mvolt - min) / div;
> +}
> +
> +int axp_set_dcdc4(unsigned int mvolt)
> +{
> +	int ret;

Initialized ret value to 0.

> +	u8 cfg;
> +
> +	if (mvolt >= 1600)
> +		cfg = 46 + axp305_mvolt_to_cfg(mvolt, 1600, 3300, 100);

Could you use macro instead of 46 (magic code)?

> +	else
> +		cfg = axp305_mvolt_to_cfg(mvolt, 600, 1500, 20);
> +
> +	if (mvolt == 0)
> +		return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1,
> +					AXP305_OUTPUT_CTRL1_DCDCD_EN);
> +
> +	ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg);
> +	if (ret)
> +		return ret;
> +
> +	return pmic_bus_setbits(AXP305_OUTPUT_CTRL1,
> +				AXP305_OUTPUT_CTRL1_DCDCD_EN);
> +}
> +
> +int axp_init(void)
> +{
> +	u8 axp_chip_id;
> +	int ret;
> +
> +	ret = pmic_bus_init();
> +	if (ret)
> +		return ret;
> +
> +	ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id);
> +	if (ret)
> +		return ret;
> +
> +	if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x40)

Ditto, use macro instead of 0x40. 

> +		return -ENODEV;
> +
> +	return ret;
> +}
> +
> +#ifndef CONFIG_PSCI_RESET
> +int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +	pmic_bus_write(AXP305_SHUTDOWN, AXP305_POWEROFF);
> +
> +	/* infinite loop during shutdown */
> +	while (1) {}
> +
> +	/* not reached */
> +	return 0;
> +}
> +#endif
> diff --git a/include/axp305.h b/include/axp305.h
> new file mode 100644
> index 000000000000..225c5040a322
> --- /dev/null
> +++ b/include/axp305.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
> + */
> +
> +enum axp305_reg {
> +	AXP305_CHIP_VERSION = 0x3,
> +	AXP305_OUTPUT_CTRL1 = 0x10,
> +	AXP305_DCDCD_VOLTAGE = 0x15,
> +	AXP305_SHUTDOWN = 0x32,
> +};
> +
> +#define AXP305_CHIP_VERSION_MASK	0xcf
> +
> +#define AXP305_OUTPUT_CTRL1_DCDCD_EN	(1 << 3)
> +
> +#define AXP305_POWEROFF			(1 << 7)
> diff --git a/include/axp_pmic.h b/include/axp_pmic.h
> index 10091d0bb278..405044c3a32f 100644
> --- a/include/axp_pmic.h
> +++ b/include/axp_pmic.h
> @@ -15,6 +15,9 @@
>  #ifdef CONFIG_AXP221_POWER
>  #include <axp221.h>
>  #endif
> +#ifdef CONFIG_AXP305_POWER
> +#include <axp305.h>
> +#endif
>  #ifdef CONFIG_AXP809_POWER
>  #include <axp809.h>
>  #endif
> 

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

* [PATCH 01/17] sunxi: Add support for AXP305 PMIC
  2021-01-05 22:36   ` Jaehoon Chung
@ 2021-01-06 10:11     ` André Przywara
  2021-01-06 23:33       ` Jaehoon Chung
  0 siblings, 1 reply; 48+ messages in thread
From: André Przywara @ 2021-01-06 10:11 UTC (permalink / raw)
  To: u-boot

On 05/01/2021 22:36, Jaehoon Chung wrote:

Hi,

thanks for having a look!

> Hi Jernej
> 
> On 1/3/21 6:26 PM, Jernej Skrabec wrote:
>> This PMIC can be found on H616 boards and it's very similar to AXP805
>> and AXP806.
> 
> Is there any plan to cleanup codes?

There is no support for either of these, we use the PMICs only in
Trusted Firmware or Linux. So nothing to consolidate, yet. This might
change in the future, and then of course we will use a common code base.

> 
>>
>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>> ---
>>  arch/arm/mach-sunxi/pmic_bus.c |  6 +++
>>  board/sunxi/board.c            | 10 +++--
>>  drivers/power/Kconfig          | 13 +++++-
>>  drivers/power/Makefile         |  1 +
>>  drivers/power/axp305.c         | 80 ++++++++++++++++++++++++++++++++++
>>  include/axp305.h               | 17 ++++++++
>>  include/axp_pmic.h             |  3 ++
>>  7 files changed, 126 insertions(+), 4 deletions(-)
>>  create mode 100644 drivers/power/axp305.c
>>  create mode 100644 include/axp305.h
>>
>> diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
>> index dea42de833f1..0394ce856448 100644
>> --- a/arch/arm/mach-sunxi/pmic_bus.c
>> +++ b/arch/arm/mach-sunxi/pmic_bus.c
>> @@ -18,6 +18,8 @@
>>  
>>  #define AXP209_I2C_ADDR			0x34
>>  
>> +#define AXP305_I2C_ADDR			0x36
>> +
>>  #define AXP221_CHIP_ADDR		0x68
>>  #define AXP221_CTRL_ADDR		0x3e
>>  #define AXP221_INIT_DATA		0x3e
>> @@ -64,6 +66,8 @@ int pmic_bus_read(u8 reg, u8 *data)
>>  	return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1);
>>  #elif defined CONFIG_AXP209_POWER
>>  	return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
>> +#elif defined CONFIG_AXP305_POWER
>> +	return i2c_read(AXP305_I2C_ADDR, reg, 1, data, 1);
>>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>  # ifdef CONFIG_MACH_SUN6I
>>  	return p2wi_read(reg, data);
>> @@ -81,6 +85,8 @@ int pmic_bus_write(u8 reg, u8 data)
>>  	return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1);
>>  #elif defined CONFIG_AXP209_POWER
>>  	return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
>> +#elif defined CONFIG_AXP305_POWER
>> +	return i2c_write(AXP305_I2C_ADDR, reg, 1, &data, 1);
>>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>  # ifdef CONFIG_MACH_SUN6I
>>  	return p2wi_write(reg, data);
>> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
>> index 708a27ed78e9..54ff9bc92396 100644
>> --- a/board/sunxi/board.c
>> +++ b/board/sunxi/board.c
>> @@ -634,16 +634,18 @@ void sunxi_board_init(void)
>>  #endif
>>  
>>  #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
>> -	defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
>> -	defined CONFIG_AXP818_POWER
>> +	defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
>> +	defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>  	power_failed = axp_init();
>>  
>>  #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
>>  	defined CONFIG_AXP818_POWER
>>  	power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
>>  #endif
>> +#if !defined(CONFIG_AXP305_POWER)
>>  	power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
>>  	power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
>> +#endif
>>  #if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
>>  	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
>>  #endif
>> @@ -656,8 +658,10 @@ void sunxi_board_init(void)
>>  	defined CONFIG_AXP818_POWER
>>  	power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
>>  #endif
>> +#if !defined(CONFIG_AXP305_POWER)
>>  	power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
>> -#if !defined(CONFIG_AXP152_POWER)
>> +#endif
>> +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER)
>>  	power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
>>  #endif
>>  #ifdef CONFIG_AXP209_POWER
>> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
>> index 02050f6f3569..d17cf2d9112a 100644
>> --- a/drivers/power/Kconfig
>> +++ b/drivers/power/Kconfig
>> @@ -48,6 +48,15 @@ config AXP221_POWER
>>  	Select this to enable support for the axp221/axp223 pmic found on most
>>  	A23 and A31 boards.
>>  
>> +config AXP305_POWER
>> +	bool "axp305 pmic support"
>> +	depends on MACH_SUN50I_H616
>> +	select AXP_PMIC_BUS
>> +	select CMD_POWEROFF
>> +	---help---
>> +	Select this to enable support for the axp305 pmic found on most
>> +	H616 boards.
>> +
>>  config AXP809_POWER
>>  	bool "axp809 pmic support"
>>  	depends on MACH_SUN9I
>> @@ -127,11 +136,12 @@ config AXP_DCDC3_VOLT
>>  
>>  config AXP_DCDC4_VOLT
>>  	int "axp pmic dcdc4 voltage"
>> -	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
>> +	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP305_POWER
>>  	default 1250 if AXP152_POWER
>>  	default 1200 if MACH_SUN6I
>>  	default 0 if MACH_SUN8I
>>  	default 900 if MACH_SUN9I
>> +	default 1500 if AXP305_POWER
>>  	---help---
>>  	Set the voltage (mV) to program the axp pmic dcdc4 at, set to 0 to
>>  	disable dcdc4.
>> @@ -140,6 +150,7 @@ config AXP_DCDC4_VOLT
>>  	On A23 / A33 boards dcdc4 is unused and should be disabled.
>>  	On A80 boards dcdc4 powers VDD-SYS, HDMI, USB OTG and should be 0.9V.
>>  	On A83T boards dcdc4 is used for VDD-GPU.
>> +	On H616 boards dcdcd is used for VCC-DRAM.
>>  
>>  config AXP_DCDC5_VOLT
>>  	int "axp pmic dcdc5 voltage"
>> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
>> index 2dcc7bb99d02..0bef06920a7d 100644
>> --- a/drivers/power/Makefile
>> +++ b/drivers/power/Makefile
>> @@ -6,6 +6,7 @@
>>  obj-$(CONFIG_AXP152_POWER)	+= axp152.o
>>  obj-$(CONFIG_AXP209_POWER)	+= axp209.o
>>  obj-$(CONFIG_AXP221_POWER)	+= axp221.o
>> +obj-$(CONFIG_AXP305_POWER)	+= axp305.o
>>  obj-$(CONFIG_AXP809_POWER)	+= axp809.o
>>  obj-$(CONFIG_AXP818_POWER)	+= axp818.o
>>  obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
>> diff --git a/drivers/power/axp305.c b/drivers/power/axp305.c
>> new file mode 100644
>> index 000000000000..f620798bb1d7
>> --- /dev/null
>> +++ b/drivers/power/axp305.c
>> @@ -0,0 +1,80 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * AXP305 driver
>> + *
>> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
>> + *
>> + * Based on axp221.c
>> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
>> + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
>> + */
>> +
>> +#include <common.h>
>> +#include <command.h>
>> +#include <errno.h>
>> +#include <asm/arch/pmic_bus.h>
>> +#include <axp_pmic.h>
>> +
>> +static u8 axp305_mvolt_to_cfg(int mvolt, int min, int max, int div)
>> +{
>> +	if (mvolt < min)
>> +		mvolt = min;
>> +	else if (mvolt > max)
>> +		mvolt = max;
>> +
>> +	return  (mvolt - min) / div;
>> +}
>> +
>> +int axp_set_dcdc4(unsigned int mvolt)
>> +{
>> +	int ret;
> 
> Initialized ret value to 0.

Why? We set it unconditionally below, so initialising it here would be
pointless and might actually be warned upon by astute compilers.

> 
>> +	u8 cfg;
>> +
>> +	if (mvolt >= 1600)
>> +		cfg = 46 + axp305_mvolt_to_cfg(mvolt, 1600, 3300, 100);
> 
> Could you use macro instead of 46 (magic code)?
> 
>> +	else
>> +		cfg = axp305_mvolt_to_cfg(mvolt, 600, 1500, 20);
>> +
>> +	if (mvolt == 0)
>> +		return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1,
>> +					AXP305_OUTPUT_CTRL1_DCDCD_EN);
>> +
>> +	ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return pmic_bus_setbits(AXP305_OUTPUT_CTRL1,
>> +				AXP305_OUTPUT_CTRL1_DCDCD_EN);
>> +}
>> +
>> +int axp_init(void)
>> +{
>> +	u8 axp_chip_id;
>> +	int ret;
>> +
>> +	ret = pmic_bus_init();
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x40)
> 
> Ditto, use macro instead of 0x40. 

Not sure a macro is too useful here. I think the statement is pretty
clear in that this must be the chip version, which is given as this
value in the manual.

Cheers,
Andre

>> +		return -ENODEV;
>> +
>> +	return ret;
>> +}
>> +
>> +#ifndef CONFIG_PSCI_RESET
>> +int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>> +{
>> +	pmic_bus_write(AXP305_SHUTDOWN, AXP305_POWEROFF);
>> +
>> +	/* infinite loop during shutdown */
>> +	while (1) {}
>> +
>> +	/* not reached */
>> +	return 0;
>> +}
>> +#endif
>> diff --git a/include/axp305.h b/include/axp305.h
>> new file mode 100644
>> index 000000000000..225c5040a322
>> --- /dev/null
>> +++ b/include/axp305.h
>> @@ -0,0 +1,17 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
>> + */
>> +
>> +enum axp305_reg {
>> +	AXP305_CHIP_VERSION = 0x3,
>> +	AXP305_OUTPUT_CTRL1 = 0x10,
>> +	AXP305_DCDCD_VOLTAGE = 0x15,
>> +	AXP305_SHUTDOWN = 0x32,
>> +};
>> +
>> +#define AXP305_CHIP_VERSION_MASK	0xcf
>> +
>> +#define AXP305_OUTPUT_CTRL1_DCDCD_EN	(1 << 3)
>> +
>> +#define AXP305_POWEROFF			(1 << 7)
>> diff --git a/include/axp_pmic.h b/include/axp_pmic.h
>> index 10091d0bb278..405044c3a32f 100644
>> --- a/include/axp_pmic.h
>> +++ b/include/axp_pmic.h
>> @@ -15,6 +15,9 @@
>>  #ifdef CONFIG_AXP221_POWER
>>  #include <axp221.h>
>>  #endif
>> +#ifdef CONFIG_AXP305_POWER
>> +#include <axp305.h>
>> +#endif
>>  #ifdef CONFIG_AXP809_POWER
>>  #include <axp809.h>
>>  #endif
>>
> 

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

* [PATCH 01/17] sunxi: Add support for AXP305 PMIC
  2021-01-06 10:11     ` André Przywara
@ 2021-01-06 23:33       ` Jaehoon Chung
  2021-01-07  9:49         ` André Przywara
  0 siblings, 1 reply; 48+ messages in thread
From: Jaehoon Chung @ 2021-01-06 23:33 UTC (permalink / raw)
  To: u-boot

On 1/6/21 7:11 PM, Andr? Przywara wrote:
> On 05/01/2021 22:36, Jaehoon Chung wrote:
> 
> Hi,
> 
> thanks for having a look!
> 
>> Hi Jernej
>>
>> On 1/3/21 6:26 PM, Jernej Skrabec wrote:
>>> This PMIC can be found on H616 boards and it's very similar to AXP805
>>> and AXP806.
>>
>> Is there any plan to cleanup codes?
> 
> There is no support for either of these, we use the PMICs only in
> Trusted Firmware or Linux. So nothing to consolidate, yet. This might
> change in the future, and then of course we will use a common code base.
> 
>>
>>>
>>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>>> ---
>>>  arch/arm/mach-sunxi/pmic_bus.c |  6 +++
>>>  board/sunxi/board.c            | 10 +++--
>>>  drivers/power/Kconfig          | 13 +++++-
>>>  drivers/power/Makefile         |  1 +
>>>  drivers/power/axp305.c         | 80 ++++++++++++++++++++++++++++++++++
>>>  include/axp305.h               | 17 ++++++++
>>>  include/axp_pmic.h             |  3 ++
>>>  7 files changed, 126 insertions(+), 4 deletions(-)
>>>  create mode 100644 drivers/power/axp305.c
>>>  create mode 100644 include/axp305.h
>>>
>>> diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
>>> index dea42de833f1..0394ce856448 100644
>>> --- a/arch/arm/mach-sunxi/pmic_bus.c
>>> +++ b/arch/arm/mach-sunxi/pmic_bus.c
>>> @@ -18,6 +18,8 @@
>>>  
>>>  #define AXP209_I2C_ADDR			0x34
>>>  
>>> +#define AXP305_I2C_ADDR			0x36
>>> +
>>>  #define AXP221_CHIP_ADDR		0x68
>>>  #define AXP221_CTRL_ADDR		0x3e
>>>  #define AXP221_INIT_DATA		0x3e
>>> @@ -64,6 +66,8 @@ int pmic_bus_read(u8 reg, u8 *data)
>>>  	return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1);
>>>  #elif defined CONFIG_AXP209_POWER
>>>  	return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
>>> +#elif defined CONFIG_AXP305_POWER
>>> +	return i2c_read(AXP305_I2C_ADDR, reg, 1, data, 1);
>>>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>>  # ifdef CONFIG_MACH_SUN6I
>>>  	return p2wi_read(reg, data);
>>> @@ -81,6 +85,8 @@ int pmic_bus_write(u8 reg, u8 data)
>>>  	return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1);
>>>  #elif defined CONFIG_AXP209_POWER
>>>  	return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
>>> +#elif defined CONFIG_AXP305_POWER
>>> +	return i2c_write(AXP305_I2C_ADDR, reg, 1, &data, 1);
>>>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>>  # ifdef CONFIG_MACH_SUN6I
>>>  	return p2wi_write(reg, data);
>>> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
>>> index 708a27ed78e9..54ff9bc92396 100644
>>> --- a/board/sunxi/board.c
>>> +++ b/board/sunxi/board.c
>>> @@ -634,16 +634,18 @@ void sunxi_board_init(void)
>>>  #endif
>>>  
>>>  #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
>>> -	defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
>>> -	defined CONFIG_AXP818_POWER
>>> +	defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
>>> +	defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>>  	power_failed = axp_init();
>>>  
>>>  #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
>>>  	defined CONFIG_AXP818_POWER
>>>  	power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
>>>  #endif
>>> +#if !defined(CONFIG_AXP305_POWER)
>>>  	power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
>>>  	power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
>>> +#endif
>>>  #if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
>>>  	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
>>>  #endif
>>> @@ -656,8 +658,10 @@ void sunxi_board_init(void)
>>>  	defined CONFIG_AXP818_POWER
>>>  	power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
>>>  #endif
>>> +#if !defined(CONFIG_AXP305_POWER)
>>>  	power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
>>> -#if !defined(CONFIG_AXP152_POWER)
>>> +#endif
>>> +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER)
>>>  	power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
>>>  #endif
>>>  #ifdef CONFIG_AXP209_POWER
>>> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
>>> index 02050f6f3569..d17cf2d9112a 100644
>>> --- a/drivers/power/Kconfig
>>> +++ b/drivers/power/Kconfig
>>> @@ -48,6 +48,15 @@ config AXP221_POWER
>>>  	Select this to enable support for the axp221/axp223 pmic found on most
>>>  	A23 and A31 boards.
>>>  
>>> +config AXP305_POWER
>>> +	bool "axp305 pmic support"
>>> +	depends on MACH_SUN50I_H616
>>> +	select AXP_PMIC_BUS
>>> +	select CMD_POWEROFF
>>> +	---help---
>>> +	Select this to enable support for the axp305 pmic found on most
>>> +	H616 boards.
>>> +
>>>  config AXP809_POWER
>>>  	bool "axp809 pmic support"
>>>  	depends on MACH_SUN9I
>>> @@ -127,11 +136,12 @@ config AXP_DCDC3_VOLT
>>>  
>>>  config AXP_DCDC4_VOLT
>>>  	int "axp pmic dcdc4 voltage"
>>> -	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
>>> +	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP305_POWER
>>>  	default 1250 if AXP152_POWER
>>>  	default 1200 if MACH_SUN6I
>>>  	default 0 if MACH_SUN8I
>>>  	default 900 if MACH_SUN9I
>>> +	default 1500 if AXP305_POWER
>>>  	---help---
>>>  	Set the voltage (mV) to program the axp pmic dcdc4 at, set to 0 to
>>>  	disable dcdc4.
>>> @@ -140,6 +150,7 @@ config AXP_DCDC4_VOLT
>>>  	On A23 / A33 boards dcdc4 is unused and should be disabled.
>>>  	On A80 boards dcdc4 powers VDD-SYS, HDMI, USB OTG and should be 0.9V.
>>>  	On A83T boards dcdc4 is used for VDD-GPU.
>>> +	On H616 boards dcdcd is used for VCC-DRAM.
>>>  
>>>  config AXP_DCDC5_VOLT
>>>  	int "axp pmic dcdc5 voltage"
>>> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
>>> index 2dcc7bb99d02..0bef06920a7d 100644
>>> --- a/drivers/power/Makefile
>>> +++ b/drivers/power/Makefile
>>> @@ -6,6 +6,7 @@
>>>  obj-$(CONFIG_AXP152_POWER)	+= axp152.o
>>>  obj-$(CONFIG_AXP209_POWER)	+= axp209.o
>>>  obj-$(CONFIG_AXP221_POWER)	+= axp221.o
>>> +obj-$(CONFIG_AXP305_POWER)	+= axp305.o
>>>  obj-$(CONFIG_AXP809_POWER)	+= axp809.o
>>>  obj-$(CONFIG_AXP818_POWER)	+= axp818.o
>>>  obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
>>> diff --git a/drivers/power/axp305.c b/drivers/power/axp305.c
>>> new file mode 100644
>>> index 000000000000..f620798bb1d7
>>> --- /dev/null
>>> +++ b/drivers/power/axp305.c
>>> @@ -0,0 +1,80 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * AXP305 driver
>>> + *
>>> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
>>> + *
>>> + * Based on axp221.c
>>> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
>>> + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <command.h>
>>> +#include <errno.h>
>>> +#include <asm/arch/pmic_bus.h>
>>> +#include <axp_pmic.h>
>>> +
>>> +static u8 axp305_mvolt_to_cfg(int mvolt, int min, int max, int div)
>>> +{
>>> +	if (mvolt < min)
>>> +		mvolt = min;
>>> +	else if (mvolt > max)
>>> +		mvolt = max;
>>> +
>>> +	return  (mvolt - min) / div;
>>> +}
>>> +
>>> +int axp_set_dcdc4(unsigned int mvolt)
>>> +{
>>> +	int ret;
>>
>> Initialized ret value to 0.
> 
> Why? We set it unconditionally below, so initialising it here would be
> pointless and might actually be warned upon by astute compilers.

Sorry. It's my misunderstanding. you're right.

> 
>>
>>> +	u8 cfg;
>>> +
>>> +	if (mvolt >= 1600)
>>> +		cfg = 46 + axp305_mvolt_to_cfg(mvolt, 1600, 3300, 100);
>>
>> Could you use macro instead of 46 (magic code)?
>>
>>> +	else
>>> +		cfg = axp305_mvolt_to_cfg(mvolt, 600, 1500, 20);
>>> +
>>> +	if (mvolt == 0)
>>> +		return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1,
>>> +					AXP305_OUTPUT_CTRL1_DCDCD_EN);
>>> +
>>> +	ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	return pmic_bus_setbits(AXP305_OUTPUT_CTRL1,
>>> +				AXP305_OUTPUT_CTRL1_DCDCD_EN);
>>> +}
>>> +
>>> +int axp_init(void)
>>> +{
>>> +	u8 axp_chip_id;
>>> +	int ret;
>>> +
>>> +	ret = pmic_bus_init();
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x40)
>>
>> Ditto, use macro instead of 0x40. 
> 
> Not sure a macro is too useful here. I think the statement is pretty
> clear in that this must be the chip version, which is given as this
> value in the manual.

0x40 is chip version? When i saw 0x40, i thought it mean some bit values.
Thanks for kindly explanation. 

Best Regards,
Jaehoon Chung

> 
> Cheers,
> Andre
> 
>>> +		return -ENODEV;
>>> +
>>> +	return ret;
>>> +}
>>> +
>>> +#ifndef CONFIG_PSCI_RESET
>>> +int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>>> +{
>>> +	pmic_bus_write(AXP305_SHUTDOWN, AXP305_POWEROFF);
>>> +
>>> +	/* infinite loop during shutdown */
>>> +	while (1) {}
>>> +
>>> +	/* not reached */
>>> +	return 0;
>>> +}
>>> +#endif
>>> diff --git a/include/axp305.h b/include/axp305.h
>>> new file mode 100644
>>> index 000000000000..225c5040a322
>>> --- /dev/null
>>> +++ b/include/axp305.h
>>> @@ -0,0 +1,17 @@
>>> +/* SPDX-License-Identifier: GPL-2.0+ */
>>> +/*
>>> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
>>> + */
>>> +
>>> +enum axp305_reg {
>>> +	AXP305_CHIP_VERSION = 0x3,
>>> +	AXP305_OUTPUT_CTRL1 = 0x10,
>>> +	AXP305_DCDCD_VOLTAGE = 0x15,
>>> +	AXP305_SHUTDOWN = 0x32,
>>> +};
>>> +
>>> +#define AXP305_CHIP_VERSION_MASK	0xcf
>>> +
>>> +#define AXP305_OUTPUT_CTRL1_DCDCD_EN	(1 << 3)
>>> +
>>> +#define AXP305_POWEROFF			(1 << 7)
>>> diff --git a/include/axp_pmic.h b/include/axp_pmic.h
>>> index 10091d0bb278..405044c3a32f 100644
>>> --- a/include/axp_pmic.h
>>> +++ b/include/axp_pmic.h
>>> @@ -15,6 +15,9 @@
>>>  #ifdef CONFIG_AXP221_POWER
>>>  #include <axp221.h>
>>>  #endif
>>> +#ifdef CONFIG_AXP305_POWER
>>> +#include <axp305.h>
>>> +#endif
>>>  #ifdef CONFIG_AXP809_POWER
>>>  #include <axp809.h>
>>>  #endif
>>>
>>
> 
> 

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

* [PATCH 01/17] sunxi: Add support for AXP305 PMIC
  2021-01-06 23:33       ` Jaehoon Chung
@ 2021-01-07  9:49         ` André Przywara
  0 siblings, 0 replies; 48+ messages in thread
From: André Przywara @ 2021-01-07  9:49 UTC (permalink / raw)
  To: u-boot

On 06/01/2021 23:33, Jaehoon Chung wrote:
> On 1/6/21 7:11 PM, Andr? Przywara wrote:
>> On 05/01/2021 22:36, Jaehoon Chung wrote:
>>
>> Hi,
>>
>> thanks for having a look!
>>
>>> Hi Jernej
>>>
>>> On 1/3/21 6:26 PM, Jernej Skrabec wrote:
>>>> This PMIC can be found on H616 boards and it's very similar to AXP805
>>>> and AXP806.
>>>
>>> Is there any plan to cleanup codes?
>>
>> There is no support for either of these, we use the PMICs only in
>> Trusted Firmware or Linux. So nothing to consolidate, yet. This might
>> change in the future, and then of course we will use a common code base.
>>
>>>
>>>>
>>>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>>>> ---
>>>>  arch/arm/mach-sunxi/pmic_bus.c |  6 +++
>>>>  board/sunxi/board.c            | 10 +++--
>>>>  drivers/power/Kconfig          | 13 +++++-
>>>>  drivers/power/Makefile         |  1 +
>>>>  drivers/power/axp305.c         | 80 ++++++++++++++++++++++++++++++++++
>>>>  include/axp305.h               | 17 ++++++++
>>>>  include/axp_pmic.h             |  3 ++
>>>>  7 files changed, 126 insertions(+), 4 deletions(-)
>>>>  create mode 100644 drivers/power/axp305.c
>>>>  create mode 100644 include/axp305.h
>>>>
>>>> diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
>>>> index dea42de833f1..0394ce856448 100644
>>>> --- a/arch/arm/mach-sunxi/pmic_bus.c
>>>> +++ b/arch/arm/mach-sunxi/pmic_bus.c
>>>> @@ -18,6 +18,8 @@
>>>>  
>>>>  #define AXP209_I2C_ADDR			0x34
>>>>  
>>>> +#define AXP305_I2C_ADDR			0x36
>>>> +
>>>>  #define AXP221_CHIP_ADDR		0x68
>>>>  #define AXP221_CTRL_ADDR		0x3e
>>>>  #define AXP221_INIT_DATA		0x3e
>>>> @@ -64,6 +66,8 @@ int pmic_bus_read(u8 reg, u8 *data)
>>>>  	return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1);
>>>>  #elif defined CONFIG_AXP209_POWER
>>>>  	return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
>>>> +#elif defined CONFIG_AXP305_POWER
>>>> +	return i2c_read(AXP305_I2C_ADDR, reg, 1, data, 1);
>>>>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>>>  # ifdef CONFIG_MACH_SUN6I
>>>>  	return p2wi_read(reg, data);
>>>> @@ -81,6 +85,8 @@ int pmic_bus_write(u8 reg, u8 data)
>>>>  	return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1);
>>>>  #elif defined CONFIG_AXP209_POWER
>>>>  	return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
>>>> +#elif defined CONFIG_AXP305_POWER
>>>> +	return i2c_write(AXP305_I2C_ADDR, reg, 1, &data, 1);
>>>>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>>>  # ifdef CONFIG_MACH_SUN6I
>>>>  	return p2wi_write(reg, data);
>>>> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
>>>> index 708a27ed78e9..54ff9bc92396 100644
>>>> --- a/board/sunxi/board.c
>>>> +++ b/board/sunxi/board.c
>>>> @@ -634,16 +634,18 @@ void sunxi_board_init(void)
>>>>  #endif
>>>>  
>>>>  #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
>>>> -	defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
>>>> -	defined CONFIG_AXP818_POWER
>>>> +	defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
>>>> +	defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>>>  	power_failed = axp_init();
>>>>  
>>>>  #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
>>>>  	defined CONFIG_AXP818_POWER
>>>>  	power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
>>>>  #endif
>>>> +#if !defined(CONFIG_AXP305_POWER)
>>>>  	power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
>>>>  	power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
>>>> +#endif
>>>>  #if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
>>>>  	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
>>>>  #endif
>>>> @@ -656,8 +658,10 @@ void sunxi_board_init(void)
>>>>  	defined CONFIG_AXP818_POWER
>>>>  	power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
>>>>  #endif
>>>> +#if !defined(CONFIG_AXP305_POWER)
>>>>  	power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
>>>> -#if !defined(CONFIG_AXP152_POWER)
>>>> +#endif
>>>> +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER)
>>>>  	power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
>>>>  #endif
>>>>  #ifdef CONFIG_AXP209_POWER
>>>> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
>>>> index 02050f6f3569..d17cf2d9112a 100644
>>>> --- a/drivers/power/Kconfig
>>>> +++ b/drivers/power/Kconfig
>>>> @@ -48,6 +48,15 @@ config AXP221_POWER
>>>>  	Select this to enable support for the axp221/axp223 pmic found on most
>>>>  	A23 and A31 boards.
>>>>  
>>>> +config AXP305_POWER
>>>> +	bool "axp305 pmic support"
>>>> +	depends on MACH_SUN50I_H616
>>>> +	select AXP_PMIC_BUS
>>>> +	select CMD_POWEROFF
>>>> +	---help---
>>>> +	Select this to enable support for the axp305 pmic found on most
>>>> +	H616 boards.
>>>> +
>>>>  config AXP809_POWER
>>>>  	bool "axp809 pmic support"
>>>>  	depends on MACH_SUN9I
>>>> @@ -127,11 +136,12 @@ config AXP_DCDC3_VOLT
>>>>  
>>>>  config AXP_DCDC4_VOLT
>>>>  	int "axp pmic dcdc4 voltage"
>>>> -	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
>>>> +	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP305_POWER
>>>>  	default 1250 if AXP152_POWER
>>>>  	default 1200 if MACH_SUN6I
>>>>  	default 0 if MACH_SUN8I
>>>>  	default 900 if MACH_SUN9I
>>>> +	default 1500 if AXP305_POWER
>>>>  	---help---
>>>>  	Set the voltage (mV) to program the axp pmic dcdc4 at, set to 0 to
>>>>  	disable dcdc4.
>>>> @@ -140,6 +150,7 @@ config AXP_DCDC4_VOLT
>>>>  	On A23 / A33 boards dcdc4 is unused and should be disabled.
>>>>  	On A80 boards dcdc4 powers VDD-SYS, HDMI, USB OTG and should be 0.9V.
>>>>  	On A83T boards dcdc4 is used for VDD-GPU.
>>>> +	On H616 boards dcdcd is used for VCC-DRAM.
>>>>  
>>>>  config AXP_DCDC5_VOLT
>>>>  	int "axp pmic dcdc5 voltage"
>>>> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
>>>> index 2dcc7bb99d02..0bef06920a7d 100644
>>>> --- a/drivers/power/Makefile
>>>> +++ b/drivers/power/Makefile
>>>> @@ -6,6 +6,7 @@
>>>>  obj-$(CONFIG_AXP152_POWER)	+= axp152.o
>>>>  obj-$(CONFIG_AXP209_POWER)	+= axp209.o
>>>>  obj-$(CONFIG_AXP221_POWER)	+= axp221.o
>>>> +obj-$(CONFIG_AXP305_POWER)	+= axp305.o
>>>>  obj-$(CONFIG_AXP809_POWER)	+= axp809.o
>>>>  obj-$(CONFIG_AXP818_POWER)	+= axp818.o
>>>>  obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
>>>> diff --git a/drivers/power/axp305.c b/drivers/power/axp305.c
>>>> new file mode 100644
>>>> index 000000000000..f620798bb1d7
>>>> --- /dev/null
>>>> +++ b/drivers/power/axp305.c
>>>> @@ -0,0 +1,80 @@
>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>> +/*
>>>> + * AXP305 driver
>>>> + *
>>>> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
>>>> + *
>>>> + * Based on axp221.c
>>>> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
>>>> + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
>>>> + */
>>>> +
>>>> +#include <common.h>
>>>> +#include <command.h>
>>>> +#include <errno.h>
>>>> +#include <asm/arch/pmic_bus.h>
>>>> +#include <axp_pmic.h>
>>>> +
>>>> +static u8 axp305_mvolt_to_cfg(int mvolt, int min, int max, int div)
>>>> +{
>>>> +	if (mvolt < min)
>>>> +		mvolt = min;
>>>> +	else if (mvolt > max)
>>>> +		mvolt = max;
>>>> +
>>>> +	return  (mvolt - min) / div;
>>>> +}
>>>> +
>>>> +int axp_set_dcdc4(unsigned int mvolt)
>>>> +{
>>>> +	int ret;
>>>
>>> Initialized ret value to 0.
>>
>> Why? We set it unconditionally below, so initialising it here would be
>> pointless and might actually be warned upon by astute compilers.
> 
> Sorry. It's my misunderstanding. you're right.
> 
>>
>>>
>>>> +	u8 cfg;
>>>> +
>>>> +	if (mvolt >= 1600)
>>>> +		cfg = 46 + axp305_mvolt_to_cfg(mvolt, 1600, 3300, 100);
>>>
>>> Could you use macro instead of 46 (magic code)?
>>>
>>>> +	else
>>>> +		cfg = axp305_mvolt_to_cfg(mvolt, 600, 1500, 20);
>>>> +
>>>> +	if (mvolt == 0)
>>>> +		return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1,
>>>> +					AXP305_OUTPUT_CTRL1_DCDCD_EN);
>>>> +
>>>> +	ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg);
>>>> +	if (ret)
>>>> +		return ret;
>>>> +
>>>> +	return pmic_bus_setbits(AXP305_OUTPUT_CTRL1,
>>>> +				AXP305_OUTPUT_CTRL1_DCDCD_EN);
>>>> +}
>>>> +
>>>> +int axp_init(void)
>>>> +{
>>>> +	u8 axp_chip_id;
>>>> +	int ret;
>>>> +
>>>> +	ret = pmic_bus_init();
>>>> +	if (ret)
>>>> +		return ret;
>>>> +
>>>> +	ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id);
>>>> +	if (ret)
>>>> +		return ret;
>>>> +
>>>> +	if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x40)
>>>
>>> Ditto, use macro instead of 0x40. 
>>
>> Not sure a macro is too useful here. I think the statement is pretty
>> clear in that this must be the chip version, which is given as this
>> value in the manual.
> 
> 0x40 is chip version? When i saw 0x40, i thought it mean some bit values.
> Thanks for kindly explanation. 

Well, it's both, welcome to Allwinner :-D
This is what the manual says:
bits 7-6 & 3-0: IC Type NO.
		010000: IC is AXP305
		Others: Reserved

So it's a mess, and that number is not really unique (the AXP805 and
AXP806 also use the same bits), but it's just a safety measure to avoid
talking to the wrong device.

Cheers,
Andre

>>
>> Cheers,
>> Andre
>>
>>>> +		return -ENODEV;
>>>> +
>>>> +	return ret;
>>>> +}
>>>> +
>>>> +#ifndef CONFIG_PSCI_RESET
>>>> +int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>>>> +{
>>>> +	pmic_bus_write(AXP305_SHUTDOWN, AXP305_POWEROFF);
>>>> +
>>>> +	/* infinite loop during shutdown */
>>>> +	while (1) {}
>>>> +
>>>> +	/* not reached */
>>>> +	return 0;
>>>> +}
>>>> +#endif
>>>> diff --git a/include/axp305.h b/include/axp305.h
>>>> new file mode 100644
>>>> index 000000000000..225c5040a322
>>>> --- /dev/null
>>>> +++ b/include/axp305.h
>>>> @@ -0,0 +1,17 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0+ */
>>>> +/*
>>>> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
>>>> + */
>>>> +
>>>> +enum axp305_reg {
>>>> +	AXP305_CHIP_VERSION = 0x3,
>>>> +	AXP305_OUTPUT_CTRL1 = 0x10,
>>>> +	AXP305_DCDCD_VOLTAGE = 0x15,
>>>> +	AXP305_SHUTDOWN = 0x32,
>>>> +};
>>>> +
>>>> +#define AXP305_CHIP_VERSION_MASK	0xcf
>>>> +
>>>> +#define AXP305_OUTPUT_CTRL1_DCDCD_EN	(1 << 3)
>>>> +
>>>> +#define AXP305_POWEROFF			(1 << 7)
>>>> diff --git a/include/axp_pmic.h b/include/axp_pmic.h
>>>> index 10091d0bb278..405044c3a32f 100644
>>>> --- a/include/axp_pmic.h
>>>> +++ b/include/axp_pmic.h
>>>> @@ -15,6 +15,9 @@
>>>>  #ifdef CONFIG_AXP221_POWER
>>>>  #include <axp221.h>
>>>>  #endif
>>>> +#ifdef CONFIG_AXP305_POWER
>>>> +#include <axp305.h>
>>>> +#endif
>>>>  #ifdef CONFIG_AXP809_POWER
>>>>  #include <axp809.h>
>>>>  #endif
>>>>
>>>
>>
>>
> 

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

* [PATCH 01/17] sunxi: Add support for AXP305 PMIC
  2021-01-03  9:26 ` [PATCH 01/17] sunxi: Add support for AXP305 PMIC Jernej Skrabec
  2021-01-05 22:36   ` Jaehoon Chung
@ 2021-01-11  0:02   ` André Przywara
  2021-01-11  1:32     ` Jaehoon Chung
  2021-01-11 19:48     ` Jernej Škrabec
  1 sibling, 2 replies; 48+ messages in thread
From: André Przywara @ 2021-01-11  0:02 UTC (permalink / raw)
  To: u-boot

On 03/01/2021 09:26, Jernej Skrabec wrote:
> This PMIC can be found on H616 boards and it's very similar to AXP805
> and AXP806.
>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>

The existing sunxi PMIC code is the typical U-Boot mess, but I don't
want to block this series on a rework. I put some comments and ideas
below how to improve the whole "framework".

For this actual patch I checked the bits against the AXP305 datasheet,
it does what we need.

(reluctantly)
Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Thanks,
Andre

> ---
>  arch/arm/mach-sunxi/pmic_bus.c |  6 +++
>  board/sunxi/board.c            | 10 +++--
>  drivers/power/Kconfig          | 13 +++++-
>  drivers/power/Makefile         |  1 +
>  drivers/power/axp305.c         | 80 ++++++++++++++++++++++++++++++++++
>  include/axp305.h               | 17 ++++++++
>  include/axp_pmic.h             |  3 ++
>  7 files changed, 126 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/power/axp305.c
>  create mode 100644 include/axp305.h
> 
> diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
> index dea42de833f1..0394ce856448 100644
> --- a/arch/arm/mach-sunxi/pmic_bus.c
> +++ b/arch/arm/mach-sunxi/pmic_bus.c
> @@ -18,6 +18,8 @@
>  
>  #define AXP209_I2C_ADDR			0x34
>  
> +#define AXP305_I2C_ADDR			0x36
> +
>  #define AXP221_CHIP_ADDR		0x68
>  #define AXP221_CTRL_ADDR		0x3e
>  #define AXP221_INIT_DATA		0x3e
> @@ -64,6 +66,8 @@ int pmic_bus_read(u8 reg, u8 *data)
>  	return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1);
>  #elif defined CONFIG_AXP209_POWER
>  	return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
> +#elif defined CONFIG_AXP305_POWER
> +	return i2c_read(AXP305_I2C_ADDR, reg, 1, data, 1);
>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>  # ifdef CONFIG_MACH_SUN6I
>  	return p2wi_read(reg, data);
> @@ -81,6 +85,8 @@ int pmic_bus_write(u8 reg, u8 data)
>  	return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1);
>  #elif defined CONFIG_AXP209_POWER
>  	return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
> +#elif defined CONFIG_AXP305_POWER
> +	return i2c_write(AXP305_I2C_ADDR, reg, 1, &data, 1);
>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>  # ifdef CONFIG_MACH_SUN6I
>  	return p2wi_write(reg, data);
> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> index 708a27ed78e9..54ff9bc92396 100644
> --- a/board/sunxi/board.c
> +++ b/board/sunxi/board.c
> @@ -634,16 +634,18 @@ void sunxi_board_init(void)
>  #endif

This whole function is really a mess, but we can clean this up later.
I wonder if we can guard with the actual CONFIG_AXP_*_VOLT symbols
directly instead of specifying the list of PMICs requiring this rail
(this list is already in Kconfig).
Maybe with some macro magic to avoid the repetitions and move the ifdefs
out of the function?
	power_failed |= axp_set_rail(dcdc1, DCDC1);
and assemble the function name and CONFIG_ symbol in that macro, plus
having the guard there?

>  
>  #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
> -	defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
> -	defined CONFIG_AXP818_POWER
> +	defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
> +	defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>  	power_failed = axp_init();
>  
>  #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
>  	defined CONFIG_AXP818_POWER
>  	power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
>  #endif
> +#if !defined(CONFIG_AXP305_POWER)
>  	power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
>  	power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
> +#endif
>  #if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
>  	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
>  #endif
> @@ -656,8 +658,10 @@ void sunxi_board_init(void)
>  	defined CONFIG_AXP818_POWER
>  	power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
>  #endif
> +#if !defined(CONFIG_AXP305_POWER)
>  	power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
> -#if !defined(CONFIG_AXP152_POWER)
> +#endif
> +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER)
>  	power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
>  #endif
>  #ifdef CONFIG_AXP209_POWER

Verified this hunk by playing CPP and removing all non-applicable calls.
This ended up in:
	power_failed = axp_init();
	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);

Which looks like the idea behind this patch, but is totally non-obvious
from the diff.

> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> index 02050f6f3569..d17cf2d9112a 100644
> --- a/drivers/power/Kconfig
> +++ b/drivers/power/Kconfig
> @@ -48,6 +48,15 @@ config AXP221_POWER
>  	Select this to enable support for the axp221/axp223 pmic found on most
>  	A23 and A31 boards.
>  
> +config AXP305_POWER
> +	bool "axp305 pmic support"
> +	depends on MACH_SUN50I_H616
> +	select AXP_PMIC_BUS
> +	select CMD_POWEROFF
> +	---help---
> +	Select this to enable support for the axp305 pmic found on most
> +	H616 boards.
> +
>  config AXP809_POWER
>  	bool "axp809 pmic support"
>  	depends on MACH_SUN9I
> @@ -127,11 +136,12 @@ config AXP_DCDC3_VOLT
>  
>  config AXP_DCDC4_VOLT
>  	int "axp pmic dcdc4 voltage"
> -	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
> +	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP305_POWER
>  	default 1250 if AXP152_POWER
>  	default 1200 if MACH_SUN6I
>  	default 0 if MACH_SUN8I
>  	default 900 if MACH_SUN9I
> +	default 1500 if AXP305_POWER
>  	---help---
>  	Set the voltage (mV) to program the axp pmic dcdc4 at, set to 0 to
>  	disable dcdc4.
> @@ -140,6 +150,7 @@ config AXP_DCDC4_VOLT
>  	On A23 / A33 boards dcdc4 is unused and should be disabled.
>  	On A80 boards dcdc4 powers VDD-SYS, HDMI, USB OTG and should be 0.9V.
>  	On A83T boards dcdc4 is used for VDD-GPU.
> +	On H616 boards dcdcd is used for VCC-DRAM.
>  
>  config AXP_DCDC5_VOLT
>  	int "axp pmic dcdc5 voltage"
> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
> index 2dcc7bb99d02..0bef06920a7d 100644
> --- a/drivers/power/Makefile
> +++ b/drivers/power/Makefile
> @@ -6,6 +6,7 @@
>  obj-$(CONFIG_AXP152_POWER)	+= axp152.o
>  obj-$(CONFIG_AXP209_POWER)	+= axp209.o
>  obj-$(CONFIG_AXP221_POWER)	+= axp221.o
> +obj-$(CONFIG_AXP305_POWER)	+= axp305.o
>  obj-$(CONFIG_AXP809_POWER)	+= axp809.o
>  obj-$(CONFIG_AXP818_POWER)	+= axp818.o
>  obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
> diff --git a/drivers/power/axp305.c b/drivers/power/axp305.c
> new file mode 100644
> index 000000000000..f620798bb1d7
> --- /dev/null
> +++ b/drivers/power/axp305.c
> @@ -0,0 +1,80 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * AXP305 driver
> + *
> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
> + *
> + * Based on axp221.c

Given that, I wonder if we can (later) simplify this, ideally we end up
at something like this:
const struct axp_regulator axp_regulators[] = {
	{"dcdc1", 1600, 3400, 100, NA, 0x20, 0x10, 0},
	...
https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/drivers/allwinner/axp/axp803.c

Not sure that can cover all AXP chips, but it's worth a try to remove
all this boilerplate.

Cheers,
Andre


> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
> + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <errno.h>
> +#include <asm/arch/pmic_bus.h>
> +#include <axp_pmic.h>
> +
> +static u8 axp305_mvolt_to_cfg(int mvolt, int min, int max, int div)
> +{
> +	if (mvolt < min)
> +		mvolt = min;
> +	else if (mvolt > max)
> +		mvolt = max;
> +
> +	return  (mvolt - min) / div;
> +}
> +
> +int axp_set_dcdc4(unsigned int mvolt)
> +{
> +	int ret;
> +	u8 cfg;
> +
> +	if (mvolt >= 1600)
> +		cfg = 46 + axp305_mvolt_to_cfg(mvolt, 1600, 3300, 100);
> +	else
> +		cfg = axp305_mvolt_to_cfg(mvolt, 600, 1500, 20);
> +
> +	if (mvolt == 0)
> +		return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1,
> +					AXP305_OUTPUT_CTRL1_DCDCD_EN);
> +
> +	ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg);
> +	if (ret)
> +		return ret;
> +
> +	return pmic_bus_setbits(AXP305_OUTPUT_CTRL1,
> +				AXP305_OUTPUT_CTRL1_DCDCD_EN);
> +}
> +
> +int axp_init(void)
> +{
> +	u8 axp_chip_id;
> +	int ret;
> +
> +	ret = pmic_bus_init();
> +	if (ret)
> +		return ret;
> +
> +	ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id);
> +	if (ret)
> +		return ret;
> +
> +	if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x40)
> +		return -ENODEV;
> +
> +	return ret;
> +}
> +
> +#ifndef CONFIG_PSCI_RESET
> +int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +	pmic_bus_write(AXP305_SHUTDOWN, AXP305_POWEROFF);
> +
> +	/* infinite loop during shutdown */
> +	while (1) {}
> +
> +	/* not reached */
> +	return 0;
> +}
> +#endif
> diff --git a/include/axp305.h b/include/axp305.h
> new file mode 100644
> index 000000000000..225c5040a322
> --- /dev/null
> +++ b/include/axp305.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
> + */
> +
> +enum axp305_reg {
> +	AXP305_CHIP_VERSION = 0x3,
> +	AXP305_OUTPUT_CTRL1 = 0x10,
> +	AXP305_DCDCD_VOLTAGE = 0x15,
> +	AXP305_SHUTDOWN = 0x32,
> +};
> +
> +#define AXP305_CHIP_VERSION_MASK	0xcf
> +
> +#define AXP305_OUTPUT_CTRL1_DCDCD_EN	(1 << 3)
> +
> +#define AXP305_POWEROFF			(1 << 7)
> diff --git a/include/axp_pmic.h b/include/axp_pmic.h
> index 10091d0bb278..405044c3a32f 100644
> --- a/include/axp_pmic.h
> +++ b/include/axp_pmic.h
> @@ -15,6 +15,9 @@
>  #ifdef CONFIG_AXP221_POWER
>  #include <axp221.h>
>  #endif
> +#ifdef CONFIG_AXP305_POWER
> +#include <axp305.h>
> +#endif
>  #ifdef CONFIG_AXP809_POWER
>  #include <axp809.h>
>  #endif
> 

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

* [linux-sunxi] [PATCH 02/17] sunxi: Introduce common symbol for H6 like SoCs
  2021-01-04 18:28       ` Jernej Škrabec
@ 2021-01-11  0:13         ` André Przywara
  0 siblings, 0 replies; 48+ messages in thread
From: André Przywara @ 2021-01-11  0:13 UTC (permalink / raw)
  To: u-boot

On 04/01/2021 18:28, Jernej ?krabec wrote:
> Dne ponedeljek, 04. januar 2021 ob 11:35:41 CET je Andr? Przywara napisal(a):
>> On 03/01/2021 23:43, Samuel Holland wrote:
>>
>> Hi Jernej,
>>
>> thanks for that patch, that's a nice solution to avoid those long #ifdef
>> chains!
>>
>>> On 1/3/21 3:26 AM, Jernej Skrabec wrote:
>>>> It turns out that there are at least 2 other SoCs which have basically
>>>> the same memory map, similar clocks and other features as H6. It's very
>>>> likely that we'll see more such SoCs in the future. In order to ease
>>>> porting to new SoCs and lower ifdef clutter, introduce common symbol for
>>>> them.
>>>>
>>>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>>>> ---
>>>>
>>>>  arch/arm/include/asm/arch-sunxi/boot0.h |  2 +-
>>>>  arch/arm/include/asm/arch-sunxi/clock.h |  2 +-
>>>>  arch/arm/include/asm/arch-sunxi/cpu.h   |  2 +-
>>>>  arch/arm/include/asm/arch-sunxi/timer.h |  2 +-
>>>>  arch/arm/mach-sunxi/Kconfig             | 21 +++++++++++++--------
>>>>  arch/arm/mach-sunxi/Makefile            |  2 +-
>>>>  arch/arm/mach-sunxi/board.c             |  4 ++--
>>>>  arch/arm/mach-sunxi/rmr_switch.S        |  2 +-
>>>>  common/spl/Kconfig                      |  4 ++--
>>>>  include/configs/sun50i.h                |  2 +-
>>>>  10 files changed, 24 insertions(+), 19 deletions(-)
>>>>
>>>> diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h
>>>> b/arch/arm/include/asm/arch-sunxi/boot0.h index
>>>> 46d0f0666c2b..e8e8e38f0556 100644
>>>> --- a/arch/arm/include/asm/arch-sunxi/boot0.h
>>>> +++ b/arch/arm/include/asm/arch-sunxi/boot0.h
>>>> @@ -39,7 +39,7 @@
>>>>
>>>>  	.word	0xf57ff06f	// isb     sy
>>>>  	.word	0xe320f003	// wfi
>>>>  	.word	0xeafffffd	// b       @wfi
>>>>
>>>> -#ifndef CONFIG_MACH_SUN50I_H6
>>>> +#ifndef CONFIG_SUN50I_GEN_H6
>>>>
>>>>  	.word	0x017000a0	// writeable RVBAR mapping address
>>>>  
>>>>  #else
>>>>  
>>>>  	.word	0x09010040	// writeable RVBAR mapping address
>>>>
>>>> diff --git a/arch/arm/include/asm/arch-sunxi/clock.h
>>>> b/arch/arm/include/asm/arch-sunxi/clock.h index
>>>> 5994130e6b54..cbbe5c7a1e68 100644
>>>> --- a/arch/arm/include/asm/arch-sunxi/clock.h
>>>> +++ b/arch/arm/include/asm/arch-sunxi/clock.h
>>>> @@ -16,7 +16,7 @@
>>>>
>>>>  /* clock control module regs definition */
>>>>  #if defined(CONFIG_MACH_SUN8I_A83T)
>>>>  #include <asm/arch/clock_sun8i_a83t.h>
>>>>
>>>> -#elif defined(CONFIG_MACH_SUN50I_H6)
>>>> +#elif defined(CONFIG_SUN50I_GEN_H6)
>>>>
>>>>  #include <asm/arch/clock_sun50i_h6.h>
>>>>  #elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
>>>>  
>>>>        defined(CONFIG_MACH_SUN50I)
>>>>
>>>> diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h
>>>> b/arch/arm/include/asm/arch-sunxi/cpu.h index 8b57d24e2f0c..b08f2023748c
>>>> 100644
>>>> --- a/arch/arm/include/asm/arch-sunxi/cpu.h
>>>> +++ b/arch/arm/include/asm/arch-sunxi/cpu.h
>>>> @@ -8,7 +8,7 @@
>>>>
>>>>  #if defined(CONFIG_MACH_SUN9I)
>>>>  #include <asm/arch/cpu_sun9i.h>
>>>>
>>>> -#elif defined(CONFIG_MACH_SUN50I_H6)
>>>> +#elif defined(CONFIG_SUN50I_GEN_H6)
>>>>
>>>>  #include <asm/arch/cpu_sun50i_h6.h>
>>>>  #else
>>>>  #include <asm/arch/cpu_sun4i.h>
>>>>
>>>> diff --git a/arch/arm/include/asm/arch-sunxi/timer.h
>>>> b/arch/arm/include/asm/arch-sunxi/timer.h index
>>>> 6f138d04b806..bb5626d893bb 100644
>>>> --- a/arch/arm/include/asm/arch-sunxi/timer.h
>>>> +++ b/arch/arm/include/asm/arch-sunxi/timer.h
>>>> @@ -76,7 +76,7 @@ struct sunxi_timer_reg {
>>>>
>>>>  	struct sunxi_tgp tgp[4];
>>>>  	u8 res5[8];
>>>>  	u32 cpu_cfg;
>>>>
>>>> -#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
>>>> +#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
>>>>
>>>>  	u8 res3[16];
>>>>  	struct sunxi_wdog wdog[5];	/* We have 5 watchdogs */
>>>>  
>>>>  #endif
>>>>
>>>> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
>>>> index 49ef217f08c0..1cf79bad7cf6 100644
>>>> --- a/arch/arm/mach-sunxi/Kconfig
>>>> +++ b/arch/arm/mach-sunxi/Kconfig
>>>> @@ -82,7 +82,7 @@ config SUN8I_RSB
>>>>
>>>>  config SUNXI_SRAM_ADDRESS
>>>>  
>>>>  	hex
>>>>  	default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
>>>>
>>>> -	default 0x20000 if MACH_SUN50I_H6
>>>> +	default 0x20000 if SUN50I_GEN_H6
>>>>
>>>>  	default 0x0
>>>>  	---help---
>>>>  	Older Allwinner SoCs have their mask boot ROM mapped just below 
> 4GB,
>>>>
>>>> @@ -108,6 +108,15 @@ config SUNXI_GEN_SUN6I
>>>>
>>>>  	separate ahb reset control registers, custom pmic bus, new style
>>>>  	watchdog, etc.
>>>>
>>>> +config SUN50I_GEN_H6
>>>
>>> The new memory map is also used for 32-bit SoCs V5 (sun8iw12p1) and
>>> newer. So this is not sun50i-specific, and I'd suggest SUNXI_GEN_H6 (or
>>> even SUNXI_GEN_H6_V5). It is unfortunate there appears to be no name for
>>> this family.
>>
>> Yeah, the Allwinner generation naming being *core* dependent is really
>> annyoing and not helpful.
>> I am fine with a rename, but then it would be very close to
>> "CONFIG_SUNXI_GEN_SUN6I", which is quite confusing to any readers
>> (already stumbled upon it myself in patch 04/17).
>>
>> Any opinions?
> 
> I would leave it as it is, it's common to name something, usually driver, but 
> in this case symbol, after first known device that implemented particular 
> feature.

Yes, but typically that's for drivers, and here this is specifying a
group of SoCs, like CONFIG_SUNXI_GEN_SUN6I does (where we also use _SUNXI_).

But this is really nitpicking, since there is no ABI, we can rename it
easily later with a simple patch, should we agree on the right name for
that baby.

Cheers,
Andre.

> 
>>
>>>> +	bool
>>>> +	select FIT
>>>> +	select SPL_LOAD_FIT
>>>> +	select SUPPORT_SPL
>>>> +	---help---
>>>> +	Select this for sunxi SoCs which have H6 like peripherals, clocks
>>>> +	and memory map.
>>>> +
>>>>
>>>>  config SUNXI_DRAM_DW
>>>>  
>>>>  	bool
>>>>  	---help---
>>>>
>>>> @@ -302,10 +311,7 @@ config MACH_SUN50I_H5
>>>>
>>>>  config MACH_SUN50I_H6
>>>>  
>>>>  	bool "sun50i (Allwinner H6)"
>>>>  	select ARM64
>>>>
>>>> -	select SUPPORT_SPL
>>>> -	select FIT
>>>>
>>>>  	select PHY_SUN4I_USB
>>>>
>>>> -	select SPL_LOAD_FIT
>>>>
>>>>  	select DRAM_SUN50I_H6
>>>
>>> I would expect this to select SUN50I_GEN_H6.
>>
>> Indeed, that breaks H6 builds.
> 
> Ops, leftover after refactoring.
> 
>>
>>>>  endchoice
>>>>
>>>> @@ -540,7 +546,6 @@ config SYS_CLK_FREQ
>>>>
>>>>  	default 816000000 if MACH_SUN50I || MACH_SUN50I_H5
>>>>  	default 1008000000 if MACH_SUN8I
>>>>  	default 1008000000 if MACH_SUN9I
>>>>
>>>> -	default 888000000 if MACH_SUN50I_H6
>>>
>>> Was this removal intentional? You later add a different value for H616
>>> only.> 
> 
> That's also an oversight after refactoring.
> 
>>>>  config SYS_CONFIG_NAME
>>>>  
>>>>  	default "sun4i" if MACH_SUN4I
>>>>
>>>> @@ -756,7 +761,7 @@ config VIDEO_SUNXI
>>>>
>>>>  	depends on !MACH_SUN8I_V3S
>>>>  	depends on !MACH_SUN9I
>>>>  	depends on !MACH_SUN50I
>>>>
>>>> -	depends on !MACH_SUN50I_H6
>>>> +	depends on !SUN50I_GEN_H6
>>>>
>>>>  	select VIDEO
>>>>  	imply VIDEO_DT_SIMPLEFB
>>>>  	default y
>>>>
>>>> @@ -989,11 +994,11 @@ config SPL_STACK_R_ADDR
>>>>
>>>>  	default 0x4fe00000 if MACH_SUN8I
>>>>  	default 0x2fe00000 if MACH_SUN9I
>>>>  	default 0x4fe00000 if MACH_SUN50I
>>>>
>>>> -	default 0x4fe00000 if MACH_SUN50I_H6
>>>> +	default 0x4fe00000 if SUN50I_GEN_H6
>>>>
>>>>  config SPL_SPI_SUNXI
>>>>  
>>>>  	bool "Support for SPI Flash on Allwinner SoCs in SPL"
>>>>
>>>> -	depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || 
> MACH_SUNXI_H3_H5
>>>> || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6 +	depends on
>>>> MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 ||
>>>> MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6
>> I know I suggested this, but it was a bit premature. The SPL SPI code
>> needs some adjustments first. I have a patch, will send it ASAP. But for
>> now you can just drop this change.
> 
> Ok,
> 
> Best regards,
> Jernej
> 
>>
>> Thanks!
>> Andre
>>
>>>>  	help
>>>>  	
>>>>  	  Enable support for SPI Flash. This option allows SPL to read 
> from
>>>>  	  sunxi SPI Flash. It uses the same method as the boot ROM, so 
> does
>>>>
>>>> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
>>>> index d129f334798b..b8aca43d6630 100644
>>>> --- a/arch/arm/mach-sunxi/Makefile
>>>> +++ b/arch/arm/mach-sunxi/Makefile
>>>> @@ -26,7 +26,7 @@ else
>>>>
>>>>  obj-$(CONFIG_MACH_SUN8I)	+= clock_sun6i.o
>>>>  endif
>>>>  obj-$(CONFIG_MACH_SUN9I)	+= clock_sun9i.o gtbus_sun9i.o
>>>>
>>>> -obj-$(CONFIG_MACH_SUN50I_H6)	+= clock_sun50i_h6.o
>>>> +obj-$(CONFIG_SUN50I_GEN_H6)	+= clock_sun50i_h6.o
>>>>
>>>>  ifdef CONFIG_SPL_BUILD
>>>>  obj-$(CONFIG_DRAM_SUN4I)	+= dram_sun4i.o
>>>>
>>>> diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
>>>> index f40fccd8f8b9..7a8b303f233c 100644
>>>> --- a/arch/arm/mach-sunxi/board.c
>>>> +++ b/arch/arm/mach-sunxi/board.c
>>>> @@ -144,7 +144,7 @@ static int gpio_init(void)
>>>>
>>>>  #error Unsupported console port number. Please fix pin mux settings in
>>>>  board.c #endif
>>>>
>>>> -#ifdef CONFIG_MACH_SUN50I_H6
>>>> +#ifdef CONFIG_SUN50I_GEN_H6
>>>>
>>>>  	/* Update PIO power bias configuration by copy hardware detected 
> value
>>>>  	*/
>>>>  	val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
>>>>  	writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
>>>>
>>>> @@ -329,7 +329,7 @@ void reset_cpu(ulong addr)
>>>>
>>>>  		/* sun5i sometimes gets stuck without this */
>>>>  		writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
>>>>  	
>>>>  	}
>>>>
>>>> -#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
>>>> +#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
>>>>
>>>>  #if defined(CONFIG_MACH_SUN50I_H6)
>>>>  
>>>>  	/* WDOG is broken for some H6 rev. use the R_WDOG instead */
>>>>  	static const struct sunxi_wdog *wdog =
>>>>
>>>> diff --git a/arch/arm/mach-sunxi/rmr_switch.S
>>>> b/arch/arm/mach-sunxi/rmr_switch.S index fafd306f95b1..33e55d496865
>>>> 100644
>>>> --- a/arch/arm/mach-sunxi/rmr_switch.S
>>>> +++ b/arch/arm/mach-sunxi/rmr_switch.S
>>>> @@ -30,7 +30,7 @@
>>>>
>>>>  .text
>>>>
>>>> -#ifndef CONFIG_MACH_SUN50I_H6
>>>> +#ifndef CONFIG_SUN50I_GEN_H6
>>>>
>>>>  	ldr	r1, =0x017000a0		@ MMIO mapped 
> RVBAR[0] register
>>>>  
>>>>  #else
>>>>  
>>>>  	ldr	r1, =0x09010040		@ MMIO mapped 
> RVBAR[0] register
>>>>
>>>> diff --git a/common/spl/Kconfig b/common/spl/Kconfig
>>>> index d8086bd9e874..bed715774d81 100644
>>>> --- a/common/spl/Kconfig
>>>> +++ b/common/spl/Kconfig
>>>> @@ -150,7 +150,7 @@ config SPL_TEXT_BASE
>>>>
>>>>  	hex "SPL Text Base"
>>>>  	default ISW_ENTRY_ADDR if AM43XX || AM33XX || OMAP54XX || 
> ARCH_KEYSTONE
>>>>  	default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I
>>>>
>>>> -	default 0x20060 if MACH_SUN50I_H6
>>>> +	default 0x20060 if SUN50I_GEN_H6
>>>>
>>>>  	default 0x00060 if ARCH_SUNXI
>>>>  	default 0xfffc0000 if ARCH_ZYNQMP
>>>>  	default 0x0
>>>>
>>>> @@ -459,7 +459,7 @@ config SPL_SHA512_SUPPORT
>>>>
>>>>  config SPL_FIT_IMAGE_TINY
>>>>  
>>>>  	bool "Remove functionality from SPL FIT loading to reduce size"
>>>>  	depends on SPL_FIT
>>>>
>>>> -	default y if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6
>>>> +	default y if MACH_SUN50I || MACH_SUN50I_H5 || SUN50I_GEN_H6
>>>
>>> This can probably be simplified to ARCH_SUNXI.
>>>
>>>>  	default y if ARCH_IMX8M
>>>>  	help
>>>>  	
>>>>  	  Enable this to reduce the size of the FIT image loading code
>>>>
>>>> diff --git a/include/configs/sun50i.h b/include/configs/sun50i.h
>>>> index e050a5299f3b..bc2e3a3d0088 100644
>>>> --- a/include/configs/sun50i.h
>>>> +++ b/include/configs/sun50i.h
>>>> @@ -10,7 +10,7 @@
>>>>
>>>>   * A64 specific configuration
>>>>   */
>>>>
>>>> -#ifndef CONFIG_MACH_SUN50I_H6
>>>> +#ifndef CONFIG_SUN50I_GEN_H6
>>>>
>>>>  #define GICD_BASE		0x1c81000
>>>>  #define GICC_BASE		0x1c82000
>>>>  #else
>>>
>>> Cheers,
>>> Samuel
> 
> 
> 
> 

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

* [PATCH 03/17] mmc: sunxi: Replace H6 ifdefs with H6 gen macro
  2021-01-03  9:26 ` [PATCH 03/17] mmc: sunxi: Replace H6 ifdefs with H6 gen macro Jernej Skrabec
@ 2021-01-11  0:13   ` André Przywara
  0 siblings, 0 replies; 48+ messages in thread
From: André Przywara @ 2021-01-11  0:13 UTC (permalink / raw)
  To: u-boot

On 03/01/2021 09:26, Jernej Skrabec wrote:
> It turns out that several SoCs share same mmc configuration as H6. In
> order to lower ifdef clutter replace H6 specific macro with common one.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>

Shame we need to do this, but the SPL requires this ifdef orgy.

Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Cheers,
Andre

> ---
>  arch/arm/include/asm/arch-sunxi/mmc.h |  2 +-
>  drivers/mmc/sunxi_mmc.c               | 12 ++++++------
>  2 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
> index f2deafddd202..340e25b04d2a 100644
> --- a/arch/arm/include/asm/arch-sunxi/mmc.h
> +++ b/arch/arm/include/asm/arch-sunxi/mmc.h
> @@ -45,7 +45,7 @@ struct sunxi_mmc {
>  	u32 chda;		/* 0x90 */
>  	u32 cbda;		/* 0x94 */
>  	u32 res2[26];
> -#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
> +#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
>  	u32 res3[17];
>  	u32 samp_dl;
>  	u32 res4[46];
> diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
> index 0e03b07ce555..3767a39277c1 100644
> --- a/drivers/mmc/sunxi_mmc.c
> +++ b/drivers/mmc/sunxi_mmc.c
> @@ -122,7 +122,7 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
>  	if (IS_ENABLED(CONFIG_MACH_SUN8I_A83T) && priv->mmc_no != 2)
>  		new_mode = false;
>  
> -#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6)
> +#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_SUN50I_GEN_H6)
>  	calibrate = true;
>  #endif
>  
> @@ -133,7 +133,7 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
>  #ifdef CONFIG_MACH_SUN9I
>  		pll = CCM_MMC_CTRL_PLL_PERIPH0;
>  		pll_hz = clock_get_pll4_periph0();
> -#elif defined(CONFIG_MACH_SUN50I_H6)
> +#elif defined(CONFIG_SUN50I_GEN_H6)
>  		pll = CCM_MMC_CTRL_PLL6X2;
>  		pll_hz = clock_get_pll6() * 2;
>  #else
> @@ -249,7 +249,7 @@ static int mmc_config_clock(struct sunxi_mmc_priv *priv, struct mmc *mmc)
>  	rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK;
>  	writel(rval, &priv->reg->clkcr);
>  
> -#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6)
> +#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_SUN50I_GEN_H6)
>  	/* A64 supports calibration of delays on MMC controller and we
>  	 * have to set delay of zero before starting calibration.
>  	 * Allwinner BSP driver sets a delay only in the case of
> @@ -530,7 +530,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
>  
>  	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
>  	cfg->host_caps = MMC_MODE_4BIT;
> -#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN50I_H6)
> +#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN8I) || defined(CONFIG_SUN50I_GEN_H6)
>  	if (sdc_no == 2)
>  		cfg->host_caps = MMC_MODE_8BIT;
>  #endif
> @@ -545,7 +545,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
>  
>  	/* config ahb clock */
>  	debug("init mmc %d clock and io\n", sdc_no);
> -#if !defined(CONFIG_MACH_SUN50I_H6)
> +#if !defined(CONFIG_SUN50I_GEN_H6)
>  	setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
>  
>  #ifdef CONFIG_SUNXI_GEN_SUN6I
> @@ -557,7 +557,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
>  	writel(SUNXI_MMC_COMMON_CLK_GATE | SUNXI_MMC_COMMON_RESET,
>  	       SUNXI_MMC_COMMON_BASE + 4 * sdc_no);
>  #endif
> -#else /* CONFIG_MACH_SUN50I_H6 */
> +#else /* CONFIG_SUN50I_GEN_H6 */
>  	setbits_le32(&ccm->sd_gate_reset, 1 << sdc_no);
>  	/* unassert reset */
>  	setbits_le32(&ccm->sd_gate_reset, 1 << (RESET_SHIFT + sdc_no));
> 

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

* [PATCH 15/17] sunxi: gpio: introduce compatible for H616
  2021-01-03  9:26 ` [PATCH 15/17] sunxi: gpio: introduce compatible for H616 Jernej Skrabec
@ 2021-01-11  0:36   ` André Przywara
  0 siblings, 0 replies; 48+ messages in thread
From: André Przywara @ 2021-01-11  0:36 UTC (permalink / raw)
  To: u-boot

On 03/01/2021 09:26, Jernej Skrabec wrote:
> H616 pinctrl is no different configuration wise than others, so just add
> compatible for it.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>

Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Cheers,
Andre

> ---
>  drivers/gpio/sunxi_gpio.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
> index 02c3471b5684..1985ee5d2fc9 100644
> --- a/drivers/gpio/sunxi_gpio.c
> +++ b/drivers/gpio/sunxi_gpio.c
> @@ -356,6 +356,7 @@ static const struct udevice_id sunxi_gpio_ids[] = {
>  	ID("allwinner,sun9i-a80-pinctrl",	a_all),
>  	ID("allwinner,sun50i-a64-pinctrl",	a_all),
>  	ID("allwinner,sun50i-h6-pinctrl",	a_all),
> +	ID("allwinner,sun50i-h616-pinctrl",	a_all),
>  	ID("allwinner,sun6i-a31-r-pinctrl",	l_2),
>  	ID("allwinner,sun8i-a23-r-pinctrl",	l_1),
>  	ID("allwinner,sun8i-a83t-r-pinctrl",	l_1),
> 

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

* [PATCH 16/17] clk: sunxi: Add support for H616 clocks
  2021-01-03  9:26 ` [PATCH 16/17] clk: sunxi: Add support for H616 clocks Jernej Skrabec
@ 2021-01-11  0:44   ` André Przywara
  0 siblings, 0 replies; 48+ messages in thread
From: André Przywara @ 2021-01-11  0:44 UTC (permalink / raw)
  To: u-boot

On 03/01/2021 09:26, Jernej Skrabec wrote:
> This commit introduces DM H616 clock driver.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>

Compared against the manual.

Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Cheers,
Andre

> ---
>  drivers/clk/sunxi/Kconfig    |   7 ++
>  drivers/clk/sunxi/Makefile   |   1 +
>  drivers/clk/sunxi/clk_h616.c | 120 +++++++++++++++++++++++++++++++++++
>  3 files changed, 128 insertions(+)
>  create mode 100644 drivers/clk/sunxi/clk_h616.c
> 
> diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
> index 5ff101b99305..bf084fa7a84a 100644
> --- a/drivers/clk/sunxi/Kconfig
> +++ b/drivers/clk/sunxi/Kconfig
> @@ -79,6 +79,13 @@ config CLK_SUN50I_H6
>  	  This enables common clock driver support for platforms based
>  	  on Allwinner H6 SoC.
>  
> +config CLK_SUN50I_H616
> +	bool "Clock driver for Allwinner H616"
> +	default MACH_SUN50I_H616
> +	help
> +	  This enables common clock driver support for platforms based
> +	  on Allwinner H616 SoC.
> +
>  config CLK_SUN50I_A64
>  	bool "Clock driver for Allwinner A64"
>  	default MACH_SUN50I
> diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
> index 36fb2aeb56c5..0dfc0593fb1c 100644
> --- a/drivers/clk/sunxi/Makefile
> +++ b/drivers/clk/sunxi/Makefile
> @@ -16,4 +16,5 @@ obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o
>  obj-$(CONFIG_CLK_SUN9I_A80) += clk_a80.o
>  obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
>  obj-$(CONFIG_CLK_SUN50I_H6) += clk_h6.o
> +obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o
>  obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
> diff --git a/drivers/clk/sunxi/clk_h616.c b/drivers/clk/sunxi/clk_h616.c
> new file mode 100644
> index 000000000000..e2e3a5c78c95
> --- /dev/null
> +++ b/drivers/clk/sunxi/clk_h616.c
> @@ -0,0 +1,120 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Copyright (C) 2021 Jernej Skrabec <jernej.skrabec@siol.net>
> + */
> +
> +#include <common.h>
> +#include <clk-uclass.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <asm/arch/ccu.h>
> +#include <dt-bindings/clock/sun50i-h616-ccu.h>
> +#include <dt-bindings/reset/sun50i-h616-ccu.h>
> +#include <linux/bitops.h>
> +
> +static struct ccu_clk_gate h616_gates[] = {
> +	[CLK_BUS_MMC0]		= GATE(0x84c, BIT(0)),
> +	[CLK_BUS_MMC1]		= GATE(0x84c, BIT(1)),
> +	[CLK_BUS_MMC2]		= GATE(0x84c, BIT(2)),
> +
> +	[CLK_BUS_UART0]		= GATE(0x90c, BIT(0)),
> +	[CLK_BUS_UART1]		= GATE(0x90c, BIT(1)),
> +	[CLK_BUS_UART2]		= GATE(0x90c, BIT(2)),
> +	[CLK_BUS_UART3]		= GATE(0x90c, BIT(3)),
> +	[CLK_BUS_UART4]		= GATE(0x90c, BIT(4)),
> +	[CLK_BUS_UART5]		= GATE(0x90c, BIT(5)),
> +
> +	[CLK_SPI0]		= GATE(0x940, BIT(31)),
> +	[CLK_SPI1]		= GATE(0x944, BIT(31)),
> +
> +	[CLK_BUS_SPI0]		= GATE(0x96c, BIT(0)),
> +	[CLK_BUS_SPI1]		= GATE(0x96c, BIT(1)),
> +
> +	[CLK_BUS_EMAC0]		= GATE(0x97c, BIT(0)),
> +	[CLK_BUS_EMAC1]		= GATE(0x97c, BIT(1)),
> +
> +	[CLK_USB_PHY0]		= GATE(0xa70, BIT(29)),
> +	[CLK_USB_OHCI0]		= GATE(0xa70, BIT(31)),
> +
> +	[CLK_USB_PHY1]		= GATE(0xa74, BIT(29)),
> +	[CLK_USB_OHCI1]		= GATE(0xa74, BIT(31)),
> +
> +	[CLK_USB_PHY2]		= GATE(0xa78, BIT(29)),
> +	[CLK_USB_OHCI2]		= GATE(0xa78, BIT(31)),
> +
> +	[CLK_USB_PHY3]		= GATE(0xa7c, BIT(29)),
> +	[CLK_USB_OHCI3]		= GATE(0xa7c, BIT(31)),
> +
> +	[CLK_BUS_OHCI0]		= GATE(0xa8c, BIT(0)),
> +	[CLK_BUS_OHCI1]		= GATE(0xa8c, BIT(1)),
> +	[CLK_BUS_OHCI2]		= GATE(0xa8c, BIT(2)),
> +	[CLK_BUS_OHCI3]		= GATE(0xa8c, BIT(3)),
> +	[CLK_BUS_EHCI0]		= GATE(0xa8c, BIT(4)),
> +	[CLK_BUS_EHCI1]		= GATE(0xa8c, BIT(5)),
> +	[CLK_BUS_EHCI2]		= GATE(0xa8c, BIT(6)),
> +	[CLK_BUS_EHCI3]		= GATE(0xa8c, BIT(7)),
> +	[CLK_BUS_OTG]		= GATE(0xa8c, BIT(8)),
> +};
> +
> +static struct ccu_reset h616_resets[] = {
> +	[RST_BUS_MMC0]		= RESET(0x84c, BIT(16)),
> +	[RST_BUS_MMC1]		= RESET(0x84c, BIT(17)),
> +	[RST_BUS_MMC2]		= RESET(0x84c, BIT(18)),
> +
> +	[RST_BUS_UART0]		= RESET(0x90c, BIT(16)),
> +	[RST_BUS_UART1]		= RESET(0x90c, BIT(17)),
> +	[RST_BUS_UART2]		= RESET(0x90c, BIT(18)),
> +	[RST_BUS_UART3]		= RESET(0x90c, BIT(19)),
> +	[RST_BUS_UART4]		= RESET(0x90c, BIT(20)),
> +	[RST_BUS_UART5]		= RESET(0x90c, BIT(21)),
> +
> +	[RST_BUS_SPI0]		= RESET(0x96c, BIT(16)),
> +	[RST_BUS_SPI1]		= RESET(0x96c, BIT(17)),
> +
> +	[RST_BUS_EMAC0]		= RESET(0x97c, BIT(16)),
> +	[RST_BUS_EMAC1]		= RESET(0x97c, BIT(17)),
> +
> +	[RST_USB_PHY0]		= RESET(0xa70, BIT(30)),
> +
> +	[RST_USB_PHY1]		= RESET(0xa74, BIT(30)),
> +
> +	[RST_USB_PHY2]		= RESET(0xa78, BIT(30)),
> +
> +	[RST_USB_PHY3]		= RESET(0xa7c, BIT(30)),
> +
> +	[RST_BUS_OHCI0]		= RESET(0xa8c, BIT(16)),
> +	[RST_BUS_OHCI1]		= RESET(0xa8c, BIT(17)),
> +	[RST_BUS_OHCI2]		= RESET(0xa8c, BIT(18)),
> +	[RST_BUS_OHCI3]		= RESET(0xa8c, BIT(19)),
> +	[RST_BUS_EHCI0]		= RESET(0xa8c, BIT(20)),
> +	[RST_BUS_EHCI1]		= RESET(0xa8c, BIT(21)),
> +	[RST_BUS_EHCI2]		= RESET(0xa8c, BIT(22)),
> +	[RST_BUS_EHCI3]		= RESET(0xa8c, BIT(23)),
> +	[RST_BUS_OTG]		= RESET(0xa8c, BIT(24)),
> +};
> +
> +static const struct ccu_desc h616_ccu_desc = {
> +	.gates = h616_gates,
> +	.resets = h616_resets,
> +};
> +
> +static int h616_clk_bind(struct udevice *dev)
> +{
> +	return sunxi_reset_bind(dev, ARRAY_SIZE(h616_resets));
> +}
> +
> +static const struct udevice_id h616_ccu_ids[] = {
> +	{ .compatible = "allwinner,sun50i-h616-ccu",
> +	  .data = (ulong)&h616_ccu_desc },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(clk_sun50i_h616) = {
> +	.name		= "sun50i_h616_ccu",
> +	.id		= UCLASS_CLK,
> +	.of_match	= h616_ccu_ids,
> +	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
> +	.ops		= &sunxi_clk_ops,
> +	.probe		= sunxi_clk_probe,
> +	.bind		= h616_clk_bind,
> +};
> 

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

* [PATCH 01/17] sunxi: Add support for AXP305 PMIC
  2021-01-11  0:02   ` André Przywara
@ 2021-01-11  1:32     ` Jaehoon Chung
  2021-01-11 19:48     ` Jernej Škrabec
  1 sibling, 0 replies; 48+ messages in thread
From: Jaehoon Chung @ 2021-01-11  1:32 UTC (permalink / raw)
  To: u-boot

On 1/11/21 9:02 AM, Andr? Przywara wrote:
> On 03/01/2021 09:26, Jernej Skrabec wrote:
>> This PMIC can be found on H616 boards and it's very similar to AXP805
>> and AXP806.
>>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> 
> The existing sunxi PMIC code is the typical U-Boot mess, but I don't
> want to block this series on a rework. I put some comments and ideas
> below how to improve the whole "framework".

Agreed. it seems that it needs to make more time about refactoring whole codes. 


> 
> For this actual patch I checked the bits against the AXP305 datasheet,
> it does what we need.
> 
> (reluctantly)
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>

Best Regards,
Jaehoon Chung

> 
> Thanks,
> Andre
> 
>> ---
>>  arch/arm/mach-sunxi/pmic_bus.c |  6 +++
>>  board/sunxi/board.c            | 10 +++--
>>  drivers/power/Kconfig          | 13 +++++-
>>  drivers/power/Makefile         |  1 +
>>  drivers/power/axp305.c         | 80 ++++++++++++++++++++++++++++++++++
>>  include/axp305.h               | 17 ++++++++
>>  include/axp_pmic.h             |  3 ++
>>  7 files changed, 126 insertions(+), 4 deletions(-)
>>  create mode 100644 drivers/power/axp305.c
>>  create mode 100644 include/axp305.h
>>
>> diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
>> index dea42de833f1..0394ce856448 100644
>> --- a/arch/arm/mach-sunxi/pmic_bus.c
>> +++ b/arch/arm/mach-sunxi/pmic_bus.c
>> @@ -18,6 +18,8 @@
>>  
>>  #define AXP209_I2C_ADDR			0x34
>>  
>> +#define AXP305_I2C_ADDR			0x36
>> +
>>  #define AXP221_CHIP_ADDR		0x68
>>  #define AXP221_CTRL_ADDR		0x3e
>>  #define AXP221_INIT_DATA		0x3e
>> @@ -64,6 +66,8 @@ int pmic_bus_read(u8 reg, u8 *data)
>>  	return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1);
>>  #elif defined CONFIG_AXP209_POWER
>>  	return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
>> +#elif defined CONFIG_AXP305_POWER
>> +	return i2c_read(AXP305_I2C_ADDR, reg, 1, data, 1);
>>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>  # ifdef CONFIG_MACH_SUN6I
>>  	return p2wi_read(reg, data);
>> @@ -81,6 +85,8 @@ int pmic_bus_write(u8 reg, u8 data)
>>  	return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1);
>>  #elif defined CONFIG_AXP209_POWER
>>  	return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
>> +#elif defined CONFIG_AXP305_POWER
>> +	return i2c_write(AXP305_I2C_ADDR, reg, 1, &data, 1);
>>  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>  # ifdef CONFIG_MACH_SUN6I
>>  	return p2wi_write(reg, data);
>> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
>> index 708a27ed78e9..54ff9bc92396 100644
>> --- a/board/sunxi/board.c
>> +++ b/board/sunxi/board.c
>> @@ -634,16 +634,18 @@ void sunxi_board_init(void)
>>  #endif
> 
> This whole function is really a mess, but we can clean this up later.
> I wonder if we can guard with the actual CONFIG_AXP_*_VOLT symbols
> directly instead of specifying the list of PMICs requiring this rail
> (this list is already in Kconfig).
> Maybe with some macro magic to avoid the repetitions and move the ifdefs
> out of the function?
> 	power_failed |= axp_set_rail(dcdc1, DCDC1);
> and assemble the function name and CONFIG_ symbol in that macro, plus
> having the guard there?
> 
>>  
>>  #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
>> -	defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
>> -	defined CONFIG_AXP818_POWER
>> +	defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
>> +	defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
>>  	power_failed = axp_init();
>>  
>>  #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
>>  	defined CONFIG_AXP818_POWER
>>  	power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
>>  #endif
>> +#if !defined(CONFIG_AXP305_POWER)
>>  	power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
>>  	power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
>> +#endif
>>  #if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
>>  	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
>>  #endif
>> @@ -656,8 +658,10 @@ void sunxi_board_init(void)
>>  	defined CONFIG_AXP818_POWER
>>  	power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
>>  #endif
>> +#if !defined(CONFIG_AXP305_POWER)
>>  	power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
>> -#if !defined(CONFIG_AXP152_POWER)
>> +#endif
>> +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER)
>>  	power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
>>  #endif
>>  #ifdef CONFIG_AXP209_POWER
> 
> Verified this hunk by playing CPP and removing all non-applicable calls.
> This ended up in:
> 	power_failed = axp_init();
> 	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
> 
> Which looks like the idea behind this patch, but is totally non-obvious
> from the diff.
> 
>> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
>> index 02050f6f3569..d17cf2d9112a 100644
>> --- a/drivers/power/Kconfig
>> +++ b/drivers/power/Kconfig
>> @@ -48,6 +48,15 @@ config AXP221_POWER
>>  	Select this to enable support for the axp221/axp223 pmic found on most
>>  	A23 and A31 boards.
>>  
>> +config AXP305_POWER
>> +	bool "axp305 pmic support"
>> +	depends on MACH_SUN50I_H616
>> +	select AXP_PMIC_BUS
>> +	select CMD_POWEROFF
>> +	---help---
>> +	Select this to enable support for the axp305 pmic found on most
>> +	H616 boards.
>> +
>>  config AXP809_POWER
>>  	bool "axp809 pmic support"
>>  	depends on MACH_SUN9I
>> @@ -127,11 +136,12 @@ config AXP_DCDC3_VOLT
>>  
>>  config AXP_DCDC4_VOLT
>>  	int "axp pmic dcdc4 voltage"
>> -	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER
>> +	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP305_POWER
>>  	default 1250 if AXP152_POWER
>>  	default 1200 if MACH_SUN6I
>>  	default 0 if MACH_SUN8I
>>  	default 900 if MACH_SUN9I
>> +	default 1500 if AXP305_POWER
>>  	---help---
>>  	Set the voltage (mV) to program the axp pmic dcdc4 at, set to 0 to
>>  	disable dcdc4.
>> @@ -140,6 +150,7 @@ config AXP_DCDC4_VOLT
>>  	On A23 / A33 boards dcdc4 is unused and should be disabled.
>>  	On A80 boards dcdc4 powers VDD-SYS, HDMI, USB OTG and should be 0.9V.
>>  	On A83T boards dcdc4 is used for VDD-GPU.
>> +	On H616 boards dcdcd is used for VCC-DRAM.
>>  
>>  config AXP_DCDC5_VOLT
>>  	int "axp pmic dcdc5 voltage"
>> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
>> index 2dcc7bb99d02..0bef06920a7d 100644
>> --- a/drivers/power/Makefile
>> +++ b/drivers/power/Makefile
>> @@ -6,6 +6,7 @@
>>  obj-$(CONFIG_AXP152_POWER)	+= axp152.o
>>  obj-$(CONFIG_AXP209_POWER)	+= axp209.o
>>  obj-$(CONFIG_AXP221_POWER)	+= axp221.o
>> +obj-$(CONFIG_AXP305_POWER)	+= axp305.o
>>  obj-$(CONFIG_AXP809_POWER)	+= axp809.o
>>  obj-$(CONFIG_AXP818_POWER)	+= axp818.o
>>  obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
>> diff --git a/drivers/power/axp305.c b/drivers/power/axp305.c
>> new file mode 100644
>> index 000000000000..f620798bb1d7
>> --- /dev/null
>> +++ b/drivers/power/axp305.c
>> @@ -0,0 +1,80 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * AXP305 driver
>> + *
>> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
>> + *
>> + * Based on axp221.c
> 
> Given that, I wonder if we can (later) simplify this, ideally we end up
> at something like this:
> const struct axp_regulator axp_regulators[] = {
> 	{"dcdc1", 1600, 3400, 100, NA, 0x20, 0x10, 0},
> 	...
> https://protect2.fireeye.com/v1/url?k=d54639fd-8add0072-d547b2b2-0cc47a31307c-01fd70f5628c90cc&q=1&e=594dac17-d975-498f-b06b-149370c2c809&u=https%3A%2F%2Fgit.trustedfirmware.org%2FTF-A%2Ftrusted-firmware-a.git%2Ftree%2Fdrivers%2Fallwinner%2Faxp%2Faxp803.c
> 
> Not sure that can cover all AXP chips, but it's worth a try to remove
> all this boilerplate.
> 
> Cheers,
> Andre
> 
> 
>> + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
>> + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
>> + */
>> +
>> +#include <common.h>
>> +#include <command.h>
>> +#include <errno.h>
>> +#include <asm/arch/pmic_bus.h>
>> +#include <axp_pmic.h>
>> +
>> +static u8 axp305_mvolt_to_cfg(int mvolt, int min, int max, int div)
>> +{
>> +	if (mvolt < min)
>> +		mvolt = min;
>> +	else if (mvolt > max)
>> +		mvolt = max;
>> +
>> +	return  (mvolt - min) / div;
>> +}
>> +
>> +int axp_set_dcdc4(unsigned int mvolt)
>> +{
>> +	int ret;
>> +	u8 cfg;
>> +
>> +	if (mvolt >= 1600)
>> +		cfg = 46 + axp305_mvolt_to_cfg(mvolt, 1600, 3300, 100);
>> +	else
>> +		cfg = axp305_mvolt_to_cfg(mvolt, 600, 1500, 20);
>> +
>> +	if (mvolt == 0)
>> +		return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1,
>> +					AXP305_OUTPUT_CTRL1_DCDCD_EN);
>> +
>> +	ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return pmic_bus_setbits(AXP305_OUTPUT_CTRL1,
>> +				AXP305_OUTPUT_CTRL1_DCDCD_EN);
>> +}
>> +
>> +int axp_init(void)
>> +{
>> +	u8 axp_chip_id;
>> +	int ret;
>> +
>> +	ret = pmic_bus_init();
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x40)
>> +		return -ENODEV;
>> +
>> +	return ret;
>> +}
>> +
>> +#ifndef CONFIG_PSCI_RESET
>> +int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>> +{
>> +	pmic_bus_write(AXP305_SHUTDOWN, AXP305_POWEROFF);
>> +
>> +	/* infinite loop during shutdown */
>> +	while (1) {}
>> +
>> +	/* not reached */
>> +	return 0;
>> +}
>> +#endif
>> diff --git a/include/axp305.h b/include/axp305.h
>> new file mode 100644
>> index 000000000000..225c5040a322
>> --- /dev/null
>> +++ b/include/axp305.h
>> @@ -0,0 +1,17 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
>> + */
>> +
>> +enum axp305_reg {
>> +	AXP305_CHIP_VERSION = 0x3,
>> +	AXP305_OUTPUT_CTRL1 = 0x10,
>> +	AXP305_DCDCD_VOLTAGE = 0x15,
>> +	AXP305_SHUTDOWN = 0x32,
>> +};
>> +
>> +#define AXP305_CHIP_VERSION_MASK	0xcf
>> +
>> +#define AXP305_OUTPUT_CTRL1_DCDCD_EN	(1 << 3)
>> +
>> +#define AXP305_POWEROFF			(1 << 7)
>> diff --git a/include/axp_pmic.h b/include/axp_pmic.h
>> index 10091d0bb278..405044c3a32f 100644
>> --- a/include/axp_pmic.h
>> +++ b/include/axp_pmic.h
>> @@ -15,6 +15,9 @@
>>  #ifdef CONFIG_AXP221_POWER
>>  #include <axp221.h>
>>  #endif
>> +#ifdef CONFIG_AXP305_POWER
>> +#include <axp305.h>
>> +#endif
>>  #ifdef CONFIG_AXP809_POWER
>>  #include <axp809.h>
>>  #endif
>>
> 
> 

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

* [linux-sunxi] [PATCH 05/17] sunxi: prcm: Add memory map for H6 like SoCs
  2021-01-04  0:03   ` [linux-sunxi] " Samuel Holland
@ 2021-01-11 16:13     ` Jernej Škrabec
  0 siblings, 0 replies; 48+ messages in thread
From: Jernej Škrabec @ 2021-01-11 16:13 UTC (permalink / raw)
  To: u-boot

Dne ponedeljek, 04. januar 2021 ob 01:03:17 CET je Samuel Holland napisal(a):
> On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> > There was no need to have prcm definitions for H6 and similar SoCs till
> > now. However, support R_I2C will be needed soon in SPL.
> > 
> > Move old definitions to prcm_sun6i.h and add new ones in prcm_sun50i.h.
> > One of those files will be selected in common prcm.h based on defined
> > macros.
> > 
> > This commit doesn't do any functional change.
> > 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> >  arch/arm/include/asm/arch-sunxi/prcm.h        | 249 +-----------------
> >  arch/arm/include/asm/arch-sunxi/prcm_sun50i.h |  41 +++
> >  arch/arm/include/asm/arch-sunxi/prcm_sun6i.h  | 247 +++++++++++++++++
> >  3 files changed, 298 insertions(+), 239 deletions(-)
> >  create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
> >  create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun6i.h
> > 
> > diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/
arch-sunxi/prcm.h
> > index 767d1ff98d74..5106076f5e91 100644
> > --- a/arch/arm/include/asm/arch-sunxi/prcm.h
> > +++ b/arch/arm/include/asm/arch-sunxi/prcm.h
> > @@ -1,247 +1,18 @@
> >  /* SPDX-License-Identifier: GPL-2.0+ */
> >  /*
> > - * Sunxi A31 Power Management Unit register definition.
> > + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
> >   *
> > - * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
> > - * http://linux-sunxi.org
> > - * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
> > - * Berg Xing <bergxing@allwinnertech.com>
> > - * Tom Cubie <tangliang@allwinnertech.com>
> > + * Sunxi platform prcm register definition.
> >   */
> >  
> >  #ifndef _SUNXI_PRCM_H
> >  #define _SUNXI_PRCM_H
> >  
> > -#define __PRCM_CPUS_CFG_PRE(n) (((n) & 0x3) << 4)
> > -#define PRCM_CPUS_CFG_PRE_MASK __PRCM_CPUS_CFG_PRE(0x3)
> > -#define __PRCM_CPUS_CFG_PRE_DIV(n) (((n) >> 1) - 1)
> > -#define PRCM_CPUS_CFG_PRE_DIV(n) \
> > -	__PRCM_CPUS_CFG_PRE(__PRCM_CPUS_CFG_CLK_PRE(n))
> > -#define __PRCM_CPUS_CFG_POST(n) (((n) & 0x1f) << 8)
> > -#define PRCM_CPUS_CFG_POST_MASK __PRCM_CPUS_CFG_POST(0x1f)
> > -#define __PRCM_CPUS_CFG_POST_DIV(n) ((n) - 1)
> > -#define PRCM_CPUS_CFG_POST_DIV(n) \
> > -	__PRCM_CPUS_CFG_POST_DIV(__PRCM_CPUS_CFG_POST_DIV(n))
> > -#define __PRCM_CPUS_CFG_CLK_SRC(n) (((n) & 0x3) << 16)
> > -#define PRCM_CPUS_CFG_CLK_SRC_MASK __PRCM_CPUS_CFG_CLK_SRC(0x3)
> > -#define __PRCM_CPUS_CFG_CLK_SRC_LOSC 0x0
> > -#define __PRCM_CPUS_CFG_CLK_SRC_HOSC 0x1
> > -#define __PRCM_CPUS_CFG_CLK_SRC_PLL6 0x2
> > -#define __PRCM_CPUS_CFG_CLK_SRC_PDIV 0x3
> > -#define PRCM_CPUS_CFG_CLK_SRC_LOSC \
> > -	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_LOSC)
> > -#define PRCM_CPUS_CFG_CLK_SRC_HOSC \
> > -	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_HOSC)
> > -#define PRCM_CPUS_CFG_CLK_SRC_PLL6 \
> > -	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PLL6)
> > -#define PRCM_CPUS_CFG_CLK_SRC_PDIV \
> > -	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PDIV)
> > -
> > -#define __PRCM_APB0_RATIO(n) (((n) & 0x3) << 0)
> > -#define PRCM_APB0_RATIO_DIV_MASK __PRCM_APB0_RATIO_DIV(0x3)
> > -#define __PRCM_APB0_RATIO_DIV(n) (((n) >> 1) - 1)
> > -#define PRCM_APB0_RATIO_DIV(n) \
> > -	__PRCM_APB0_RATIO(__PRCM_APB0_RATIO_DIV(n))
> > -
> > -#define PRCM_CPU_CFG_NEON_CLK_EN (0x1 << 0)
> > -#define PRCM_CPU_CFG_CPU_CLK_EN (0x1 << 1)
> > -
> > -#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)		/* 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)
> > -
> > -#define PRCM_APB0_RESET_PIO (0x1 << 0)
> > -#define PRCM_APB0_RESET_IR (0x1 << 1)
> > -#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
> > -#define PRCM_APB0_RESET_P2WI (0x1 << 3)
> > -#define PRCM_APB0_RESET_UART (0x1 << 4)
> > -#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
> > -#define PRCM_APB0_RESET_I2C (0x1 << 6)
> > -
> > -#define PRCM_PLL_CTRL_PLL_BIAS (0x1 << 0)
> > -#define PRCM_PLL_CTRL_HOSC_GAIN_ENH (0x1 << 1)
> > -#define __PRCM_PLL_CTRL_USB_CLK_SRC(n) (((n) & 0x3) << 4)
> > -#define PRCM_PLL_CTRL_USB_CLK_SRC_MASK \
> > -	__PRCM_PLL_CTRL_USB_CLK_SRC(0x3)
> > -#define __PRCM_PLL_CTRL_USB_CLK_0 0x0
> > -#define __PRCM_PLL_CTRL_USB_CLK_1 0x1
> > -#define __PRCM_PLL_CTRL_USB_CLK_2 0x2
> > -#define __PRCM_PLL_CTRL_USB_CLK_3 0x3
> > -#define PRCM_PLL_CTRL_USB_CLK_0 \
> > -	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_0)
> > -#define PRCM_PLL_CTRL_USB_CLK_1 \
> > -	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_1)
> > -#define PRCM_PLL_CTRL_USB_CLK_2 \
> > -	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_2)
> > -#define PRCM_PLL_CTRL_USB_CLK_3 \
> > -	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_3)
> > -#define __PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) (((n) & 0x3) << 12)
> > -#define PRCM_PLL_CTRL_INT_PLL_IN_SEL_MASK \
> > -	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(0x3)
> > -#define PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) \
> > -	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(n)
> > -#define __PRCM_PLL_CTRL_HOSC_CLK_SEL(n) (((n) & 0x3) << 20)
> > -#define PRCM_PLL_CTRL_HOSC_CLK_SEL_MASK \
> > -	__PRCM_PLL_CTRL_HOSC_CLK_SEL(0x3)
> > -#define __PRCM_PLL_CTRL_HOSC_CLK_0 0x0
> > -#define __PRCM_PLL_CTRL_HOSC_CLK_1 0x1
> > -#define __PRCM_PLL_CTRL_HOSC_CLK_2 0x2
> > -#define __PRCM_PLL_CTRL_HOSC_CLK_3 0x3
> > -#define PRCM_PLL_CTRL_HOSC_CLK_0 \
> > -	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_0)
> > -#define PRCM_PLL_CTRL_HOSC_CLK_1 \
> > -	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_1)
> > -#define PRCM_PLL_CTRL_HOSC_CLK_2 \
> > -	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_2)
> > -#define PRCM_PLL_CTRL_HOSC_CLK_3 \
> > -	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_3)
> > -#define PRCM_PLL_CTRL_PLL_TST_SRC_EXT (0x1 << 24)
> > -#define PRCM_PLL_CTRL_LDO_DIGITAL_EN (0x1 << 0)
> > -#define PRCM_PLL_CTRL_LDO_ANALOG_EN (0x1 << 1)
> > -#define PRCM_PLL_CTRL_EXT_OSC_EN (0x1 << 2)
> > -#define PRCM_PLL_CTRL_CLK_TST_EN (0x1 << 3)
> > -#define PRCM_PLL_CTRL_IN_PWR_HIGH (0x1 << 15) /* 3.3 for hi 2.5 for lo */
> > -#define __PRCM_PLL_CTRL_VDD_LDO_OUT(n) (((n) & 0x7) << 16)
> > -#define PRCM_PLL_CTRL_LDO_OUT_MASK \
> > -	__PRCM_PLL_CTRL_LDO_OUT(0x7)
> > -/* When using the low voltage 20 mV steps, and high voltage 30 mV steps 
*/
> > -#define PRCM_PLL_CTRL_LDO_OUT_L(n) \
> > -	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1000) / 20) & 0x7)
> > -#define PRCM_PLL_CTRL_LDO_OUT_H(n) \
> > -	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1160) / 30) & 0x7)
> > -#define PRCM_PLL_CTRL_LDO_OUT_LV(n) \
> > -	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 20) + 1000)
> > -#define PRCM_PLL_CTRL_LDO_OUT_HV(n) \
> > -	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 30) + 1160)
> > -#define PRCM_PLL_CTRL_LDO_KEY (0xa7 << 24)
> > -#define PRCM_PLL_CTRL_LDO_KEY_MASK (0xff << 24)
> > -
> > -#define PRCM_CLK_1WIRE_GATE (0x1 << 31)
> > -
> > -#define __PRCM_CLK_MOD0_M(n) (((n) & 0xf) << 0)
> > -#define PRCM_CLK_MOD0_M_MASK __PRCM_CLK_MOD0_M(0xf)
> > -#define __PRCM_CLK_MOD0_M_X(n) (n - 1)
> > -#define PRCM_CLK_MOD0_M(n) __PRCM_CLK_MOD0_M(__PRCM_CLK_MOD0_M_X(n))
> > -#define PRCM_CLK_MOD0_OUT_PHASE(n) (((n) & 0x7) << 8)
> > -#define PRCM_CLK_MOD0_OUT_PHASE_MASK(n) PRCM_CLK_MOD0_OUT_PHASE(0x7)
> > -#define _PRCM_CLK_MOD0_N(n) (((n) & 0x3) << 16)
> > -#define PRCM_CLK_MOD0_N_MASK __PRCM_CLK_MOD_N(0x3)
> > -#define __PRCM_CLK_MOD0_N_X(n) (((n) >> 1) - 1)
> > -#define PRCM_CLK_MOD0_N(n) __PRCM_CLK_MOD0_N(__PRCM_CLK_MOD0_N_X(n))
> > -#define PRCM_CLK_MOD0_SMPL_PHASE(n) (((n) & 0x7) << 20)
> > -#define PRCM_CLK_MOD0_SMPL_PHASE_MASK PRCM_CLK_MOD0_SMPL_PHASE(0x7)
> > -#define PRCM_CLK_MOD0_SRC_SEL(n) (((n) & 0x7) << 24)
> > -#define PRCM_CLK_MOD0_SRC_SEL_MASK PRCM_CLK_MOD0_SRC_SEL(0x7)
> > -#define PRCM_CLK_MOD0_GATE_EN (0x1 << 31)
> > -
> > -#define PRCM_APB0_RESET_PIO (0x1 << 0)
> > -#define PRCM_APB0_RESET_IR (0x1 << 1)
> > -#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
> > -#define PRCM_APB0_RESET_P2WI (0x1 << 3)
> > -#define PRCM_APB0_RESET_UART (0x1 << 4)
> > -#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
> > -#define PRCM_APB0_RESET_I2C (0x1 << 6)
> > -
> > -#define __PRCM_CLK_OUTD_M(n) (((n) & 0x7) << 8)
> > -#define PRCM_CLK_OUTD_M_MASK __PRCM_CLK_OUTD_M(0x7)
> > -#define __PRCM_CLK_OUTD_M_X() ((n) - 1)
> > -#define PRCM_CLK_OUTD_M(n) __PRCM_CLK_OUTD_M(__PRCM_CLK_OUTD_M_X(n))
> > -#define __PRCM_CLK_OUTD_N(n) (((n) & 0x7) << 20)
> > -#define PRCM_CLK_OUTD_N_MASK __PRCM_CLK_OUTD_N(0x7)
> > -#define __PRCM_CLK_OUTD_N_X(n) (((n) >> 1) - 1)
> > -#define PRCM_CLK_OUTD_N(n) __PRCM_CLK_OUTD_N(__PRCM_CLK_OUTD_N_X(n)
> > -#define __PRCM_CLK_OUTD_SRC_SEL(n) (((n) & 0x3) << 24)
> > -#define PRCM_CLK_OUTD_SRC_SEL_MASK __PRCM_CLK_OUTD_SRC_SEL(0x3)
> > -#define __PRCM_CLK_OUTD_SRC_LOSC2 0x0
> > -#define __PRCM_CLK_OUTD_SRC_LOSC 0x1
> > -#define __PRCM_CLK_OUTD_SRC_HOSC 0x2
> > -#define __PRCM_CLK_OUTD_SRC_ERR 0x3
> > -#define PRCM_CLK_OUTD_SRC_LOSC2 \
> > -#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC2)
> > -#define PRCM_CLK_OUTD_SRC_LOSC \
> > -#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC)
> > -#define PRCM_CLK_OUTD_SRC_HOSC \
> > -#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_HOSC)
> > -#define PRCM_CLK_OUTD_SRC_ERR \
> > -#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_ERR)
> > -#define PRCM_CLK_OUTD_EN (0x1 << 31)
> > -
> > -#define PRCM_CPU0_PWROFF (0x1 << 0)
> > -#define PRCM_CPU1_PWROFF (0x1 << 1)
> > -#define PRCM_CPU2_PWROFF (0x1 << 2)
> > -#define PRCM_CPU3_PWROFF (0x1 << 3)
> > -#define PRCM_CPU_ALL_PWROFF (0xf << 0)
> > -
> > -#define PRCM_VDD_SYS_DRAM_CH0_PAD_HOLD_PWROFF (0x1 << 0)
> > -#define PRCM_VDD_SYS_DRAM_CH1_PAD_HOLD_PWROFF (0x1 << 1)
> > -#define PRCM_VDD_SYS_AVCC_A_PWROFF (0x1 << 2)
> > -#define PRCM_VDD_SYS_CPU0_VDD_PWROFF (0x1 << 3)
> > -
> > -#define PRCM_VDD_GPU_PWROFF (0x1 << 0)
> > -
> > -#define PRCM_VDD_SYS_RESET (0x1 << 0)
> > -
> > -#define PRCM_CPU1_PWR_CLAMP(n) (((n) & 0xff) << 0)
> > -#define PRCM_CPU1_PWR_CLAMP_MASK PRCM_CPU1_PWR_CLAMP(0xff)
> > -
> > -#define PRCM_CPU2_PWR_CLAMP(n) (((n) & 0xff) << 0)
> > -#define PRCM_CPU2_PWR_CLAMP_MASK PRCM_CPU2_PWR_CLAMP(0xff)
> > -
> > -#define PRCM_CPU3_PWR_CLAMP(n) (((n) & 0xff) << 0)
> > -#define PRCM_CPU3_PWR_CLAMP_MASK PRCM_CPU3_PWR_CLAMP(0xff)
> > -
> > -#define PRCM_SEC_SWITCH_APB0_CLK_NONSEC (0x1 << 0)
> > -#define PRCM_SEC_SWITCH_PLL_CFG_NONSEC (0x1 << 1)
> > -#define PRCM_SEC_SWITCH_PWR_GATE_NONSEC (0x1 << 2)
> > -
> > -#ifndef __ASSEMBLY__
> > -#include <linux/compiler.h>
> > -
> > -struct sunxi_prcm_reg {
> > -	u32 cpus_cfg;		/* 0x000 */
> > -	u8 res0[0x8];		/* 0x004 */
> > -	u32 apb0_ratio;		/* 0x00c */
> > -	u32 cpu0_cfg;		/* 0x010 */
> > -	u32 cpu1_cfg;		/* 0x014 */
> > -	u32 cpu2_cfg;		/* 0x018 */
> > -	u32 cpu3_cfg;		/* 0x01c */
> > -	u8 res1[0x8];		/* 0x020 */
> > -	u32 apb0_gate;		/* 0x028 */
> > -	u8 res2[0x14];		/* 0x02c */
> > -	u32 pll_ctrl0;		/* 0x040 */
> > -	u32 pll_ctrl1;		/* 0x044 */
> > -	u8 res3[0x8];		/* 0x048 */
> > -	u32 clk_1wire;		/* 0x050 */
> > -	u32 clk_ir;		/* 0x054 */
> > -	u8 res4[0x58];		/* 0x058 */
> > -	u32 apb0_reset;		/* 0x0b0 */
> > -	u8 res5[0x3c];		/* 0x0b4 */
> > -	u32 clk_outd;		/* 0x0f0 */
> > -	u8 res6[0xc];		/* 0x0f4 */
> > -	u32 cpu_pwroff;		/* 0x100 */
> > -	u8 res7[0xc];		/* 0x104 */
> > -	u32 vdd_sys_pwroff;	/* 0x110 */
> > -	u8 res8[0x4];		/* 0x114 */
> > -	u32 gpu_pwroff;		/* 0x118 */
> > -	u8 res9[0x4];		/* 0x11c */
> > -	u32 vdd_pwr_reset;	/* 0x120 */
> > -	u8 res10[0x1c];		/* 0x124 */
> > -	u32 cpu_pwr_clamp[4];	/* 0x140 but first one is actually unused 
*/
> > -	u8 res11[0x30];		/* 0x150 */
> > -	u32 dram_pwr;		/* 0x180 */
> > -	u8 res12[0xc];		/* 0x184 */
> > -	u32 dram_tst;		/* 0x190 */
> > -	u8 res13[0x3c];		/* 0x194 */
> > -	u32 prcm_sec_switch;	/* 0x1d0 */
> > -};
> > -
> > -void prcm_apb0_enable(u32 flags);
> > -void prcm_apb0_disable(u32 flags);
> > -
> > -#endif /* __ASSEMBLY__ */
> > -#endif /* _PRCM_H */
> > +/* prcm regs definition */
> > +#if defined(CONFIG_SUN50I_GEN_H6)
> > +#include <asm/arch/prcm_sun50i.h>
> > +#else
> > +#include <asm/arch/prcm_sun6i.h>
> > +#endif
> > +
> > +#endif /* _SUNXI_PRCM_H */
> > diff --git a/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h b/arch/arm/
include/asm/arch-sunxi/prcm_sun50i.h
> > new file mode 100644
> > index 000000000000..68a78e50ce64
> > --- /dev/null
> > +++ b/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
> > @@ -0,0 +1,41 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Sunxi H6 Power Management Unit register definition.
> > + *
> > + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
> > + */
> > +
> > +#ifndef _SUN50I_PRCM_H
> > +#define _SUN50I_PRCM_H
> > +
> > +#ifndef __ASSEMBLY__
> > +#include <linux/compiler.h>
> > +
> > +struct sunxi_prcm_reg {
> > +	u32 cpus_cfg;		/* 0x000 */
> > +	u8 res0[0x8];		/* 0x004 */
> > +	u32 apbs1_cfg;		/* 0x00c */
> > +	u32 apbs2_cfg;		/* 0x010 */
> > +	u8 res1[0x118];		/* 0x014 */
> > +	u32 wdg_gate_reset;	/* 0x12c */
> 
> This is the register for R_TWD, not R_WDOG.
> 
> And out of curiosity, were you intending to include all PRCM registers,
> or just those present on both H6 and H616? (H6 also has TIMER, PWM and
> UART.)

I think I went over some BSP sources. Anyway, I'll update this structure to 
cover both SoCs. Not sure if most of definitions will be ever used, but I'll 
include them for the sake of completeness.

> 
> > +	u8 res2[0x6c];		/* 0x130 */
> > +	u32 twi_gate_reset;	/* 0x19c */
> > +	u8 res3[0x1c];		/* 0x1a0 */
> > +	u32 rsb_gate_reset;	/* 0x1bc */
> > +	u32 cir_cfg;		/* 0x1c0 */
> > +	u8 res4[0x8];		/* 0x1c4 */
> > +	u32 cir_gate_reset;	/* 0x1cc */
> > +	u8 res5[0x10];		/* 0x1d0 */
> > +	u32 w1_cfg;		/* 0x1e0 */
> > +	u8 res6[0x8];		/* 0x1e4 */
> > +	u32 w1_gate_reset;	/* 0x1ec */
> > +	u8 res7[0x1c];		/* 0x1f0 */
> > +	u32 rtc_gate_reset;	/* 0x20c */
> > +};
> > +check_member(sunxi_prcm_reg, rtc_gate_reset, 0x20c);
> > +
> > +#define PRCM_TWI_GATE		(1 << 0)
> > +#define PRCM_TWI_RESET		(1 << 16)
> > +
> > +#endif /* __ASSEMBLY__ */
> > +#endif /* _PRCM_H */
> > diff --git a/arch/arm/include/asm/arch-sunxi/prcm_sun6i.h b/arch/arm/
include/asm/arch-sunxi/prcm_sun6i.h
> > new file mode 100644
> > index 000000000000..ab664e80bbe8
> > --- /dev/null
> > +++ b/arch/arm/include/asm/arch-sunxi/prcm_sun6i.h
> > @@ -0,0 +1,247 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Sunxi A31 Power Management Unit register definition.
> > + *
> > + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
> > + * http://linux-sunxi.org
> > + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
> > + * Berg Xing <bergxing@allwinnertech.com>
> > + * Tom Cubie <tangliang@allwinnertech.com>
> > + */
> > +
> > +#ifndef _SUN6I_PRCM_H
> > +#define _SUN6I_PRCM_H
> > +
> > +#define __PRCM_CPUS_CFG_PRE(n) (((n) & 0x3) << 4)
> > +#define PRCM_CPUS_CFG_PRE_MASK __PRCM_CPUS_CFG_PRE(0x3)
> > +#define __PRCM_CPUS_CFG_PRE_DIV(n) (((n) >> 1) - 1)
> > +#define PRCM_CPUS_CFG_PRE_DIV(n) \
> > +	__PRCM_CPUS_CFG_PRE(__PRCM_CPUS_CFG_CLK_PRE(n))
> > +#define __PRCM_CPUS_CFG_POST(n) (((n) & 0x1f) << 8)
> > +#define PRCM_CPUS_CFG_POST_MASK __PRCM_CPUS_CFG_POST(0x1f)
> > +#define __PRCM_CPUS_CFG_POST_DIV(n) ((n) - 1)
> > +#define PRCM_CPUS_CFG_POST_DIV(n) \
> > +	__PRCM_CPUS_CFG_POST_DIV(__PRCM_CPUS_CFG_POST_DIV(n))
> > +#define __PRCM_CPUS_CFG_CLK_SRC(n) (((n) & 0x3) << 16)
> > +#define PRCM_CPUS_CFG_CLK_SRC_MASK __PRCM_CPUS_CFG_CLK_SRC(0x3)
> > +#define __PRCM_CPUS_CFG_CLK_SRC_LOSC 0x0
> > +#define __PRCM_CPUS_CFG_CLK_SRC_HOSC 0x1
> > +#define __PRCM_CPUS_CFG_CLK_SRC_PLL6 0x2
> > +#define __PRCM_CPUS_CFG_CLK_SRC_PDIV 0x3
> > +#define PRCM_CPUS_CFG_CLK_SRC_LOSC \
> > +	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_LOSC)
> > +#define PRCM_CPUS_CFG_CLK_SRC_HOSC \
> > +	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_HOSC)
> > +#define PRCM_CPUS_CFG_CLK_SRC_PLL6 \
> > +	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PLL6)
> > +#define PRCM_CPUS_CFG_CLK_SRC_PDIV \
> > +	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PDIV)
> > +
> > +#define __PRCM_APB0_RATIO(n) (((n) & 0x3) << 0)
> > +#define PRCM_APB0_RATIO_DIV_MASK __PRCM_APB0_RATIO_DIV(0x3)
> > +#define __PRCM_APB0_RATIO_DIV(n) (((n) >> 1) - 1)
> > +#define PRCM_APB0_RATIO_DIV(n) \
> > +	__PRCM_APB0_RATIO(__PRCM_APB0_RATIO_DIV(n))
> > +
> > +#define PRCM_CPU_CFG_NEON_CLK_EN (0x1 << 0)
> > +#define PRCM_CPU_CFG_CPU_CLK_EN (0x1 << 1)
> > +
> > +#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)		/* 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)
> > +
> > +#define PRCM_APB0_RESET_PIO (0x1 << 0)
> > +#define PRCM_APB0_RESET_IR (0x1 << 1)
> > +#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
> > +#define PRCM_APB0_RESET_P2WI (0x1 << 3)
> > +#define PRCM_APB0_RESET_UART (0x1 << 4)
> > +#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
> > +#define PRCM_APB0_RESET_I2C (0x1 << 6)
> > +
> > +#define PRCM_PLL_CTRL_PLL_BIAS (0x1 << 0)
> > +#define PRCM_PLL_CTRL_HOSC_GAIN_ENH (0x1 << 1)
> > +#define __PRCM_PLL_CTRL_USB_CLK_SRC(n) (((n) & 0x3) << 4)
> > +#define PRCM_PLL_CTRL_USB_CLK_SRC_MASK \
> > +	__PRCM_PLL_CTRL_USB_CLK_SRC(0x3)
> > +#define __PRCM_PLL_CTRL_USB_CLK_0 0x0
> > +#define __PRCM_PLL_CTRL_USB_CLK_1 0x1
> > +#define __PRCM_PLL_CTRL_USB_CLK_2 0x2
> > +#define __PRCM_PLL_CTRL_USB_CLK_3 0x3
> > +#define PRCM_PLL_CTRL_USB_CLK_0 \
> > +	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_0)
> > +#define PRCM_PLL_CTRL_USB_CLK_1 \
> > +	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_1)
> > +#define PRCM_PLL_CTRL_USB_CLK_2 \
> > +	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_2)
> > +#define PRCM_PLL_CTRL_USB_CLK_3 \
> > +	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_3)
> > +#define __PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) (((n) & 0x3) << 12)
> > +#define PRCM_PLL_CTRL_INT_PLL_IN_SEL_MASK \
> > +	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(0x3)
> > +#define PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) \
> > +	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(n)
> > +#define __PRCM_PLL_CTRL_HOSC_CLK_SEL(n) (((n) & 0x3) << 20)
> > +#define PRCM_PLL_CTRL_HOSC_CLK_SEL_MASK \
> > +	__PRCM_PLL_CTRL_HOSC_CLK_SEL(0x3)
> > +#define __PRCM_PLL_CTRL_HOSC_CLK_0 0x0
> > +#define __PRCM_PLL_CTRL_HOSC_CLK_1 0x1
> > +#define __PRCM_PLL_CTRL_HOSC_CLK_2 0x2
> > +#define __PRCM_PLL_CTRL_HOSC_CLK_3 0x3
> > +#define PRCM_PLL_CTRL_HOSC_CLK_0 \
> > +	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_0)
> > +#define PRCM_PLL_CTRL_HOSC_CLK_1 \
> > +	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_1)
> > +#define PRCM_PLL_CTRL_HOSC_CLK_2 \
> > +	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_2)
> > +#define PRCM_PLL_CTRL_HOSC_CLK_3 \
> > +	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_3)
> > +#define PRCM_PLL_CTRL_PLL_TST_SRC_EXT (0x1 << 24)
> > +#define PRCM_PLL_CTRL_LDO_DIGITAL_EN (0x1 << 0)
> > +#define PRCM_PLL_CTRL_LDO_ANALOG_EN (0x1 << 1)
> > +#define PRCM_PLL_CTRL_EXT_OSC_EN (0x1 << 2)
> > +#define PRCM_PLL_CTRL_CLK_TST_EN (0x1 << 3)
> > +#define PRCM_PLL_CTRL_IN_PWR_HIGH (0x1 << 15) /* 3.3 for hi 2.5 for lo */
> > +#define __PRCM_PLL_CTRL_VDD_LDO_OUT(n) (((n) & 0x7) << 16)
> > +#define PRCM_PLL_CTRL_LDO_OUT_MASK \
> > +	__PRCM_PLL_CTRL_LDO_OUT(0x7)
> > +/* When using the low voltage 20 mV steps, and high voltage 30 mV steps 
*/
> > +#define PRCM_PLL_CTRL_LDO_OUT_L(n) \
> > +	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1000) / 20) & 0x7)
> > +#define PRCM_PLL_CTRL_LDO_OUT_H(n) \
> > +	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1160) / 30) & 0x7)
> > +#define PRCM_PLL_CTRL_LDO_OUT_LV(n) \
> > +	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 20) + 1000)
> > +#define PRCM_PLL_CTRL_LDO_OUT_HV(n) \
> > +	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 30) + 1160)
> > +#define PRCM_PLL_CTRL_LDO_KEY (0xa7 << 24)
> > +#define PRCM_PLL_CTRL_LDO_KEY_MASK (0xff << 24)
> > +
> > +#define PRCM_CLK_1WIRE_GATE (0x1 << 31)
> > +
> > +#define __PRCM_CLK_MOD0_M(n) (((n) & 0xf) << 0)
> > +#define PRCM_CLK_MOD0_M_MASK __PRCM_CLK_MOD0_M(0xf)
> > +#define __PRCM_CLK_MOD0_M_X(n) (n - 1)
> > +#define PRCM_CLK_MOD0_M(n) __PRCM_CLK_MOD0_M(__PRCM_CLK_MOD0_M_X(n))
> > +#define PRCM_CLK_MOD0_OUT_PHASE(n) (((n) & 0x7) << 8)
> > +#define PRCM_CLK_MOD0_OUT_PHASE_MASK(n) PRCM_CLK_MOD0_OUT_PHASE(0x7)
> > +#define _PRCM_CLK_MOD0_N(n) (((n) & 0x3) << 16)
> > +#define PRCM_CLK_MOD0_N_MASK __PRCM_CLK_MOD_N(0x3)
> > +#define __PRCM_CLK_MOD0_N_X(n) (((n) >> 1) - 1)
> > +#define PRCM_CLK_MOD0_N(n) __PRCM_CLK_MOD0_N(__PRCM_CLK_MOD0_N_X(n))
> > +#define PRCM_CLK_MOD0_SMPL_PHASE(n) (((n) & 0x7) << 20)
> > +#define PRCM_CLK_MOD0_SMPL_PHASE_MASK PRCM_CLK_MOD0_SMPL_PHASE(0x7)
> > +#define PRCM_CLK_MOD0_SRC_SEL(n) (((n) & 0x7) << 24)
> > +#define PRCM_CLK_MOD0_SRC_SEL_MASK PRCM_CLK_MOD0_SRC_SEL(0x7)
> > +#define PRCM_CLK_MOD0_GATE_EN (0x1 << 31)
> > +
> > +#define PRCM_APB0_RESET_PIO (0x1 << 0)
> > +#define PRCM_APB0_RESET_IR (0x1 << 1)
> > +#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
> > +#define PRCM_APB0_RESET_P2WI (0x1 << 3)
> > +#define PRCM_APB0_RESET_UART (0x1 << 4)
> > +#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
> > +#define PRCM_APB0_RESET_I2C (0x1 << 6)
> > +
> > +#define __PRCM_CLK_OUTD_M(n) (((n) & 0x7) << 8)
> > +#define PRCM_CLK_OUTD_M_MASK __PRCM_CLK_OUTD_M(0x7)
> > +#define __PRCM_CLK_OUTD_M_X() ((n) - 1)
> > +#define PRCM_CLK_OUTD_M(n) __PRCM_CLK_OUTD_M(__PRCM_CLK_OUTD_M_X(n))
> > +#define __PRCM_CLK_OUTD_N(n) (((n) & 0x7) << 20)
> > +#define PRCM_CLK_OUTD_N_MASK __PRCM_CLK_OUTD_N(0x7)
> > +#define __PRCM_CLK_OUTD_N_X(n) (((n) >> 1) - 1)
> > +#define PRCM_CLK_OUTD_N(n) __PRCM_CLK_OUTD_N(__PRCM_CLK_OUTD_N_X(n)
> > +#define __PRCM_CLK_OUTD_SRC_SEL(n) (((n) & 0x3) << 24)
> > +#define PRCM_CLK_OUTD_SRC_SEL_MASK __PRCM_CLK_OUTD_SRC_SEL(0x3)
> > +#define __PRCM_CLK_OUTD_SRC_LOSC2 0x0
> > +#define __PRCM_CLK_OUTD_SRC_LOSC 0x1
> > +#define __PRCM_CLK_OUTD_SRC_HOSC 0x2
> > +#define __PRCM_CLK_OUTD_SRC_ERR 0x3
> > +#define PRCM_CLK_OUTD_SRC_LOSC2 \
> > +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC2)
> > +#define PRCM_CLK_OUTD_SRC_LOSC \
> > +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC)
> > +#define PRCM_CLK_OUTD_SRC_HOSC \
> > +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_HOSC)
> > +#define PRCM_CLK_OUTD_SRC_ERR \
> > +#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_ERR)
> > +#define PRCM_CLK_OUTD_EN (0x1 << 31)
> > +
> > +#define PRCM_CPU0_PWROFF (0x1 << 0)
> > +#define PRCM_CPU1_PWROFF (0x1 << 1)
> > +#define PRCM_CPU2_PWROFF (0x1 << 2)
> > +#define PRCM_CPU3_PWROFF (0x1 << 3)
> > +#define PRCM_CPU_ALL_PWROFF (0xf << 0)
> > +
> > +#define PRCM_VDD_SYS_DRAM_CH0_PAD_HOLD_PWROFF (0x1 << 0)
> > +#define PRCM_VDD_SYS_DRAM_CH1_PAD_HOLD_PWROFF (0x1 << 1)
> > +#define PRCM_VDD_SYS_AVCC_A_PWROFF (0x1 << 2)
> > +#define PRCM_VDD_SYS_CPU0_VDD_PWROFF (0x1 << 3)
> > +
> > +#define PRCM_VDD_GPU_PWROFF (0x1 << 0)
> > +
> > +#define PRCM_VDD_SYS_RESET (0x1 << 0)
> > +
> > +#define PRCM_CPU1_PWR_CLAMP(n) (((n) & 0xff) << 0)
> > +#define PRCM_CPU1_PWR_CLAMP_MASK PRCM_CPU1_PWR_CLAMP(0xff)
> > +
> > +#define PRCM_CPU2_PWR_CLAMP(n) (((n) & 0xff) << 0)
> > +#define PRCM_CPU2_PWR_CLAMP_MASK PRCM_CPU2_PWR_CLAMP(0xff)
> > +
> > +#define PRCM_CPU3_PWR_CLAMP(n) (((n) & 0xff) << 0)
> > +#define PRCM_CPU3_PWR_CLAMP_MASK PRCM_CPU3_PWR_CLAMP(0xff)
> > +
> > +#define PRCM_SEC_SWITCH_APB0_CLK_NONSEC (0x1 << 0)
> > +#define PRCM_SEC_SWITCH_PLL_CFG_NONSEC (0x1 << 1)
> > +#define PRCM_SEC_SWITCH_PWR_GATE_NONSEC (0x1 << 2)
> > +
> > +#ifndef __ASSEMBLY__
> > +#include <linux/compiler.h>
> > +
> > +struct sunxi_prcm_reg {
> > +	u32 cpus_cfg;		/* 0x000 */
> > +	u8 res0[0x8];		/* 0x004 */
> > +	u32 apb0_ratio;		/* 0x00c */
> > +	u32 cpu0_cfg;		/* 0x010 */
> > +	u32 cpu1_cfg;		/* 0x014 */
> > +	u32 cpu2_cfg;		/* 0x018 */
> > +	u32 cpu3_cfg;		/* 0x01c */
> > +	u8 res1[0x8];		/* 0x020 */
> > +	u32 apb0_gate;		/* 0x028 */
> > +	u8 res2[0x14];		/* 0x02c */
> > +	u32 pll_ctrl0;		/* 0x040 */
> > +	u32 pll_ctrl1;		/* 0x044 */
> > +	u8 res3[0x8];		/* 0x048 */
> > +	u32 clk_1wire;		/* 0x050 */
> > +	u32 clk_ir;		/* 0x054 */
> > +	u8 res4[0x58];		/* 0x058 */
> > +	u32 apb0_reset;		/* 0x0b0 */
> > +	u8 res5[0x3c];		/* 0x0b4 */
> > +	u32 clk_outd;		/* 0x0f0 */
> > +	u8 res6[0xc];		/* 0x0f4 */
> > +	u32 cpu_pwroff;		/* 0x100 */
> > +	u8 res7[0xc];		/* 0x104 */
> > +	u32 vdd_sys_pwroff;	/* 0x110 */
> > +	u8 res8[0x4];		/* 0x114 */
> > +	u32 gpu_pwroff;		/* 0x118 */
> > +	u8 res9[0x4];		/* 0x11c */
> > +	u32 vdd_pwr_reset;	/* 0x120 */
> > +	u8 res10[0x1c];		/* 0x124 */
> > +	u32 cpu_pwr_clamp[4];	/* 0x140 but first one is actually unused 
*/
> > +	u8 res11[0x30];		/* 0x150 */
> > +	u32 dram_pwr;		/* 0x180 */
> > +	u8 res12[0xc];		/* 0x184 */
> > +	u32 dram_tst;		/* 0x190 */
> > +	u8 res13[0x3c];		/* 0x194 */
> > +	u32 prcm_sec_switch;	/* 0x1d0 */
> > +};
> > +
> > +void prcm_apb0_enable(u32 flags);
> > +void prcm_apb0_disable(u32 flags);
> > +
> > +#endif /* __ASSEMBLY__ */
> > +#endif /* _PRCM_H */
> > 
> 
> 

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

* [linux-sunxi] [PATCH 07/17] sunxi: support loading with SPL > 32KB
  2021-01-04  2:02   ` [linux-sunxi] " Samuel Holland
@ 2021-01-11 18:17     ` Jernej Škrabec
  0 siblings, 0 replies; 48+ messages in thread
From: Jernej Škrabec @ 2021-01-11 18:17 UTC (permalink / raw)
  To: u-boot

Dne ponedeljek, 04. januar 2021 ob 03:02:03 CET je Samuel Holland napisal(a):
> On 1/3/21 3:26 AM, Jernej Skrabec wrote:
> > From: Andre Przywara <andre.przywara@arm.com>
> > 
> > H616 supports and needs bigger SPL than 32 KiB, mostly due to big DRAM
> > driver and need for PMIC configuration, which pull several drivers which
> > are not needed otherwise.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> >  arch/arm/mach-sunxi/board.c | 12 ++++++++++++
> >  1 file changed, 12 insertions(+)
> > 
> > diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
> > index 7a8b303f233c..296efd615769 100644
> > --- a/arch/arm/mach-sunxi/board.c
> > +++ b/arch/arm/mach-sunxi/board.c
> > @@ -277,6 +277,14 @@ uint32_t sunxi_get_boot_device(void)
> >  }
> >  
> >  #ifdef CONFIG_SPL_BUILD
> > +static u32 sunxi_get_spl_size(void)
> > +{
> > +	if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */
> > +		return 32768;
> In the context of the suggestion below, this case could return 0.
> 
> > +
> > +	return readl(SPL_ADDR + 0x10);
> > +}
> > +
> >  /*
> >   * The eGON SPL image can be located at 8KB or at 128KB into an SD card 
or
> >   * an eMMC device. The boot source has bit 4 set in the latter case.
> > @@ -286,6 +294,7 @@ uint32_t sunxi_get_boot_device(void)
> >  unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc)
> 
> As a side note, the prototype for this function was changed in commit
> cf0082559698 ("spl: mmc: Fix spl_mmc_get_uboot_raw_sector()
> implementation"), but nobody noticed since it is not in a header.
> 
> >  {
> >  	unsigned long sector = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR;
> > +	u32 spl_size = sunxi_get_spl_size();
> >  
> >  	switch (sunxi_get_boot_source()) {
> >  	case SUNXI_BOOTED_FROM_MMC0_HIGH:
> > @@ -294,6 +303,9 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc 
*mmc)
> >  		break;
> >  	}
> >  
> > +	if (spl_size > 32768)
> > +		sector += (spl_size - 32768) / 512;
> > +
> 
> What I would suggest doing instead of this is setting
> SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x40,
> SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET=0x10, and then before the
> switch statement doing:
> 
>         sector = max(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR,
>                      spl_size / 512);
> 
> Not only does this get rid of the magic 32768 constant (which is
> meaningless on new platforms), but it also works cleanly for eMMC boot
> partitions (where there's no 0x10 sector offset).

Thanks for the suggestion, this is indeed much cleaner.

Best regards,
Jernej

> 
> >  	return sector;
> >  }
> >  
> > 
> 
> Cheers,
> Samuel
> 

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

* [PATCH 01/17] sunxi: Add support for AXP305 PMIC
  2021-01-11  0:02   ` André Przywara
  2021-01-11  1:32     ` Jaehoon Chung
@ 2021-01-11 19:48     ` Jernej Škrabec
  1 sibling, 0 replies; 48+ messages in thread
From: Jernej Škrabec @ 2021-01-11 19:48 UTC (permalink / raw)
  To: u-boot

Dne ponedeljek, 11. januar 2021 ob 01:02:07 CET je Andr? Przywara napisal(a):
> On 03/01/2021 09:26, Jernej Skrabec wrote:
> > This PMIC can be found on H616 boards and it's very similar to AXP805
> > and AXP806.
> >> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> 
> The existing sunxi PMIC code is the typical U-Boot mess, but I don't
> want to block this series on a rework. I put some comments and ideas
> below how to improve the whole "framework".
> 
> For this actual patch I checked the bits against the AXP305 datasheet,
> it does what we need.
> 
> (reluctantly)
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
> 
> Thanks,
> Andre
> 
> > ---
> >  arch/arm/mach-sunxi/pmic_bus.c |  6 +++
> >  board/sunxi/board.c            | 10 +++--
> >  drivers/power/Kconfig          | 13 +++++-
> >  drivers/power/Makefile         |  1 +
> >  drivers/power/axp305.c         | 80 ++++++++++++++++++++++++++++++++++
> >  include/axp305.h               | 17 ++++++++
> >  include/axp_pmic.h             |  3 ++
> >  7 files changed, 126 insertions(+), 4 deletions(-)
> >  create mode 100644 drivers/power/axp305.c
> >  create mode 100644 include/axp305.h
> > 
> > diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/
pmic_bus.c
> > index dea42de833f1..0394ce856448 100644
> > --- a/arch/arm/mach-sunxi/pmic_bus.c
> > +++ b/arch/arm/mach-sunxi/pmic_bus.c
> > @@ -18,6 +18,8 @@
> >  
> >  #define AXP209_I2C_ADDR			0x34
> >  
> > +#define AXP305_I2C_ADDR			0x36
> > +
> >  #define AXP221_CHIP_ADDR		0x68
> >  #define AXP221_CTRL_ADDR		0x3e
> >  #define AXP221_INIT_DATA		0x3e
> > @@ -64,6 +66,8 @@ int pmic_bus_read(u8 reg, u8 *data)
> >  	return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1);
> >  #elif defined CONFIG_AXP209_POWER
> >  	return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
> > +#elif defined CONFIG_AXP305_POWER
> > +	return i2c_read(AXP305_I2C_ADDR, reg, 1, data, 1);
> >  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined 
CONFIG_AXP818_POWER
> >  # ifdef CONFIG_MACH_SUN6I
> >  	return p2wi_read(reg, data);
> > @@ -81,6 +85,8 @@ int pmic_bus_write(u8 reg, u8 data)
> >  	return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1);
> >  #elif defined CONFIG_AXP209_POWER
> >  	return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
> > +#elif defined CONFIG_AXP305_POWER
> > +	return i2c_write(AXP305_I2C_ADDR, reg, 1, &data, 1);
> >  #elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || defined 
CONFIG_AXP818_POWER
> >  # ifdef CONFIG_MACH_SUN6I
> >  	return p2wi_write(reg, data);
> > diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> > index 708a27ed78e9..54ff9bc92396 100644
> > --- a/board/sunxi/board.c
> > +++ b/board/sunxi/board.c
> > @@ -634,16 +634,18 @@ void sunxi_board_init(void)
> >  #endif
> 
> This whole function is really a mess, but we can clean this up later.
> I wonder if we can guard with the actual CONFIG_AXP_*_VOLT symbols
> directly instead of specifying the list of PMICs requiring this rail
> (this list is already in Kconfig).
> Maybe with some macro magic to avoid the repetitions and move the ifdefs
> out of the function?
> 	power_failed |= axp_set_rail(dcdc1, DCDC1);
> and assemble the function name and CONFIG_ symbol in that macro, plus
> having the guard there?
> 
> >  
> >  #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
> > -	defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
> > -	defined CONFIG_AXP818_POWER
> > +	defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
> > +	defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
> >  	power_failed = axp_init();
> >  
> >  #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
> >  	defined CONFIG_AXP818_POWER
> >  	power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
> >  #endif
> > +#if !defined(CONFIG_AXP305_POWER)
> >  	power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
> >  	power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
> > +#endif
> >  #if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
> >  	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
> >  #endif
> > @@ -656,8 +658,10 @@ void sunxi_board_init(void)
> >  	defined CONFIG_AXP818_POWER
> >  	power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
> >  #endif
> > +#if !defined(CONFIG_AXP305_POWER)
> >  	power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
> > -#if !defined(CONFIG_AXP152_POWER)
> > +#endif
> > +#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER)
> >  	power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
> >  #endif
> >  #ifdef CONFIG_AXP209_POWER
> 
> Verified this hunk by playing CPP and removing all non-applicable calls.
> This ended up in:
> 	power_failed = axp_init();
> 	power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
> 
> Which looks like the idea behind this patch, but is totally non-obvious
> from the diff.

Yes, that's correct. I wonder if we need all these power rails to be really 
enabled at this time? IMO we need only those which powers DRAM and probably 
CPU, all others can be moved to U-Boot proper.

Every potential boot source must be already powered before SPL even begins 
execution, so first stage bootloader (BROM) can even load SPL from it.

Best regards,
Jernej

> 
> > diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> > index 02050f6f3569..d17cf2d9112a 100644
> > --- a/drivers/power/Kconfig
> > +++ b/drivers/power/Kconfig
> > @@ -48,6 +48,15 @@ config AXP221_POWER
> >  	Select this to enable support for the axp221/axp223 pmic found on 
most
> >  	A23 and A31 boards.
> >  
> > +config AXP305_POWER
> > +	bool "axp305 pmic support"
> > +	depends on MACH_SUN50I_H616
> > +	select AXP_PMIC_BUS
> > +	select CMD_POWEROFF
> > +	---help---
> > +	Select this to enable support for the axp305 pmic found on most
> > +	H616 boards.
> > +
> >  config AXP809_POWER
> >  	bool "axp809 pmic support"
> >  	depends on MACH_SUN9I
> > @@ -127,11 +136,12 @@ config AXP_DCDC3_VOLT
> >  
> >  config AXP_DCDC4_VOLT
> >  	int "axp pmic dcdc4 voltage"
> > -	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || 
AXP818_POWER
> > +	depends on AXP152_POWER || AXP221_POWER || AXP809_POWER || 
AXP818_POWER || AXP305_POWER
> >  	default 1250 if AXP152_POWER
> >  	default 1200 if MACH_SUN6I
> >  	default 0 if MACH_SUN8I
> >  	default 900 if MACH_SUN9I
> > +	default 1500 if AXP305_POWER
> >  	---help---
> >  	Set the voltage (mV) to program the axp pmic dcdc4 at, set to 0 to
> >  	disable dcdc4.
> > @@ -140,6 +150,7 @@ config AXP_DCDC4_VOLT
> >  	On A23 / A33 boards dcdc4 is unused and should be disabled.
> >  	On A80 boards dcdc4 powers VDD-SYS, HDMI, USB OTG and should be 
0.9V.
> >  	On A83T boards dcdc4 is used for VDD-GPU.
> > +	On H616 boards dcdcd is used for VCC-DRAM.
> >  
> >  config AXP_DCDC5_VOLT
> >  	int "axp pmic dcdc5 voltage"
> > diff --git a/drivers/power/Makefile b/drivers/power/Makefile
> > index 2dcc7bb99d02..0bef06920a7d 100644
> > --- a/drivers/power/Makefile
> > +++ b/drivers/power/Makefile
> > @@ -6,6 +6,7 @@
> >  obj-$(CONFIG_AXP152_POWER)	+= axp152.o
> >  obj-$(CONFIG_AXP209_POWER)	+= axp209.o
> >  obj-$(CONFIG_AXP221_POWER)	+= axp221.o
> > +obj-$(CONFIG_AXP305_POWER)	+= axp305.o
> >  obj-$(CONFIG_AXP809_POWER)	+= axp809.o
> >  obj-$(CONFIG_AXP818_POWER)	+= axp818.o
> >  obj-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
> > diff --git a/drivers/power/axp305.c b/drivers/power/axp305.c
> > new file mode 100644
> > index 000000000000..f620798bb1d7
> > --- /dev/null
> > +++ b/drivers/power/axp305.c
> > @@ -0,0 +1,80 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * AXP305 driver
> > + *
> > + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
> > + *
> > + * Based on axp221.c
> 
> Given that, I wonder if we can (later) simplify this, ideally we end up
> at something like this:
> const struct axp_regulator axp_regulators[] = {
> 	{"dcdc1", 1600, 3400, 100, NA, 0x20, 0x10, 0},
> 	...
> https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/drivers/
allwinner/axp/axp803.c
> 
> Not sure that can cover all AXP chips, but it's worth a try to remove
> all this boilerplate.
> 
> Cheers,
> Andre
> 
> 
> > + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
> > + * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
> > + */
> > +
> > +#include <common.h>
> > +#include <command.h>
> > +#include <errno.h>
> > +#include <asm/arch/pmic_bus.h>
> > +#include <axp_pmic.h>
> > +
> > +static u8 axp305_mvolt_to_cfg(int mvolt, int min, int max, int div)
> > +{
> > +	if (mvolt < min)
> > +		mvolt = min;
> > +	else if (mvolt > max)
> > +		mvolt = max;
> > +
> > +	return  (mvolt - min) / div;
> > +}
> > +
> > +int axp_set_dcdc4(unsigned int mvolt)
> > +{
> > +	int ret;
> > +	u8 cfg;
> > +
> > +	if (mvolt >= 1600)
> > +		cfg = 46 + axp305_mvolt_to_cfg(mvolt, 1600, 3300, 100);
> > +	else
> > +		cfg = axp305_mvolt_to_cfg(mvolt, 600, 1500, 20);
> > +
> > +	if (mvolt == 0)
> > +		return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1,
> > +					
AXP305_OUTPUT_CTRL1_DCDCD_EN);
> > +
> > +	ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return pmic_bus_setbits(AXP305_OUTPUT_CTRL1,
> > +				AXP305_OUTPUT_CTRL1_DCDCD_EN);
> > +}
> > +
> > +int axp_init(void)
> > +{
> > +	u8 axp_chip_id;
> > +	int ret;
> > +
> > +	ret = pmic_bus_init();
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x40)
> > +		return -ENODEV;
> > +
> > +	return ret;
> > +}
> > +
> > +#ifndef CONFIG_PSCI_RESET
> > +int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const 
argv[])
> > +{
> > +	pmic_bus_write(AXP305_SHUTDOWN, AXP305_POWEROFF);
> > +
> > +	/* infinite loop during shutdown */
> > +	while (1) {}
> > +
> > +	/* not reached */
> > +	return 0;
> > +}
> > +#endif
> > diff --git a/include/axp305.h b/include/axp305.h
> > new file mode 100644
> > index 000000000000..225c5040a322
> > --- /dev/null
> > +++ b/include/axp305.h
> > @@ -0,0 +1,17 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
> > + */
> > +
> > +enum axp305_reg {
> > +	AXP305_CHIP_VERSION = 0x3,
> > +	AXP305_OUTPUT_CTRL1 = 0x10,
> > +	AXP305_DCDCD_VOLTAGE = 0x15,
> > +	AXP305_SHUTDOWN = 0x32,
> > +};
> > +
> > +#define AXP305_CHIP_VERSION_MASK	0xcf
> > +
> > +#define AXP305_OUTPUT_CTRL1_DCDCD_EN	(1 << 3)
> > +
> > +#define AXP305_POWEROFF			(1 << 7)
> > diff --git a/include/axp_pmic.h b/include/axp_pmic.h
> > index 10091d0bb278..405044c3a32f 100644
> > --- a/include/axp_pmic.h
> > +++ b/include/axp_pmic.h
> > @@ -15,6 +15,9 @@
> >  #ifdef CONFIG_AXP221_POWER
> >  #include <axp221.h>
> >  #endif
> > +#ifdef CONFIG_AXP305_POWER
> > +#include <axp305.h>
> > +#endif
> >  #ifdef CONFIG_AXP809_POWER
> >  #include <axp809.h>
> >  #endif
> > 
> 
> 

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

end of thread, other threads:[~2021-01-11 19:48 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-03  9:26 [PATCH 00/17] sunxi: Introduce H616 support Jernej Skrabec
2021-01-03  9:26 ` [PATCH 01/17] sunxi: Add support for AXP305 PMIC Jernej Skrabec
2021-01-05 22:36   ` Jaehoon Chung
2021-01-06 10:11     ` André Przywara
2021-01-06 23:33       ` Jaehoon Chung
2021-01-07  9:49         ` André Przywara
2021-01-11  0:02   ` André Przywara
2021-01-11  1:32     ` Jaehoon Chung
2021-01-11 19:48     ` Jernej Škrabec
2021-01-03  9:26 ` [PATCH 02/17] sunxi: Introduce common symbol for H6 like SoCs Jernej Skrabec
2021-01-03 23:43   ` [linux-sunxi] " Samuel Holland
2021-01-04 10:35     ` André Przywara
2021-01-04 18:28       ` Jernej Škrabec
2021-01-11  0:13         ` André Przywara
2021-01-03  9:26 ` [PATCH 03/17] mmc: sunxi: Replace H6 ifdefs with H6 gen macro Jernej Skrabec
2021-01-11  0:13   ` André Przywara
2021-01-03  9:26 ` [PATCH 04/17] i2c: mvtwsi: sunxi: update macro Jernej Skrabec
2021-01-03 23:55   ` [linux-sunxi] " Samuel Holland
2021-01-04  5:57   ` Heiko Schocher
2021-01-03  9:26 ` [PATCH 05/17] sunxi: prcm: Add memory map for H6 like SoCs Jernej Skrabec
2021-01-04  0:03   ` [linux-sunxi] " Samuel Holland
2021-01-11 16:13     ` Jernej Škrabec
2021-01-03  9:26 ` [PATCH 06/17] sunxi: Add support for I2C on " Jernej Skrabec
2021-01-04  0:04   ` [linux-sunxi] " Samuel Holland
2021-01-03  9:26 ` [PATCH 07/17] sunxi: support loading with SPL > 32KB Jernej Skrabec
2021-01-04  2:02   ` [linux-sunxi] " Samuel Holland
2021-01-11 18:17     ` Jernej Škrabec
2021-01-03  9:26 ` [PATCH 08/17] sunxi: introduce support for H616 clocks Jernej Skrabec
2021-01-04  2:28   ` [linux-sunxi] " Samuel Holland
2021-01-03  9:26 ` [PATCH 09/17] sunxi: add support for H616 uart0 Jernej Skrabec
2021-01-04  2:30   ` [linux-sunxi] " Samuel Holland
2021-01-03  9:26 ` [PATCH 10/17] sunxi: add support for R_I2C on H616 Jernej Skrabec
2021-01-04  2:33   ` [linux-sunxi] " Samuel Holland
2021-01-04 18:36     ` Jernej Škrabec
2021-01-03  9:26 ` [PATCH 11/17] sunxi: Add H616 DRAM support Jernej Skrabec
2021-01-04  2:39   ` [linux-sunxi] " Samuel Holland
2021-01-04 18:39     ` Jernej Škrabec
2021-01-05  3:14       ` Samuel Holland
2021-01-03  9:26 ` [PATCH 12/17] sunxi: Add support for H616 SoC Jernej Skrabec
2021-01-04  2:47   ` [linux-sunxi] " Samuel Holland
2021-01-04 18:43     ` Jernej Škrabec
2021-01-03  9:26 ` [PATCH 13/17] net: sun8i-emac: Determine pinmux based on SoC, not EMAC type Jernej Skrabec
2021-01-03  9:26 ` [PATCH 14/17] arm: sunxi: add initial H616 DTSI and headers Jernej Skrabec
2021-01-03  9:26 ` [PATCH 15/17] sunxi: gpio: introduce compatible for H616 Jernej Skrabec
2021-01-11  0:36   ` André Przywara
2021-01-03  9:26 ` [PATCH 16/17] clk: sunxi: Add support for H616 clocks Jernej Skrabec
2021-01-11  0:44   ` André Przywara
2021-01-03  9:26 ` [PATCH 17/17] sunxi: Add support for OrangePi Zero2 Jernej Skrabec

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.