linux-sunxi.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 00/13] Add support for Allwinner R329
@ 2021-07-22  6:30 Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 01/13] sunxi: decide the inclusion of SCP by SCP_ADDR existence Icenowy Zheng
                   ` (12 more replies)
  0 siblings, 13 replies; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

This patchset adds Allwinner R329 support to U-Boot.

First, some code refactors happen for SoCs w/o SCP/MMC2.

Then the basical support for R329 come as several parts (memory map,
clocks, pinmux, DRAM, final Kconfig option).

Then, as the RFC part of this patchset, some device tree related
changes.

Finally it comes the defconfig file for a R329 board, Sipeed Maix IIA
Dock.

This patchset is RFC mainly because of the DT-related part, as no DT
binding is mainlined in Linux now (it's still WIP). All other patches
are ready for being reviewed and, if proper, merged.

Icenowy Zheng (13):
  sunxi: decide the inclusion of SCP by SCP_ADDR existence
  sunxi: only include alias for eMMC when mmc2 used
  mmc: sunxi: conditionally include MMC2 initialization code
  sunxi: add memory addresses for R329 SoC
  sunxi: add support for R329 clocks
  sunxi: add support for basical pinmux setup on R329
  sunxi: add support for R329 DRAM controller
  sunxi: add Kconfig option for R329
  sunxi: sync R329 CCU binding headers from internal WIP kernel tree
  clk: sunxi: add support for R329 in sunxi DM clock driver
  mmc: sunxi: add support for R329 MMC controller
  sunxi: sync R329 DTs from internal WIP kernel tree
  sunxi: add support for Sipeed Maix IIA Dock board

 arch/arm/cpu/armv8/fel_utils.S                |   2 +-
 arch/arm/dts/Makefile                         |   2 +
 arch/arm/dts/sun50i-r329-maix-iia-dock.dts    |  36 ++
 arch/arm/dts/sun50i-r329-maix-iia.dtsi        |  45 +++
 arch/arm/dts/sun50i-r329.dtsi                 | 225 +++++++++++
 arch/arm/dts/sunxi-u-boot.dtsi                |   8 +-
 arch/arm/include/asm/arch-sunxi/boot0.h       |   4 +-
 .../include/asm/arch-sunxi/clock_sun50i_h6.h  |  17 +
 arch/arm/include/asm/arch-sunxi/cpu.h         |   3 +
 .../include/asm/arch-sunxi/cpu_sun50i_r329.h  |  58 +++
 arch/arm/include/asm/arch-sunxi/dram.h        |   2 +
 .../include/asm/arch-sunxi/dram_sun50i_r329.h | 232 +++++++++++
 arch/arm/include/asm/arch-sunxi/gpio.h        |   3 +
 arch/arm/include/asm/arch-sunxi/prcm_sun50i.h |  33 ++
 arch/arm/mach-sunxi/Kconfig                   |  37 +-
 arch/arm/mach-sunxi/Makefile                  |   2 +
 arch/arm/mach-sunxi/board.c                   |   4 +
 arch/arm/mach-sunxi/clock_sun50i_h6.c         |  49 ++-
 arch/arm/mach-sunxi/cpu_info.c                |   2 +
 arch/arm/mach-sunxi/dram_sun50i_r329.c        | 377 ++++++++++++++++++
 arch/arm/mach-sunxi/dram_timings/Makefile     |   1 +
 arch/arm/mach-sunxi/dram_timings/ddr3_r329.c  |  89 +++++
 board/sunxi/MAINTAINERS                       |   5 +
 board/sunxi/board.c                           |  20 +
 common/spl/Kconfig                            |   1 +
 configs/sipeed_maix_iia_dock_defconfig        |   8 +
 drivers/clk/sunxi/Kconfig                     |   7 +
 drivers/clk/sunxi/Makefile                    |   1 +
 drivers/clk/sunxi/clk_r329.c                  |  94 +++++
 drivers/mmc/sunxi_mmc.c                       |   3 +
 include/configs/sunxi-common.h                |   3 +
 include/dt-bindings/clock/sun50i-r329-ccu.h   |  73 ++++
 include/dt-bindings/clock/sun50i-r329-r-ccu.h |  32 ++
 include/dt-bindings/reset/sun50i-r329-ccu.h   |  45 +++
 include/dt-bindings/reset/sun50i-r329-r-ccu.h |  23 ++
 35 files changed, 1535 insertions(+), 11 deletions(-)
 create mode 100644 arch/arm/dts/sun50i-r329-maix-iia-dock.dts
 create mode 100644 arch/arm/dts/sun50i-r329-maix-iia.dtsi
 create mode 100644 arch/arm/dts/sun50i-r329.dtsi
 create mode 100644 arch/arm/include/asm/arch-sunxi/cpu_sun50i_r329.h
 create mode 100644 arch/arm/include/asm/arch-sunxi/dram_sun50i_r329.h
 create mode 100644 arch/arm/mach-sunxi/dram_sun50i_r329.c
 create mode 100644 arch/arm/mach-sunxi/dram_timings/ddr3_r329.c
 create mode 100644 configs/sipeed_maix_iia_dock_defconfig
 create mode 100644 drivers/clk/sunxi/clk_r329.c
 create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
 create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h

-- 
2.30.2


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

* [RFC PATCH 01/13] sunxi: decide the inclusion of SCP by SCP_ADDR existence
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22 13:35   ` Andre Przywara
  2021-07-22  6:30 ` [RFC PATCH 02/13] sunxi: only include alias for eMMC when mmc2 used Icenowy Zheng
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

There are more Allwinner SoCs that do not have a SCP now.

When there's no SCP_ADDR macro defined, we can assume there's no SCP
available.

Drop the scp part of FIT description when SCP_ADDR does not exist.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 arch/arm/dts/sunxi-u-boot.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index 06da009fa2..4a6ed3a7dd 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -64,7 +64,7 @@
 					};
 				};
 
-#ifndef CONFIG_MACH_SUN50I_H616
+#ifdef SCP_ADDR
 				scp {
 					description = "SCP firmware";
 					type = "firmware";
@@ -92,7 +92,7 @@
 				@config-SEQ {
 					description = "NAME";
 					firmware = "atf";
-#ifdef CONFIG_MACH_SUN50I_H616
+#ifndef SCP_ADDR
 					loadables = "uboot";
 #else
 					loadables = "scp", "uboot";
-- 
2.30.2


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

* [RFC PATCH 02/13] sunxi: only include alias for eMMC when mmc2 used
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 01/13] sunxi: decide the inclusion of SCP by SCP_ADDR existence Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22 13:46   ` Andre Przywara
  2021-07-22  6:30 ` [RFC PATCH 03/13] mmc: sunxi: conditionally include MMC2 initialization code Icenowy Zheng
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

Some Allwinner SoCs (e.g. R329) doesn't have a MMC2 controller at all,
and on boards that we do not utilize MMC2, the alias for it is just
useless.

Only include the alias when we specify CONFIG_MMC_SUNXI_EXTRA_SLOT to 2.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 arch/arm/dts/sunxi-u-boot.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index 4a6ed3a7dd..b7244c1112 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -13,7 +13,9 @@
 / {
 	aliases {
 		mmc0 = &mmc0;
+#if CONFIG_MMC_SUNXI_EXTRA_SLOT == 2
 		mmc1 = &mmc2;
+#endif
 	};
 
 	binman: binman {
-- 
2.30.2


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

* [RFC PATCH 03/13] mmc: sunxi: conditionally include MMC2 initialization code
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 01/13] sunxi: decide the inclusion of SCP by SCP_ADDR existence Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 02/13] sunxi: only include alias for eMMC when mmc2 used Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22 13:48   ` Andre Przywara
  2021-07-22  6:30 ` [RFC PATCH 04/13] sunxi: add memory addresses for R329 SoC Icenowy Zheng
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

Allwinner R329 has no MMC2.

Only include the code of MMC2 if the base address of it is defined.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/mmc/sunxi_mmc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 178b8cf106..6b809c001f 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -73,10 +73,12 @@ static int mmc_resource_init(int sdc_no)
 		priv->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE;
 		priv->mclkreg = &ccm->sd1_clk_cfg;
 		break;
+#ifdef SUNXI_MMC2_BASE
 	case 2:
 		priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE;
 		priv->mclkreg = &ccm->sd2_clk_cfg;
 		break;
+#endif
 #ifdef SUNXI_MMC3_BASE
 	case 3:
 		priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE;
-- 
2.30.2


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

* [RFC PATCH 04/13] sunxi: add memory addresses for R329 SoC
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
                   ` (2 preceding siblings ...)
  2021-07-22  6:30 ` [RFC PATCH 03/13] mmc: sunxi: conditionally include MMC2 initialization code Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 05/13] sunxi: add support for R329 clocks Icenowy Zheng
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

Allwinner R329 SoC has a different memory map with previous post-H6
SoCs.

Add the memory map to a dedicated header file, fill everywhere that
uses a hardcoded MMIO address and specify the SPL/ATF load address.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 arch/arm/cpu/armv8/fel_utils.S                |  2 +-
 arch/arm/dts/sunxi-u-boot.dtsi                |  2 +
 arch/arm/include/asm/arch-sunxi/boot0.h       |  4 +-
 .../include/asm/arch-sunxi/clock_sun50i_h6.h  | 17 ++++++
 arch/arm/include/asm/arch-sunxi/cpu.h         |  2 +
 .../include/asm/arch-sunxi/cpu_sun50i_r329.h  | 58 +++++++++++++++++++
 arch/arm/include/asm/arch-sunxi/prcm_sun50i.h | 33 +++++++++++
 include/configs/sunxi-common.h                |  3 +
 8 files changed, 119 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-sunxi/cpu_sun50i_r329.h

diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S
index 7def44ad1d..aa16d79df9 100644
--- a/arch/arm/cpu/armv8/fel_utils.S
+++ b/arch/arm/cpu/armv8/fel_utils.S
@@ -40,7 +40,7 @@ ENTRY(return_to_fel)
 	str	w2, [x1]
 
 	ldr	x0, =0xfa50392f		// CPU hotplug magic
-#ifdef CONFIG_MACH_SUN50I_H616
+#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_R329)
 	ldr	x2, =(SUNXI_R_CPUCFG_BASE + 0x1c0)
 	str	w0, [x2], #0x4
 #elif CONFIG_MACH_SUN50I_H6
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index b7244c1112..9bb6fffeb4 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -5,6 +5,8 @@
 #define  SCP_ADDR 0x114000
 #elif defined(CONFIG_MACH_SUN50I_H616)
 #define BL31_ADDR 0x40000000
+#elif defined(CONFIG_MACH_SUN50I_R329)
+#define BL31_ADDR 0x124000
 #else
 #define BL31_ADDR  0x44000
 #define  SCP_ADDR  0x50000
diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
index e8e8e38f05..a791c7c403 100644
--- a/arch/arm/include/asm/arch-sunxi/boot0.h
+++ b/arch/arm/include/asm/arch-sunxi/boot0.h
@@ -39,7 +39,9 @@
 	.word	0xf57ff06f	// isb     sy
 	.word	0xe320f003	// wfi
 	.word	0xeafffffd	// b       @wfi
-#ifndef CONFIG_SUN50I_GEN_H6
+#if defined(CONFIG_MACH_SUN50I_R329)
+	.word	0x08100040	// writeable RVBAR mapping address
+#elif !defined(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_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
index 37df4410ea..6c3b8ea351 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
@@ -250,10 +250,19 @@ struct sunxi_ccm_reg {
 #define CCM_PLL6_LOCK			BIT(28)
 #define CCM_PLL6_CTRL_N_SHIFT		8
 #define CCM_PLL6_CTRL_N_MASK		(0xff << CCM_PLL6_CTRL_N_SHIFT)
+#ifndef CONFIG_MACH_SUN50I_R329
 #define CCM_PLL6_CTRL_DIV1_SHIFT	0
 #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)
+#else
+#define CCM_PLL6_CTRL_M_SHIFT	1
+#define CCM_PLL6_CTRL_M_MASK		(0x1 << CCM_PLL6_CTRL_DIV2_SHIFT)
+#define CCM_PLL6_CTRL_DIV1_SHIFT	16
+#define CCM_PLL6_CTRL_DIV1_MASK		(0x7 << CCM_PLL6_CTRL_DIV1_SHIFT)
+#define CCM_PLL6_CTRL_DIV2_SHIFT	20
+#define CCM_PLL6_CTRL_DIV2_MASK		(0x7 << CCM_PLL6_CTRL_DIV2_SHIFT)
+#endif
 
 /* cpu_axi bit field*/
 #define CCM_CPU_AXI_MUX_MASK		(0x3 << 24)
@@ -285,6 +294,14 @@ struct sunxi_ccm_reg {
 
 /* apb1 bit field */
 #define CCM_APB1_DEFAULT		0x03000102
+#elif CONFIG_MACH_SUN50I_R329
+#define CCM_PLL6_DEFAULT		0xa8216300
+
+/* ahb bit field */
+#define CCM_PSI_AHB1_AHB2_DEFAULT	0x03000002
+
+/* apb1 bit field */
+#define CCM_APB1_DEFAULT		0x02000001
 #endif
 
 /* apb2 bit field */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
index b08f202374..20d04cac74 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -8,6 +8,8 @@
 
 #if defined(CONFIG_MACH_SUN9I)
 #include <asm/arch/cpu_sun9i.h>
+#elif defined(CONFIG_MACH_SUN50I_R329)
+#include <asm/arch/cpu_sun50i_r329.h>
 #elif defined(CONFIG_SUN50I_GEN_H6)
 #include <asm/arch/cpu_sun50i_h6.h>
 #else
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_r329.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_r329.h
new file mode 100644
index 0000000000..3d2237a59f
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_r329.h
@@ -0,0 +1,58 @@
+/*
+ * (C) Copyright 2021 Sipeed
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _SUNXI_CPU_SUN50I_H6_H
+#define _SUNXI_CPU_SUN50I_H6_H
+
+#define SUNXI_SRAM_A1_BASE		0x00020000
+#define SUNXI_SRAM_A2_BASE		0x00100000
+
+#define SUNXI_TIMER_BASE		0x02000000
+#define SUNXI_PIO_BASE			0x02000400
+#define SUNXI_CCM_BASE			0x02001000
+
+#define SUNXI_UART0_BASE		0x02500000
+#define SUNXI_UART1_BASE		0x02500400
+#define SUNXI_UART2_BASE		0x02500800
+#define SUNXI_UART3_BASE		0x02500C00
+#define SUNXI_TWI0_BASE			0x02502000
+#define SUNXI_TWI1_BASE			0x02502400
+
+#define SUNXI_SRAMC_BASE		0x03000000
+#define SUNXI_DMA_BASE			0x03002000
+/* SID address space starts at 0x03006000, but e-fuse is at offset 0x200 */
+#define SUNXI_SIDC_BASE			0x03006000
+#define SUNXI_SID_BASE			0x03006200
+
+#define SUNXI_GIC400_BASE		0x03020000
+#define SUNXI_SS_BASE			0x03040000
+#define SUNXI_DRAM_COM_BASE		0x03102000
+#define SUNXI_DRAM_CTL0_BASE		0x03103000
+
+#define SUNXI_NFC_BASE			0x04011000
+#define SUNXI_MMC0_BASE			0x04020000
+#define SUNXI_MMC1_BASE			0x04021000
+#define SUNXI_SPI0_BASE			0x04025000
+#define SUNXI_SPI1_BASE			0x04026000
+#define SUNXI_USB0_BASE			0x04100000
+#define SUNXI_USB1_BASE			0x04201000
+#define SUNXI_GMAC_BASE			0x04500000
+
+#define SUNXI_R_CPUCFG_BASE		0x07000400
+#define SUNXI_PRCM_BASE			0x07010000
+#define SUNXI_R_WDOG_BASE		0x07020400
+#define SUNXI_R_PIO_BASE		0x07022000
+#define SUNXI_R_UART_BASE		0x07080000
+#define SUNXI_R_TWI_BASE		0x07081400
+#define SUNXI_RTC_BASE			0x07090000
+
+#ifndef __ASSEMBLY__
+void sunxi_board_init(void);
+void sunxi_reset(void);
+int sunxi_get_sid(unsigned int *sid);
+#endif
+
+#endif /* _SUNXI_CPU_SUN9I_H */
diff --git a/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h b/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
index 5f636e8384..1aba5f0122 100644
--- a/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
+++ b/arch/arm/include/asm/arch-sunxi/prcm_sun50i.h
@@ -37,8 +37,41 @@ struct sunxi_prcm_reg {
 	u32 w1_gate_reset;	/* 0x1ec */
 	u8 res10[0x1c];		/* 0x1f0 */
 	u32 rtc_gate_reset;	/* 0x20c */
+#ifdef CONFIG_MACH_SUN50I_R329
+	u8 res11[0xdf0];	/* 0x210 */
+
+	u32 pll1_cfg;		/* 0x1000 pll1 (cpux) control */
+	u8 reserved_0x1004[0xc];
+	u32 pll6_cfg;		/* 0x1010 pll6 (periph) control */
+	u8 reserved_0x1014[0xc];
+	u32 pll2_cfg;		/* 0x1020 pll2 (audio) control */
+	u8 reserved_0x1024[0xc];
+	u32 pll_audio1_cfg;	/* 0x1030 pll audio1 control */
+	u8 reserved_0x1034[0xdc];
+	u32 pll6_pat0;		/* 0x1110 pll6 (periph) pattern0 */
+	u32 pll6_pat1;		/* 0x1114 pll6 (periph) pattern1 */
+	u8 reserved_0x1118[0x8];
+	u32 pll2_pat0;		/* 0x1120 pll2 (audio) pattern0 */
+	u32 pll2_pat1;		/* 0x1120 pll2 (audio) pattern1 */
+	u8 reserved_0x1128[0x8];
+	u32 pll_audio1_pat0;	/* 0x1130 pll audio1 pattern0 */
+	u32 pll_audio1_pat1;	/* 0x1130 pll audio1 pattern1 */
+	u8 reserved_0x1138[0x1c8];
+	u32 pll1_bias;		/* 0x1300 pll1 (cpux) bias */
+	u8 reserved_0x1304[0xc];
+	u32 pll6_bias;		/* 0x1310 pll6 (periph) bias */
+	u8 reserved_0x1314[0xc];
+	u32 pll2_bias;		/* 0x1320 pll6 (periph0) bias */
+	u8 reserved_0x1324[0xc];
+	u32 pll_audio1_bias;	/* 0x1330 pll audio1 bias */
+	u8 reserved_0x1334[0xcc];
+	u32 pll1_tun;		/* 0x1400 pll1 (cpux) tunning */
+#endif
 };
 check_member(sunxi_prcm_reg, rtc_gate_reset, 0x20c);
+#ifdef CONFIG_MACH_SUN50I_R329
+check_member(sunxi_prcm_reg, pll1_tun, 0x1400);
+#endif
 
 #define PRCM_TWI_GATE		(1 << 0)
 #define PRCM_TWI_RESET		(1 << 16)
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 9e37e99684..a114c1addc 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -181,6 +181,9 @@
 /* end of SRAM A2 on H6 for now */
 #define LOW_LEVEL_SRAM_STACK		0x00118000
 #endif
+#elif CONFIG_SUNXI_SRAM_ADDRESS == 0x100000
+#define CONFIG_SPL_MAX_SIZE		0x7fa0		/* 32 KiB */
+#define LOW_LEVEL_SRAM_STACK		0x00120000	/* 64 KiB inside SRAM A2 */
 #else
 #define CONFIG_SPL_MAX_SIZE		0x5fa0		/* 24KB on sun4i/sun7i */
 #define LOW_LEVEL_SRAM_STACK		0x00008000	/* End of sram */
-- 
2.30.2


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

* [RFC PATCH 05/13] sunxi: add support for R329 clocks
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
                   ` (3 preceding siblings ...)
  2021-07-22  6:30 ` [RFC PATCH 04/13] sunxi: add memory addresses for R329 SoC Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 06/13] sunxi: add support for basical pinmux setup on R329 Icenowy Zheng
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

R329 has a quite different clock tree than other SoCs. It has only 4
PLLs and its PLL-PERIPH has two post dividers, one for the normal
PLL-PERIPH-2x output and another for a special PLL-PERIPH-800M output.
In addition, its PLL configuration registers are in PRCM memory zone,
not the ordinary CPUX CCU one.

Add support for basical R329 clock initialization.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 arch/arm/mach-sunxi/clock_sun50i_h6.c | 49 ++++++++++++++++++++++++---
 1 file changed, 44 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index a947463e0a..28bc5fccd8 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -9,6 +9,13 @@ void clock_init_safe(void)
 {
 	struct sunxi_ccm_reg *const ccm =
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+#ifdef CONFIG_MACH_SUN50I_R329
+	struct sunxi_prcm_reg *const prcm =
+		(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+	struct sunxi_prcm_reg *const pllccm = prcm;
+#else
+	struct sunxi_ccm_reg *const pllccm = ccm;
+#endif
 
 	/* this seems to enable PLLs on H616 */
 	if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
@@ -16,22 +23,26 @@ void clock_init_safe(void)
 
 	clock_set_pll1(408000000);
 
-	writel(CCM_PLL6_DEFAULT, &ccm->pll6_cfg);
-	while (!(readl(&ccm->pll6_cfg) & CCM_PLL6_LOCK))
+	writel(CCM_PLL6_DEFAULT, &pllccm->pll6_cfg);
+	while (!(readl(&pllccm->pll6_cfg) & CCM_PLL6_LOCK))
 		;
 
 	clrsetbits_le32(&ccm->cpu_axi_cfg, CCM_CPU_AXI_APB_MASK | CCM_CPU_AXI_AXI_MASK,
 			CCM_CPU_AXI_DEFAULT_FACTORS);
 
 	writel(CCM_PSI_AHB1_AHB2_DEFAULT, &ccm->psi_ahb1_ahb2_cfg);
+#ifdef CCM_AHB3_DEFAULT
 	writel(CCM_AHB3_DEFAULT, &ccm->ahb3_cfg);
+#endif
 	writel(CCM_APB1_DEFAULT, &ccm->apb1_cfg);
 
+#ifndef CONFIG_MACH_SUN50I_R329
 	/*
 	 * The mux and factor are set, but the clock will be enabled in
 	 * DRAM initialization code.
 	 */
 	writel(MBUS_CLK_SRC_PLL6X2 | MBUS_CLK_M(3), &ccm->mbus_cfg);
+#endif
 }
 #endif
 
@@ -60,8 +71,20 @@ void clock_set_pll1(unsigned int clk)
 {
 	struct sunxi_ccm_reg * const ccm =
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+#ifdef CONFIG_MACH_SUN50I_R329
+	struct sunxi_prcm_reg *const prcm =
+		(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+	struct sunxi_prcm_reg *const pllccm = prcm;
+#else
+	struct sunxi_ccm_reg *const pllccm = ccm;
+#endif
 	u32 val;
 
+#ifdef CONFIG_MACH_SUN50I_R329
+	/* Fix undervoltage reset threshold */
+	clrsetbits_le32(0x070901f4, 0xfff, 0xc0);
+#endif
+
 	/* Do not support clocks < 288MHz as they need factor P */
 	if (clk < 288000000) clk = 288000000;
 
@@ -73,11 +96,11 @@ 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
+#ifndef CONFIG_MACH_SUN50I_H6
 	       CCM_PLL1_OUT_EN |
 #endif
-	       CCM_PLL1_CTRL_N(clk / 24000000), &ccm->pll1_cfg);
-	while (!(readl(&ccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
+	       CCM_PLL1_CTRL_N(clk / 24000000), &pllccm->pll1_cfg);
+	while (!(readl(&pllccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
 
 	/* Switch CPU to PLL1 */
 	val = readl(&ccm->cpu_axi_cfg);
@@ -87,6 +110,7 @@ void clock_set_pll1(unsigned int clk)
 }
 #endif
 
+#ifndef CONFIG_MACH_SUN50I_R329
 unsigned int clock_get_pll6(void)
 {
 	struct sunxi_ccm_reg *const ccm =
@@ -102,6 +126,21 @@ unsigned int clock_get_pll6(void)
 	/* The register defines PLL6-2X or PLL6-4X, not plain PLL6 */
 	return 24000000 / m * n / div1 / div2;
 }
+#else
+unsigned int clock_get_pll6(void)
+{
+	struct sunxi_prcm_reg *const prcm =
+		(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+
+	uint32_t rval = readl(&prcm->pll6_cfg);
+	int m = ((rval & CCM_PLL6_CTRL_M_MASK) >> CCM_PLL6_CTRL_M_SHIFT) + 1;
+	int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
+	int div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
+			CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
+	/* The register defines PLL6-2X, not plain PLL6 */
+	return 24000000 / m * n / div1 / 2;
+}
+#endif
 
 int clock_twi_onoff(int port, int state)
 {
-- 
2.30.2


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

* [RFC PATCH 06/13] sunxi: add support for basical pinmux setup on R329
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
                   ` (4 preceding siblings ...)
  2021-07-22  6:30 ` [RFC PATCH 05/13] sunxi: add support for R329 clocks Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 07/13] sunxi: add support for R329 DRAM controller Icenowy Zheng
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

Allwinner R329 SoC is the first known Allwinner SoC that has two
possible pinmux setups for MMC0 controller.

Support configuration of both setups of MMC0 and UART0 at PB4/5.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 arch/arm/include/asm/arch-sunxi/gpio.h |  3 +++
 arch/arm/mach-sunxi/Kconfig            |  7 +++++++
 arch/arm/mach-sunxi/board.c            |  4 ++++
 board/sunxi/board.c                    | 20 ++++++++++++++++++++
 4 files changed, 34 insertions(+)

diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index 2969a530ae..da9acfab78 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -166,12 +166,14 @@ enum sunxi_gpio_number {
 #define SUN8I_A83T_GPB_UART0	2
 #define SUN8I_V3S_GPB_UART0	3
 #define SUN50I_GPB_UART0	4
+#define SUN50I_R329_GPB_UART0	2
 
 #define SUNXI_GPC_NAND		2
 #define SUNXI_GPC_SPI0		3
 #define SUNXI_GPC_SDC2		3
 #define SUN6I_GPC_SDC3		4
 #define SUN50I_GPC_SPI0		4
+#define SUN50I_R329_GPC_SDC0	3
 
 #define SUN8I_GPD_SDC1		3
 #define SUNXI_GPD_LCD0		2
@@ -185,6 +187,7 @@ enum sunxi_gpio_number {
 #define SUNXI_GPF_SDC0		2
 #define SUNXI_GPF_UART0		4
 #define SUN8I_GPF_UART0		3
+#define SUN50I_R329_GPF_SDC0	5
 
 #define SUN4I_GPG_SDC1		4
 #define SUN5I_GPG_SDC1		2
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 49f94f095c..391a3dd9e5 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -672,6 +672,13 @@ config MMC3_CD_PIN
 	---help---
 	See MMC0_CD_PIN help text.
 
+config MMC0_PINS
+	string "Pins for mmc0"
+	default "PF"
+	depends on MACH_SUN50I_R329
+	---help---
+	See MMC1_PINS help text.
+
 config MMC1_PINS
 	string "Pins for mmc1"
 	default ""
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index e979e426dd..1aa31c7e05 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -129,6 +129,10 @@ static int gpio_init(void)
 	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_SUN50I_R329)
+	sunxi_gpio_set_cfgpin(SUNXI_GPB(4), SUN50I_R329_GPB_UART0);
+	sunxi_gpio_set_cfgpin(SUNXI_GPB(5), SUN50I_R329_GPB_UART0);
+	sunxi_gpio_set_pull(SUNXI_GPB(5), 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);
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 67acc01d83..bfc90345d9 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -417,12 +417,32 @@ static void mmc_pinmux_setup(int sdc)
 
 	switch (sdc) {
 	case 0:
+#if defined(CONFIG_MACH_SUN50I_R329)
+		pins = sunxi_name_to_gpio_bank(CONFIG_MMC0_PINS);
+
+		if (pins == SUNXI_GPIO_C) {
+			/* SDC0: PC0-PC6 */
+			for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(6); pin++) {
+				sunxi_gpio_set_cfgpin(pin, SUN50I_R329_GPC_SDC0);
+				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+				sunxi_gpio_set_drv(pin, 2);
+			}
+		} else {
+			/* SDC0: PF0-PF5 */
+			for (pin = SUNXI_GPF(0); pin <= SUNXI_GPF(5); pin++) {
+				sunxi_gpio_set_cfgpin(pin, SUN50I_R329_GPF_SDC0);
+				sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+				sunxi_gpio_set_drv(pin, 2);
+			}
+		}
+#else
 		/* SDC0: PF0-PF5 */
 		for (pin = SUNXI_GPF(0); pin <= SUNXI_GPF(5); pin++) {
 			sunxi_gpio_set_cfgpin(pin, SUNXI_GPF_SDC0);
 			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 			sunxi_gpio_set_drv(pin, 2);
 		}
+#endif
 		break;
 
 	case 1:
-- 
2.30.2


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

* [RFC PATCH 07/13] sunxi: add support for R329 DRAM controller
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
                   ` (5 preceding siblings ...)
  2021-07-22  6:30 ` [RFC PATCH 06/13] sunxi: add support for basical pinmux setup on R329 Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 08/13] sunxi: add Kconfig option for R329 Icenowy Zheng
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

R329 has a new DRAM controller, which looks like a combination of the
H6/H616 MCTL_COM part and the SUNXI_DW MCTL_CTL part. This design has
already got reused by Allwinner, and V831/V833 SoCs have similar
memory controller.

Add support for it. To prepare for further support of other SoCs,
routines with socid parameter are added, although not checked now.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 arch/arm/include/asm/arch-sunxi/cpu.h         |   1 +
 arch/arm/include/asm/arch-sunxi/dram.h        |   2 +
 .../include/asm/arch-sunxi/dram_sun50i_r329.h | 232 +++++++++++
 arch/arm/mach-sunxi/Kconfig                   |  16 +-
 arch/arm/mach-sunxi/Makefile                  |   2 +
 arch/arm/mach-sunxi/dram_sun50i_r329.c        | 377 ++++++++++++++++++
 arch/arm/mach-sunxi/dram_timings/Makefile     |   1 +
 arch/arm/mach-sunxi/dram_timings/ddr3_r329.c  |  89 +++++
 8 files changed, 719 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/include/asm/arch-sunxi/dram_sun50i_r329.h
 create mode 100644 arch/arm/mach-sunxi/dram_sun50i_r329.c
 create mode 100644 arch/arm/mach-sunxi/dram_timings/ddr3_r329.c

diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
index 20d04cac74..a968af6012 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -21,5 +21,6 @@
 #define SOCID_V3S	0x1681
 #define SOCID_H5	0x1718
 #define SOCID_R40	0x1701
+#define SOCID_R329	0x1851
 
 #endif /* _SUNXI_CPU_H */
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index c3b3e1f512..36549a47c5 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -31,6 +31,8 @@
 #include <asm/arch/dram_sun50i_h6.h>
 #elif defined(CONFIG_MACH_SUN50I_H616)
 #include <asm/arch/dram_sun50i_h616.h>
+#elif defined(CONFIG_MACH_SUN50I_R329)
+#include <asm/arch/dram_sun50i_r329.h>
 #else
 #include <asm/arch/dram_sun4i.h>
 #endif
diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_r329.h b/arch/arm/include/asm/arch-sunxi/dram_sun50i_r329.h
new file mode 100644
index 0000000000..723c687670
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_r329.h
@@ -0,0 +1,232 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * sun50i R329 platform dram controller register and constant defines
+ *
+ * (C) Copyright 2021 Sipeed
+ * 
+ * based on dram_sun50i_h6.h, which is:
+ *   (C) Copyright 2017  Icenowy Zheng <icenowy@aosc.io>
+ *
+ * based on dram_sun8i_h3.h, which is:
+ *   (C) Copyright 2007-2015 Allwinner Technology Co.
+ *                           Jerry Wang <wangflord@allwinnertech.com>
+ *   (C) Copyright 2015      Vishnu Patekar <vishnupatekar0510@gmail.com>
+ *   (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
+ *   (C) Copyright 2015      Jens Kuske <jenskuske@gmail.com>
+ */
+
+#ifndef _SUNXI_DRAM_SUN8I_H3_H
+#define _SUNXI_DRAM_SUN8I_H3_H
+
+#include <linux/bitops.h>
+
+struct sunxi_mctl_com_reg {
+	u32 cr;			/* 0x000 control register */
+	u32 cr_r1;		/* 0x004 control register for 2nd rank */
+	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 */
+};
+check_member(sunxi_mctl_com_reg, master[40].reserved_0x8, 0x498);
+
+#define MCTL_CR_BL8		(0x4 << 20)
+
+#define MCTL_CR_1T		(0x1 << 19)
+#define MCTL_CR_2T		(0x0 << 19)
+
+#define MCTL_CR_LPDDR3		(0x7 << 16)
+#define MCTL_CR_LPDDR2		(0x6 << 16)
+#define MCTL_CR_DDR3		(0x3 << 16)
+#define MCTL_CR_DDR2		(0x2 << 16)
+
+#define MCTL_CR_SEQUENTIAL	(0x1 << 15)
+#define MCTL_CR_INTERLEAVED	(0x0 << 15)
+
+#define MCTL_CR_FULL_WIDTH	(0x1 << 12)
+#define MCTL_CR_HALF_WIDTH	(0x0 << 12)
+#define MCTL_CR_BUS_FULL_WIDTH(x)	((x) << 12)
+
+#define MCTL_CR_PAGE_SIZE(x)	((fls(x) - 4) << 8)
+#define MCTL_CR_ROW_BITS(x)	(((x) - 1) << 4)
+#define MCTL_CR_EIGHT_BANKS	(0x1 << 2)
+#define MCTL_CR_FOUR_BANKS	(0x0 << 2)
+#define MCTL_CR_DUAL_RANK	(0x1 << 0)
+#define MCTL_CR_SINGLE_RANK	(0x0 << 0)
+
+struct sunxi_mctl_ctl_reg {
+	u32 pir;		/* 0x00 PHY initialization register */
+	u32 pwrctl;		/* 0x04 */
+	u32 mrctrl;		/* 0x08 */
+	u32 clken;		/* 0x0c */
+	u32 pgsr[2];		/* 0x10 PHY general status registers */
+	u32 statr;		/* 0x18 */
+	u8 res1[0x10];		/* 0x1c */
+	u32 lp3mr11;		/* 0x2c */
+	u32 mr[4];		/* 0x30 mode registers */
+	u32 pllgcr;		/* 0x40 */
+	u32 ptr[5];		/* 0x44 PHY timing registers */
+	u32 dramtmg[9];		/* 0x58 DRAM timing registers */
+	u32 odtcfg;		/* 0x7c */
+	u32 pitmg[2];		/* 0x80 PHY interface timing registers */
+	u8 res2[0x4];		/* 0x88 */
+	u32 rfshctl0;		/* 0x8c */
+	u32 rfshtmg[2];		/* 0x90 refresh timing */
+	u32 pwrtmg;		/* 0x98 */
+	u8 res3[0x4];		/* 0x9c */
+	u32 unk_0x0a0;		/* 0xa0 */
+	u8 res3_1[0x14];	/* 0xa4 */
+	u32 vtfcr;		/* 0xb8 (unused on H3) */
+	u32 dqsgmr;		/* 0xbc */
+	u32 dtcr;		/* 0xc0 */
+	u32 dtar[4];		/* 0xc4 */
+	u32 dtdr[2];		/* 0xd4 */
+	u32 dtmr[2];		/* 0xdc */
+	u32 dtbmr;		/* 0xe4 */
+	u32 catr[2];		/* 0xe8 */
+	u32 dtedr[2];		/* 0xf0 */
+	u8 res4[0x8];		/* 0xf8 */
+	u32 pgcr[4];		/* 0x100 PHY general configuration registers */
+	u32 iovcr[2];		/* 0x110 */
+	u32 dqsdr;		/* 0x118 */
+	u32 dxccr;		/* 0x11c */
+	u32 odtmap;		/* 0x120 */
+	u32 zqctl[2];		/* 0x124 */
+	u8 res6[0x14];		/* 0x12c */
+	u32 zqcr;		/* 0x140 ZQ control register */
+	u32 zqsr;		/* 0x144 ZQ status register */
+	u32 zqdr[3];		/* 0x148 ZQ data registers */
+	u8 res7[0x6c];		/* 0x154 */
+	u32 sched;		/* 0x1c0 */
+	u32 perfhpr[2];		/* 0x1c4 */
+	u32 perflpr[2];		/* 0x1cc */
+	u32 perfwr[2];		/* 0x1d4 */
+	u8 res8[0x24];		/* 0x1dc */
+	u32 acmdlr;		/* 0x200 AC master delay line register */
+	u32 aclcdlr;		/* 0x204 AC local calibrated delay line register */
+	u32 aciocr;		/* 0x208 AC I/O configuration register */
+	u8 res9[0x4];		/* 0x20c */
+	u32 acbdlr[31];		/* 0x210 AC bit delay line registers */
+	u8 res10[0x74];		/* 0x28c */
+	struct {		/* 0x300 DATX8 modules*/
+		u32 mdlr;		/* 0x00 master delay line register */
+		u32 lcdlr[3];		/* 0x04 local calibrated delay line registers */
+		u32 bdlr[11];		/* 0x10 bit delay line registers */
+		u32 sdlr;		/* 0x3c output enable bit delay registers */
+		u32 gtr;		/* 0x40 general timing register */
+		u32 gcr;		/* 0x44 general configuration register */
+		u32 gsr[3];		/* 0x48 general status registers */
+		u8 res0[0x2c];		/* 0x54 */
+	} dx[4];
+	u8 res11[0x388];	/* 0x500 */
+	u32 upd2;		/* 0x888 */
+};
+check_member(sunxi_mctl_ctl_reg, upd2, 0x888);
+
+#define PTR3_TDINIT1(x)		((x) << 20)
+#define PTR3_TDINIT0(x)		((x) <<  0)
+
+#define PTR4_TDINIT3(x)		((x) << 20)
+#define PTR4_TDINIT2(x)		((x) <<  0)
+
+#define DRAMTMG0_TWTP(x)	((x) << 24)
+#define DRAMTMG0_TFAW(x)	((x) << 16)
+#define DRAMTMG0_TRAS_MAX(x)	((x) <<  8)
+#define DRAMTMG0_TRAS(x)	((x) <<  0)
+
+#define DRAMTMG1_TXP(x)		((x) << 16)
+#define DRAMTMG1_TRTP(x)	((x) <<  8)
+#define DRAMTMG1_TRC(x)		((x) <<  0)
+
+#define DRAMTMG2_TCWL(x)	((x) << 24)
+#define DRAMTMG2_TCL(x)		((x) << 16)
+#define DRAMTMG2_TRD2WR(x)	((x) <<  8)
+#define DRAMTMG2_TWR2RD(x)	((x) <<  0)
+
+#define DRAMTMG3_TMRW(x)	((x) << 16)
+#define DRAMTMG3_TMRD(x)	((x) << 12)
+#define DRAMTMG3_TMOD(x)	((x) <<  0)
+
+#define DRAMTMG4_TRCD(x)	((x) << 24)
+#define DRAMTMG4_TCCD(x)	((x) << 16)
+#define DRAMTMG4_TRRD(x)	((x) <<  8)
+#define DRAMTMG4_TRP(x)		((x) <<  0)
+
+#define DRAMTMG5_TCKSRX(x)	((x) << 24)
+#define DRAMTMG5_TCKSRE(x)	((x) << 16)
+#define DRAMTMG5_TCKESR(x)	((x) <<  8)
+#define DRAMTMG5_TCKE(x)	((x) <<  0)
+
+#define RFSHTMG_TREFI(x)	((x) << 16)
+#define RFSHTMG_TRFC(x)		((x) <<  0)
+
+#define PIR_CLRSR	(0x1 << 27)	/* clear status registers */
+#define PIR_QSGATE	(0x1 << 10)	/* Read DQS gate training */
+#define PIR_DRAMINIT	(0x1 << 8)	/* DRAM initialization */
+#define PIR_DRAMRST	(0x1 << 7)	/* DRAM reset */
+#define PIR_PHYRST	(0x1 << 6)	/* PHY reset */
+#define PIR_DCAL	(0x1 << 5)	/* DDL calibration */
+#define PIR_PLLINIT	(0x1 << 4)	/* PLL initialization */
+#define PIR_ZCAL	(0x1 << 1)	/* ZQ calibration */
+#define PIR_INIT	(0x1 << 0)	/* PHY initialization trigger */
+
+#define PGSR_INIT_DONE	(0x1 << 0)	/* PHY init done */
+
+#define ZQCR_PWRDOWN	(1U << 31)	/* ZQ power down */
+
+#define ACBDLR_WRITE_DELAY(x)	((x) << 8)
+
+#define DXBDLR_DQ(x)	(x)		/* DQ0-7 BDLR index */
+#define DXBDLR_DM	8		/* DM BDLR index */
+#define DXBDLR_DQS	9		/* DQS BDLR index */
+#define DXBDLR_DQSN	10		/* DQSN BDLR index */
+
+#define DXBDLR_WRITE_DELAY(x)	((x) << 8)
+#define DXBDLR_READ_DELAY(x)	((x) << 0)
+
+/*
+ * The delay parameters below allow to allegedly specify delay times of some
+ * unknown unit for each individual bit trace in each of the four data bytes
+ * the 32-bit wide access consists of. Also three control signals can be
+ * adjusted individually.
+ */
+#define NR_OF_BYTE_LANES	(32 / BITS_PER_BYTE)
+/* The eight data lines (DQn) plus DM, DQS and DQSN */
+#define LINES_PER_BYTE_LANE	(BITS_PER_BYTE + 3)
+struct dram_para {
+	u16 page_size;
+	u8 bus_full_width;
+	u8 dual_rank;
+	u8 row_bits;
+	u8 bank_bits;
+	const u8 dx_read_delays[NR_OF_BYTE_LANES][LINES_PER_BYTE_LANE];
+	const u8 dx_write_delays[NR_OF_BYTE_LANES][LINES_PER_BYTE_LANE];
+	const u8 ac_delays[31];
+};
+
+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(uint16_t socid, struct dram_para *para);
+
+#endif /* _SUNXI_DRAM_SUN8I_H3_H */
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 391a3dd9e5..c9bb47a8bd 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -54,6 +54,12 @@ config DRAM_SUN50I_H616
 	  Select this dram controller driver for some sun50i platforms,
 	  like H616.
 
+config DRAM_SUN50I_R329
+	bool
+	help
+	  Select this dram controller driver for some sun50i platforms,
+	  like R329.
+
 if DRAM_SUN50I_H616
 config DRAM_SUN50I_H616_WRITE_LEVELING
 	bool "H616 DRAM write leveling"
@@ -402,7 +408,7 @@ config ARM_BOOT_HOOK_RMR
 	This allows both the SPL and the U-Boot proper to be entered in
 	either mode and switch to AArch64 if needed.
 
-if SUNXI_DRAM_DW || DRAM_SUN50I_H6
+if SUNXI_DRAM_DW || DRAM_SUN50I_H6 || DRAM_SUN50I_R329
 config SUNXI_DRAM_DDR3
 	bool
 
@@ -424,6 +430,14 @@ config SUNXI_DRAM_DDR3_1333
 	This option is the original only supported memory type, which suits
 	many H3/H5/A64 boards available now.
 
+config SUNXI_DRAM_DDR3_R329
+	bool "DDR3 found in R329 chip"
+	select SUNXI_DRAM_DDR3
+	depends on DRAM_SUN50I_R329
+	---help---
+	This option is only for the DDR3 memory chip which is co-packaged in
+	Allwinner R329 SoC.
+
 config SUNXI_DRAM_LPDDR3_STOCK
 	bool "LPDDR3 with Allwinner stock configuration"
 	select SUNXI_DRAM_LPDDR3
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index 3f081d92f3..f90393cbbc 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -42,4 +42,6 @@ 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/
+obj-$(CONFIG_DRAM_SUN50I_R329)	+= dram_sun50i_r329.o
+obj-$(CONFIG_DRAM_SUN50I_R329)	+= dram_timings/
 endif
diff --git a/arch/arm/mach-sunxi/dram_sun50i_r329.c b/arch/arm/mach-sunxi/dram_sun50i_r329.c
new file mode 100644
index 0000000000..730883999c
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_sun50i_r329.c
@@ -0,0 +1,377 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * sun50i R329 platform dram controller init
+ *
+ * (C) Copyright 2921 Sipeed
+ *
+ * Based on dram_sunxi_dw.c, which is:
+ *   (C) Copyright 2007-2015 Allwinner Technology Co.
+ *                           Jerry Wang <wangflord@allwinnertech.com>
+ *   (C) Copyright 2015      Vishnu Patekar <vishnupatekar0510@gmail.com>
+ *   (C) Copyright 2015      Hans de Goede <hdegoede@redhat.com>
+ *   (C) Copyright 2015      Jens Kuske <jenskuske@gmail.com>
+ */
+#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 <asm/arch/prcm.h>
+#include <linux/delay.h>
+#include <linux/kconfig.h>
+
+static void mctl_phy_init(u32 val)
+{
+	struct sunxi_mctl_ctl_reg * const mctl_ctl =
+			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+	writel(val | PIR_INIT, &mctl_ctl->pir);
+	mctl_await_completion(&mctl_ctl->pgsr[0], PGSR_INIT_DONE, 0x1);
+}
+
+static void mctl_set_bit_delays(struct dram_para *para)
+{
+	struct sunxi_mctl_ctl_reg * const mctl_ctl =
+			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+	int i, j;
+
+	clrbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
+
+	for (i = 0; i < NR_OF_BYTE_LANES; i++)
+		for (j = 0; j < LINES_PER_BYTE_LANE; j++)
+			writel(DXBDLR_WRITE_DELAY(para->dx_write_delays[i][j]) |
+			       DXBDLR_READ_DELAY(para->dx_read_delays[i][j]),
+			       &mctl_ctl->dx[i].bdlr[j]);
+
+	for (i = 0; i < 31; i++)
+		writel(ACBDLR_WRITE_DELAY(para->ac_delays[i]),
+		       &mctl_ctl->acbdlr[i]);
+
+	/* DQSn, DMn, DQn output enable bit delay */
+	writel(0x4 << 24, &mctl_ctl->dx[0].sdlr);
+	writel(0x2 << 24, &mctl_ctl->dx[1].sdlr);
+
+	setbits_le32(&mctl_ctl->pgcr[0], 1 << 26);
+}
+
+static void mctl_apply_para(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;
+
+	clrsetbits_le32(&mctl_com->unk_0x008, 0x3f00, 0x2000);
+
+	writel(MCTL_CR_BL8 | MCTL_CR_INTERLEAVED |
+#if defined CONFIG_SUNXI_DRAM_DDR2
+	       MCTL_CR_DDR2 | MCTL_CR_2T |
+#elif defined CONFIG_SUNXI_DRAM_DDR3
+	       MCTL_CR_DDR3 | MCTL_CR_2T |
+#else
+#error Unsupported DRAM type!
+#endif
+	       (para->bank_bits == 3 ? MCTL_CR_EIGHT_BANKS : MCTL_CR_FOUR_BANKS) |
+	       MCTL_CR_BUS_FULL_WIDTH(para->bus_full_width) |
+	       (para->dual_rank ? MCTL_CR_DUAL_RANK : MCTL_CR_SINGLE_RANK) |
+	       MCTL_CR_PAGE_SIZE(para->page_size) |
+	       MCTL_CR_ROW_BITS(para->row_bits), &mctl_com->cr);
+
+	if (para->dual_rank)
+		writel(0x00000303, &mctl_ctl->odtmap);
+	else
+		writel(0x00000201, &mctl_ctl->odtmap);
+
+	if (!para->bus_full_width)
+		writel(0x0, &mctl_ctl->dx[1].gcr);
+
+	/* TODO: asymmetric dual rank */
+}
+
+static uint32_t mctl_r329_round_dram_clk(void)
+{
+	const int base_clk[] = {1200000, 800000, 516096, 1548288};
+	const int target_clk = CONFIG_DRAM_CLK * 2 * 1000;
+	int best_error = target_clk;
+	int best_mux = 0, best_n = 0, best_m = 0;
+
+	for (int mux = 0; mux < 4; mux++) {
+		for (int n = 0; n < 4; n++) {
+			for (int m = 0; m < 4; m++) {
+				int clk = base_clk[mux] / (1 << n) / (m + 1);
+				int error = target_clk - clk;
+
+				/* We shouldn't accept a higher result */
+				if (clk > target_clk)
+					continue;
+
+				if (error < best_error) {
+					best_error = error;
+					best_mux = mux;
+					best_n = n;
+					best_m = m;
+				}
+			}
+		}
+	}
+
+	return (((uint32_t) best_mux) << 24) | 
+	       (((uint32_t) best_n) << 8) |
+	       ((uint32_t) best_m);
+}
+
+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;
+	struct sunxi_prcm_reg * const prcm =
+			(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+
+	/*
+	 * These PLL2 values is the used by Allwinner BSP.
+	 *
+	 * The clock rate is 1548288 kHz according to BSP kernel.
+	 */
+
+	/* Enable PLL */
+	writel(0x09023f00, &prcm->pll2_cfg);
+	writel(0xc0070624, &prcm->pll2_pat0);
+	writel(0x0, &prcm->pll2_pat1);
+	udelay(5);
+	setbits_le32(&prcm->pll2_cfg, BIT(31) | BIT(29));
+	mctl_await_completion(&prcm->pll2_cfg, BIT(28), BIT(28));
+
+	/* Put all DRAM-related blocks to reset state */
+	clrbits_le32(&ccm->mbus_cfg, MBUS_ENABLE | MBUS_RESET);
+	clrbits_le32(&ccm->dram_gate_reset, BIT(0));
+	udelay(5);
+	writel(0, &ccm->dram_gate_reset);
+	clrbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
+	udelay(5);
+	clrbits_le32(&ccm->dram_clk_cfg, BIT(31));
+	udelay(5);
+	setbits_le32(&ccm->dram_clk_cfg, DRAM_CLK_UPDATE);
+
+	/* Configure DRAM mod clock */
+	writel(mctl_r329_round_dram_clk(), &ccm->dram_clk_cfg);
+
+	/* Disable all masters */
+	writel(1, &mctl_com->maer0);
+	writel(0, &mctl_com->maer1);
+	writel(0, &mctl_com->maer2);
+
+	/* Configure MBUS and enable DRAM mod gate and reset */
+	setbits_le32(&ccm->dram_gate_reset, BIT(RESET_SHIFT));
+	setbits_le32(&ccm->mbus_cfg, MBUS_RESET);
+	setbits_le32(&ccm->dram_clk_cfg, DRAM_MOD_RESET);
+	setbits_le32(&ccm->dram_gate_reset, BIT(0));
+	setbits_le32(&ccm->dram_clk_cfg, BIT(31));
+	setbits_le32(&ccm->dram_clk_cfg, DRAM_CLK_UPDATE);
+
+	/* Unknown hack from the BSP, which enables access of mctl_ctl regs */
+	writel(0x8000, &mctl_ctl->clken);
+}
+
+static void mctl_set_ddr3_magic(void)
+{
+	uint32_t magic_val_from_sid = (readl(SUNXI_SID_BASE + 0x20) >> 24) & 0xf;
+	if (magic_val_from_sid < 0xc) {
+		writel(0x08d08c40, SUNXI_DRAM_COM_BASE + 0x500);
+		writel(0x240030c5, SUNXI_DRAM_COM_BASE + 0x504);
+		writel(0x00000107, SUNXI_DRAM_COM_BASE + 0x508);
+		writel(0x2b4b4d60, SUNXI_DRAM_COM_BASE + 0x50c);
+		writel(0x08d08c41, SUNXI_DRAM_COM_BASE + 0x500);
+	} else if (magic_val_from_sid == 0xc) {
+		writel(0x02d20ca0, SUNXI_DRAM_COM_BASE + 0x500);
+		writel(0x24851cc2, SUNXI_DRAM_COM_BASE + 0x504);
+		writel(0x000031c9, SUNXI_DRAM_COM_BASE + 0x508);
+		writel(0x2b4b4573, SUNXI_DRAM_COM_BASE + 0x50c);
+		writel(0x02d20ca1, SUNXI_DRAM_COM_BASE + 0x500);
+	}
+}
+
+/* These are more guessed based on some Allwinner code. */
+#define DX_GCR_ODT_DYNAMIC	(0x0 << 4)
+#define DX_GCR_ODT_ALWAYS_ON	(0x1 << 4)
+#define DX_GCR_ODT_OFF		(0x2 << 4)
+
+static int mctl_channel_init(uint16_t socid, 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;
+
+	unsigned int i;
+
+	clrsetbits_le32(&mctl_ctl->iovcr[0], 0x7f7f7f7f, 0x48484848);
+	clrsetbits_le32(&mctl_ctl->iovcr[1], 0x7f, 0x48);
+
+	mctl_apply_para(para);
+#ifdef CONFIG_SUNXI_DRAM_DDR3
+	mctl_set_ddr3_magic();
+#endif
+	mctl_set_timing_params(socid, para);
+
+	clrsetbits_le32(&mctl_com->tmr, 0xfff, (CONFIG_DRAM_CLK / 2));
+
+	/* dphy & aphy phase select ? */
+	clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
+			(0x0 << 10) | (0x3 << 8));
+
+	/* set dramc odt */
+	for (i = 0; i < 4; i++) {
+		u32 clearmask = 0xf61e;
+		u32 setmask = IS_ENABLED(CONFIG_DRAM_ODT_EN) ?
+				DX_GCR_ODT_DYNAMIC : DX_GCR_ODT_OFF;
+		if (CONFIG_DRAM_CLK > 672)
+			setmask |= 0x400;
+
+		clrsetbits_le32(&mctl_ctl->dx[i].gcr, clearmask, setmask);
+	}
+
+	/* AC PDR should always ON */
+	clrsetbits_le32(&mctl_ctl->aciocr, 0, 0x1 << 1);
+
+	mctl_set_bit_delays(para);
+
+	/* set DQS auto gating PD mode */
+	setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
+
+	/* data training configuration */
+	clrsetbits_le32(&mctl_ctl->dtcr, 0x0fffffff,
+			(para->dual_rank ? 0x3 : 0x1) << 24 | 1);
+
+	udelay(50);
+
+	clrsetbits_le32(&mctl_ctl->zqcr, 0x3ffffff, 0x2000000 | CONFIG_DRAM_ZQ);
+
+	mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
+		      PIR_QSGATE | PIR_DRAMRST | PIR_DRAMINIT);
+	if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20))
+		return 1;
+
+	/* check the dramc status */
+	mctl_await_completion(&mctl_ctl->statr, 0x1, 0x1);
+
+	/* liuke added for refresh debug */
+	setbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
+	udelay(10);
+	clrbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31);
+	udelay(10);
+
+	setbits_le32(&mctl_com->unk_0x014, BIT(31));
+
+	clrbits_le32(&mctl_ctl->pgcr[3], 0x06000000);
+
+	return 0;
+}
+
+static void mctl_auto_detect_dram_size(struct dram_para *para)
+{
+	/* detect row address bits */
+	para->page_size = 512;
+	para->row_bits = 16;
+	para->bank_bits = 2;
+	mctl_apply_para(para);
+
+	for (para->row_bits = 11; para->row_bits < 16; para->row_bits++)
+		if (mctl_mem_matches((1 << (para->row_bits + para->bank_bits)) * para->page_size))
+			break;
+
+	/* detect bank address bits */
+	para->bank_bits = 3;
+	mctl_apply_para(para);
+
+	for (para->bank_bits = 2; para->bank_bits < 3; para->bank_bits++)
+		if (mctl_mem_matches((1 << para->bank_bits) * para->page_size))
+			break;
+
+	/* detect page size */
+	para->page_size = 8192;
+	mctl_apply_para(para);
+
+	for (para->page_size = 512; para->page_size < 8192; para->page_size *= 2)
+		if (mctl_mem_matches(para->page_size))
+			break;
+}
+
+#define SUN50I_R329_DX_READ_DELAYS					\
+	{{ 10, 10, 10, 10, 10, 10, 10, 10, 10,  0,  0 },	\
+	 { 10, 10, 10, 10, 10, 10, 10, 10, 10,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }}
+#define SUN50I_R329_DX_WRITE_DELAYS				\
+	{{  0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },	\
+	 {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }}
+#define SUN50I_R329_AC_DELAYS					\
+	{  0,  0,  0,  0,  0,  0,  0,  0,			\
+	   0,  0,  0,  0,  0,  0,  0,  0,			\
+	   0,  0,  0,  0,  0,  0,  0,  0,			\
+	   0,  0,  0,  0,  0,  0,  0      }
+
+unsigned long sunxi_dram_init(void)
+{
+	struct sunxi_mctl_com_reg * const mctl_com =
+			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
+	struct sunxi_mctl_ctl_reg * const mctl_ctl =
+			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+	struct dram_para para = {
+		.dual_rank = 0,
+		.bus_full_width = 1,
+		.row_bits = 16,
+		.bank_bits = 3,
+		.page_size = 8192,
+
+		.dx_read_delays  = SUN50I_R329_DX_READ_DELAYS,
+		.dx_write_delays = SUN50I_R329_DX_WRITE_DELAYS,
+		.ac_delays	 = SUN50I_R329_AC_DELAYS,
+	};
+
+	/* Unknown magic */
+	writel(0x10, 0x07010250);
+	writel(0x330000, 0x07010310);
+	writel(0x330003, 0x07010310);
+
+#if defined(CONFIG_MACH_SUN50I_R329)
+	uint16_t socid = SOCID_R329;
+#endif
+
+	mctl_sys_init(&para);
+	if (mctl_channel_init(socid, &para))
+		return 0;
+
+	udelay(1);
+
+	clrbits_le32(&mctl_ctl->unk_0x0a0, 0xffff);
+	clrbits_le32(&mctl_ctl->pwrctl, 0x1);
+
+	/* HDR/DDR dynamic mode */
+	clrbits_le32(&mctl_ctl->pgcr[0], 0xf000);
+
+	/* power down zq calibration module for power save */
+	setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
+
+	/* DQ hold disable (tpr13[26] == 1) */
+	clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
+
+	mctl_auto_detect_dram_size(&para);
+	mctl_apply_para(&para);
+
+	/* enable master access */
+	writel(0xffffffff, &mctl_com->maer0);
+	writel(0x7f, &mctl_com->maer1);
+	writel(0xffff, &mctl_com->maer2);
+
+	return (1UL << (para.row_bits + para.bank_bits)) * para.page_size *
+	       (para.dual_rank ? 2 : 1);
+}
diff --git a/arch/arm/mach-sunxi/dram_timings/Makefile b/arch/arm/mach-sunxi/dram_timings/Makefile
index 39a8756c29..32d5f15c61 100644
--- a/arch/arm/mach-sunxi/dram_timings/Makefile
+++ b/arch/arm/mach-sunxi/dram_timings/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_SUNXI_DRAM_DDR3_1333)	+= ddr3_1333.o
+obj-$(CONFIG_SUNXI_DRAM_DDR3_R329)	+= ddr3_r329.o
 obj-$(CONFIG_SUNXI_DRAM_LPDDR3_STOCK)	+= lpddr3_stock.o
 obj-$(CONFIG_SUNXI_DRAM_DDR2_V3S)	+= ddr2_v3s.o
 obj-$(CONFIG_SUNXI_DRAM_H6_LPDDR3)	+= h6_lpddr3.o
diff --git a/arch/arm/mach-sunxi/dram_timings/ddr3_r329.c b/arch/arm/mach-sunxi/dram_timings/ddr3_r329.c
new file mode 100644
index 0000000000..e8a34e7da3
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_timings/ddr3_r329.c
@@ -0,0 +1,89 @@
+#include <common.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/cpu.h>
+
+void mctl_set_timing_params(uint16_t socid, struct dram_para *para)
+{
+	struct sunxi_mctl_ctl_reg * const mctl_ctl =
+			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+	u8 tccd		= 2;
+	u8 tfaw		= ns_to_t(50);
+	u8 trrd		= max(ns_to_t(10), 2);
+	u8 trcd		= ns_to_t(15);
+	u8 trc		= ns_to_t(53);
+	u8 txp		= max(ns_to_t(8), 2);
+	u8 twtr		= max(ns_to_t(8), 2);
+	u8 trtp		= max(ns_to_t(8), 2);
+	u8 twr		= max(ns_to_t(15), 2);
+	u8 trp		= ns_to_t(15);
+	u8 tras		= ns_to_t(38);
+	u16 trefi	= ns_to_t(7800) / 32 + 1;
+	u16 trfc	= ns_to_t(350);
+
+	u8 tmrw		= 0;
+	u8 tmrd		= 4;
+	u8 tmod		= 12;
+	u8 tcke		= 3;
+	u8 tcksrx	= 5;
+	u8 tcksre	= 5;
+	u8 tckesr	= 4;
+	u8 trasmax	= 25;
+
+	u8 tcl		= 6; /* CL 12 */
+	u8 tcwl		= 4; /* CWL 8 */
+	u8 t_rdata_en	= 4;
+	u8 wr_latency	= 2;
+
+	u32 tdinit0	= (500 * CONFIG_DRAM_CLK) + 1;		/* 500us */
+	u32 tdinit1	= (360 * CONFIG_DRAM_CLK) / 1000 + 1;	/* 360ns */
+	u32 tdinit2	= (200 * CONFIG_DRAM_CLK) + 1;		/* 200us */
+	u32 tdinit3	= (1 * CONFIG_DRAM_CLK) + 1;		/* 1us */
+
+	u8 twtp		= tcwl + 2 + twr;	/* WL + BL / 2 + tWR */
+	u8 twr2rd	= tcwl + 2 + twtr;	/* WL + BL / 2 + tWTR */
+	u8 trd2wr	= 5;
+
+	if (trtp < tcl + 2 - trp)
+		trtp = tcl + 2 - trp;
+	
+	/* set mode register */
+	writel(0x1c70, &mctl_ctl->mr[0]);	/* CL=11, WR=12 */
+	writel(0x2, &mctl_ctl->mr[1]);
+	writel(0x18, &mctl_ctl->mr[2]);		/* CWL=8 */
+	writel(0x0, &mctl_ctl->mr[3]);
+
+	/* set DRAM timing */
+	writel(DRAMTMG0_TWTP(twtp) | DRAMTMG0_TFAW(tfaw) |
+	       DRAMTMG0_TRAS_MAX(trasmax) | DRAMTMG0_TRAS(tras),
+	       &mctl_ctl->dramtmg[0]);
+	writel(DRAMTMG1_TXP(txp) | DRAMTMG1_TRTP(trtp) | DRAMTMG1_TRC(trc),
+	       &mctl_ctl->dramtmg[1]);
+	writel(DRAMTMG2_TCWL(tcwl) | DRAMTMG2_TCL(tcl) |
+	       DRAMTMG2_TRD2WR(trd2wr) | DRAMTMG2_TWR2RD(twr2rd),
+	       &mctl_ctl->dramtmg[2]);
+	writel(DRAMTMG3_TMRW(tmrw) | DRAMTMG3_TMRD(tmrd) | DRAMTMG3_TMOD(tmod),
+	       &mctl_ctl->dramtmg[3]);
+	writel(DRAMTMG4_TRCD(trcd) | DRAMTMG4_TCCD(tccd) | DRAMTMG4_TRRD(trrd) |
+	       DRAMTMG4_TRP(trp), &mctl_ctl->dramtmg[4]);
+	writel(DRAMTMG5_TCKSRX(tcksrx) | DRAMTMG5_TCKSRE(tcksre) |
+	       DRAMTMG5_TCKESR(tckesr) | DRAMTMG5_TCKE(tcke),
+	       &mctl_ctl->dramtmg[5]);
+
+	/* set two rank timing */
+	clrsetbits_le32(&mctl_ctl->dramtmg[8], (0xf0 << 24) | (0xff << 8) | (0xff << 0),
+			(0xf0 << 24) | (0x66 << 8) | (0x10 << 0));
+
+
+	/* set PHY interface timing, write latency and read latency configure */
+	writel((0x2 << 24) | (t_rdata_en << 16) | (0x1 << 8) |
+	       (wr_latency << 0), &mctl_ctl->pitmg[0]);
+
+	/* set PHY timing, PTR0-2 use default */
+	writel(PTR3_TDINIT0(tdinit0) | PTR3_TDINIT1(tdinit1), &mctl_ctl->ptr[3]);
+	writel(PTR4_TDINIT2(tdinit2) | PTR4_TDINIT3(tdinit3), &mctl_ctl->ptr[4]);
+
+	/* set refresh timing */
+	writel(RFSHTMG_TREFI(trefi) | RFSHTMG_TRFC(trfc), &mctl_ctl->rfshtmg[0]);
+	writel((trefi / 2) << 16, &mctl_ctl->rfshtmg[1]);
+}
-- 
2.30.2


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

* [RFC PATCH 08/13] sunxi: add Kconfig option for R329
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
                   ` (6 preceding siblings ...)
  2021-07-22  6:30 ` [RFC PATCH 07/13] sunxi: add support for R329 DRAM controller Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 09/13] sunxi: sync R329 CCU binding headers from internal WIP kernel tree Icenowy Zheng
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

As most code are ready for basic R329 support, let's add a Kconfig
option for it.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 arch/arm/mach-sunxi/Kconfig    | 14 +++++++++++++-
 arch/arm/mach-sunxi/cpu_info.c |  2 ++
 common/spl/Kconfig             |  1 +
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index c9bb47a8bd..9d3ec82497 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -128,6 +128,7 @@ config SUN8I_RSB
 config SUNXI_SRAM_ADDRESS
 	hex
 	default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
+	default 0x100000 if MACH_SUN50I_R329
 	default 0x20000 if SUN50I_GEN_H6
 	default 0x0
 	---help---
@@ -371,6 +372,12 @@ config MACH_SUN50I_H616
 	select DRAM_SUN50I_H616
 	select SUN50I_GEN_H6
 
+config MACH_SUN50I_R329
+	bool "sun50i (Allwinner R329)"
+	select ARM64
+	select DRAM_SUN50I_R329
+	select SUN50I_GEN_H6
+
 endchoice
 
 # The sun8i SoCs share a lot, this helps to avoid a lot of "if A23 || A33"
@@ -420,7 +427,8 @@ config SUNXI_DRAM_LPDDR3
 
 choice
 	prompt "DRAM Type and Timing"
-	default SUNXI_DRAM_DDR3_1333 if !MACH_SUN8I_V3S
+	default SUNXI_DRAM_DDR3_1333 if !MACH_SUN8I_V3S && !MACH_SUN50I_R329
+	default SUNXI_DRAM_DDR3_R329 if MACH_SUN50I_R329
 	default SUNXI_DRAM_DDR2_V3S if MACH_SUN8I_V3S
 
 config SUNXI_DRAM_DDR3_1333
@@ -488,6 +496,7 @@ config DRAM_CLK
 		       MACH_SUN8I_V3S
 	default 672 if MACH_SUN50I
 	default 744 if MACH_SUN50I_H6
+	default 775 if MACH_SUN50I_R329
 	default 720 if MACH_SUN50I_H616
 	---help---
 	Set the dram clock speed, valid range 240 - 480 (prior to sun9i),
@@ -510,6 +519,7 @@ config DRAM_ZQ
 		       MACH_SUN8I_A23 || MACH_SUN8I_A33 || MACH_SUN8I_A83T
 	default 127 if MACH_SUN7I
 	default 14779 if MACH_SUN8I_V3S
+	default 3067 if MACH_SUN50I_R329
 	default 3881979 if MACH_SUNXI_H3_H5 || MACH_SUN8I_R40 || MACH_SUN50I_H6
 	default 4145117 if MACH_SUN9I
 	default 3881915 if MACH_SUN50I
@@ -616,6 +626,7 @@ config SYS_CLK_FREQ
 	default 1008000000 if MACH_SUN9I
 	default 888000000 if MACH_SUN50I_H6
 	default 1008000000 if MACH_SUN50I_H616
+	default 1008000000 if MACH_SUN50I_R329
 
 config SYS_CONFIG_NAME
 	default "sun4i" if MACH_SUN4I
@@ -627,6 +638,7 @@ config SYS_CONFIG_NAME
 	default "sun50i" if MACH_SUN50I
 	default "sun50i" if MACH_SUN50I_H6
 	default "sun50i" if MACH_SUN50I_H616
+	default "sun50i" if MACH_SUN50I_R329
 
 config SYS_BOARD
 	default "sunxi"
diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
index ba33ef2430..8021f4c307 100644
--- a/arch/arm/mach-sunxi/cpu_info.c
+++ b/arch/arm/mach-sunxi/cpu_info.c
@@ -101,6 +101,8 @@ int print_cpuinfo(void)
 	puts("CPU:   Allwinner H6 (SUN50I)\n");
 #elif defined CONFIG_MACH_SUN50I_H616
 	puts("CPU:   Allwinner H616 (SUN50I)\n");
+#elif defined CONFIG_MACH_SUN50I_R329
+	puts("CPU:   Allwinner R329 (SUN50I)\n");
 #else
 #warning Please update cpu_info.c with correct CPU information
 	puts("CPU:   SUNXI Family\n");
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 2df3e5d869..ed4477ff93 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -150,6 +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 0x100060 if MACH_SUN50I_R329
 	default 0x20060 if SUN50I_GEN_H6
 	default 0x00060 if ARCH_SUNXI
 	default 0xfffc0000 if ARCH_ZYNQMP
-- 
2.30.2


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

* [RFC PATCH 09/13] sunxi: sync R329 CCU binding headers from internal WIP kernel tree
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
                   ` (7 preceding siblings ...)
  2021-07-22  6:30 ` [RFC PATCH 08/13] sunxi: add Kconfig option for R329 Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 10/13] clk: sunxi: add support for R329 in sunxi DM clock driver Icenowy Zheng
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 include/dt-bindings/clock/sun50i-r329-ccu.h   | 73 +++++++++++++++++++
 include/dt-bindings/clock/sun50i-r329-r-ccu.h | 32 ++++++++
 include/dt-bindings/reset/sun50i-r329-ccu.h   | 45 ++++++++++++
 include/dt-bindings/reset/sun50i-r329-r-ccu.h | 23 ++++++
 4 files changed, 173 insertions(+)
 create mode 100644 include/dt-bindings/clock/sun50i-r329-ccu.h
 create mode 100644 include/dt-bindings/clock/sun50i-r329-r-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-ccu.h
 create mode 100644 include/dt-bindings/reset/sun50i-r329-r-ccu.h

diff --git a/include/dt-bindings/clock/sun50i-r329-ccu.h b/include/dt-bindings/clock/sun50i-r329-ccu.h
new file mode 100644
index 0000000000..769a40a175
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-r329-ccu.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
+#define _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_
+
+#define CLK_CPUX		1
+
+#define CLK_APB1		5
+
+#define CLK_CE			7
+#define CLK_BUS_CE		8
+#define CLK_AIPU		9
+#define CLK_BUS_VE		10
+#define CLK_BUS_DMA		11
+#define CLK_BUS_MSGBOX		12
+#define CLK_BUS_SPINLOCK	13
+#define CLK_BUS_HSTIMER		14
+#define CLK_AVS			15
+#define CLK_BUS_DBG		16
+#define CLK_BUS_PWM		17
+
+#define CLK_MBUS_DMA		19
+#define CLK_MBUS_CE		20
+#define CLK_MBUS_NAND		21
+#define CLK_MBUS_CSI		22
+#define CLK_MBUS_ISP		23
+
+#define CLK_NAND0		25
+#define CLK_NAND1		26
+#define CLK_BUS_NAND		27
+#define CLK_MMC0		28
+#define CLK_MMC1		29
+#define CLK_BUS_MMC0		30
+#define CLK_BUS_MMC1		31
+#define CLK_BUS_UART0		32
+#define CLK_BUS_UART1		33
+#define CLK_BUS_UART2		34
+#define CLK_BUS_UART3		35
+#define CLK_BUS_I2C0		36
+#define CLK_BUS_I2C1		37
+#define CLK_BUS_SCR		38
+#define CLK_SPI0		39
+#define CLK_SPI1		40
+#define CLK_BUS_SPI0		41
+#define CLK_BUS_SPI1		42
+#define CLK_EMAC_25M_DIV	43
+#define CLK_EMAC_25M		44
+#define CLK_BUS_EMAC		45
+#define CLK_IR_RX		46
+#define CLK_BUS_IR_RX		47
+#define CLK_IR_TX		48
+#define CLK_BUS_IR_TX		49
+#define CLK_I2S0		50
+#define CLK_I2S1		51
+#define CLK_BUS_I2S0		52
+#define CLK_BUS_I2S1		53
+#define CLK_SPDIF		54
+#define CLK_BUS_SPDIF		55
+#define CLK_USB_OHCI0		56
+#define CLK_USB_PHY0		57
+#define CLK_USB_OHCI1		58
+#define CLK_USB_PHY1		59
+#define CLK_BUS_OHCI0		60
+#define CLK_BUS_OHCI1		61
+#define CLK_BUS_EHCI0		62
+#define CLK_BUS_OTG		63
+#define CLK_LEDC		64
+#define CLK_BUS_LEDC		65
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_R329_CCU_H_ */
diff --git a/include/dt-bindings/clock/sun50i-r329-r-ccu.h b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
new file mode 100644
index 0000000000..2044d25383
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-r329-r-ccu.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_
+
+#define CLK_R_APB1		12
+
+#define CLK_R_BUS_GPADC		14
+#define CLK_R_BUS_THS		15
+#define CLK_R_PWM		16
+#define CLK_R_BUS_PWM		17
+#define CLK_R_CODEC_ADC		18
+#define CLK_R_CODEC_DAC		19
+#define CLK_R_BUS_CODEC		20
+#define CLK_R_DMIC		21
+#define CLK_R_BUS_DMIC		22
+#define CLK_R_BUS_LRADC		23
+#define CLK_R_I2S		24
+#define CLK_R_I2S_ASRC		25
+#define CLK_R_BUS_I2S		26
+#define CLK_R_BUS_UART		27
+#define CLK_R_BUS_I2C		28
+#define CLK_R_IR		29
+#define CLK_R_BUS_IR		30
+#define CLK_R_BUS_MSGBOX	31
+#define CLK_R_BUS_SPINLOCK	32
+#define CLK_R_BUS_RTC		33
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_R329_R_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun50i-r329-ccu.h b/include/dt-bindings/reset/sun50i-r329-ccu.h
new file mode 100644
index 0000000000..bb704a8244
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-r329-ccu.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
+#define _DT_BINDINGS_RST_SUN50I_R329_CCU_H_
+
+#define RST_MBUS		0
+#define RST_BUS_CE		1
+#define RST_BUS_AIPU		2
+#define RST_BUS_DMA		3
+#define RST_BUS_MSGBOX		4
+#define RST_BUS_SPINLOCK	5
+#define RST_BUS_HSTIMER		6
+#define RST_BUS_DBG		7
+#define RST_BUS_PWM		8
+#define RST_BUS_DRAM		9
+#define RST_BUS_NAND		10
+#define RST_BUS_MMC0		11
+#define RST_BUS_MMC1		12
+#define RST_BUS_UART0		13
+#define RST_BUS_UART1		14
+#define RST_BUS_UART2		15
+#define RST_BUS_UART3		16
+#define RST_BUS_I2C0		17
+#define RST_BUS_I2C1		18
+#define RST_BUS_SCR		19
+#define RST_BUS_SPI0		20
+#define RST_BUS_SPI1		21
+#define RST_BUS_EMAC		22
+#define RST_BUS_IR_RX		23
+#define RST_BUS_IR_TX		24
+#define RST_BUS_I2S0		25
+#define RST_BUS_I2S1		26
+#define RST_BUS_SPDIF		27
+#define RST_USB_PHY0		28
+#define RST_USB_PHY1		29
+#define RST_BUS_OHCI0		30
+#define RST_BUS_OHCI1		31
+#define RST_BUS_EHCI0		32
+#define RST_BUS_OTG		33
+#define RST_BUS_LEDC		34
+
+#endif /* _DT_BINDINGS_RST_SUN50I_R329_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun50i-r329-r-ccu.h b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
new file mode 100644
index 0000000000..e65a317afb
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-r329-r-ccu.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (c) 2021 Sipeed
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
+#define _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_
+
+#define RST_R_BUS_GPADC		0
+#define RST_R_BUS_THS		1
+#define RST_R_BUS_PWM		2
+#define RST_R_BUS_CODEC		3
+#define RST_R_BUS_DMIC		4
+#define RST_R_BUS_LRADC		5
+#define RST_R_BUS_I2S		6
+#define RST_R_BUS_UART		7
+#define RST_R_BUS_I2C		8
+#define RST_R_BUS_IR		9
+#define RST_R_BUS_MSGBOX	10
+#define RST_R_BUS_SPINLOCK	11
+#define RST_R_BUS_RTC		12
+
+#endif /* _DT_BINDINGS_RST_SUN50I_R329_R_CCU_H_ */
-- 
2.30.2


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

* [RFC PATCH 10/13] clk: sunxi: add support for R329 in sunxi DM clock driver
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
                   ` (8 preceding siblings ...)
  2021-07-22  6:30 ` [RFC PATCH 09/13] sunxi: sync R329 CCU binding headers from internal WIP kernel tree Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 11/13] mmc: sunxi: add support for R329 MMC controller Icenowy Zheng
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

Currently only a subset of clocks/resets (similar to other SoCs) are
supported.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/clk/sunxi/Kconfig    |  7 +++
 drivers/clk/sunxi/Makefile   |  1 +
 drivers/clk/sunxi/clk_r329.c | 94 ++++++++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_r329.c

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index bf084fa7a8..8dd3be4683 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -86,6 +86,13 @@ config CLK_SUN50I_H616
 	  This enables common clock driver support for platforms based
 	  on Allwinner H616 SoC.
 
+config CLK_SUN50I_R329
+	bool "Clock driver for Allwinner R329"
+	default MACH_SUN50I_R329
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner R329 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 4f9282a8b9..050f7ecc46 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -19,4 +19,5 @@ 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_R329) += clk_r329.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_r329.c b/drivers/clk/sunxi/clk_r329.c
new file mode 100644
index 0000000000..17157214b6
--- /dev/null
+++ b/drivers/clk/sunxi/clk_r329.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2021 Sipeed
+ * Based on clk_h616.c, which is:
+ *   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-r329-ccu.h>
+#include <dt-bindings/reset/sun50i-r329-ccu.h>
+#include <linux/bitops.h>
+
+static struct ccu_clk_gate r329_gates[] = {
+	[CLK_BUS_MMC0]		= GATE(0x84c, BIT(0)),
+	[CLK_BUS_MMC1]		= GATE(0x84c, BIT(1)),
+
+	[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_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_EMAC]		= GATE(0x97c, BIT(0)),
+
+	[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_BUS_OHCI0]		= GATE(0xa8c, BIT(0)),
+	[CLK_BUS_OHCI1]		= GATE(0xa8c, BIT(1)),
+	[CLK_BUS_EHCI0]		= GATE(0xa8c, BIT(4)),
+	[CLK_BUS_OTG]		= GATE(0xa8c, BIT(8)),
+};
+
+static struct ccu_reset r329_resets[] = {
+	[RST_BUS_MMC0]		= RESET(0x84c, BIT(16)),
+	[RST_BUS_MMC1]		= RESET(0x84c, BIT(17)),
+
+	[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_SPI0]		= RESET(0x96c, BIT(16)),
+	[RST_BUS_SPI1]		= RESET(0x96c, BIT(17)),
+
+	[RST_BUS_EMAC]		= RESET(0x97c, BIT(16)),
+
+	[RST_USB_PHY0]		= RESET(0xa70, BIT(30)),
+
+	[RST_USB_PHY1]		= RESET(0xa74, BIT(30)),
+
+	[RST_BUS_OHCI0]		= RESET(0xa8c, BIT(16)),
+	[RST_BUS_OHCI1]		= RESET(0xa8c, BIT(17)),
+	[RST_BUS_EHCI0]		= RESET(0xa8c, BIT(20)),
+	[RST_BUS_OTG]		= RESET(0xa8c, BIT(24)),
+};
+
+static const struct ccu_desc r329_ccu_desc = {
+	.gates = r329_gates,
+	.resets = r329_resets,
+};
+
+static int r329_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, ARRAY_SIZE(r329_resets));
+}
+
+static const struct udevice_id r329_ccu_ids[] = {
+	{ .compatible = "allwinner,sun50i-r329-ccu",
+	  .data = (ulong)&r329_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun50i_r329) = {
+	.name		= "sun50i_r329_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= r329_ccu_ids,
+	.priv_auto	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= r329_clk_bind,
+};
-- 
2.30.2


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

* [RFC PATCH 11/13] mmc: sunxi: add support for R329 MMC controller
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
                   ` (9 preceding siblings ...)
  2021-07-22  6:30 ` [RFC PATCH 10/13] clk: sunxi: add support for R329 in sunxi DM clock driver Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 12/13] sunxi: sync R329 DTs from internal WIP kernel tree Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 13/13] sunxi: add support for Sipeed Maix IIA Dock board Icenowy Zheng
  12 siblings, 0 replies; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

R329 SoC has similar MMC controllers with previous Allwinner SoCs.

Add support for it by adding its compatible string.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 drivers/mmc/sunxi_mmc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 6b809c001f..59cc28794d 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -734,6 +734,7 @@ static const struct udevice_id sunxi_mmc_ids[] = {
 	{ .compatible = "allwinner,sun50i-h6-emmc" },
 	{ .compatible = "allwinner,sun50i-a100-mmc" },
 	{ .compatible = "allwinner,sun50i-a100-emmc" },
+	{ .compatible = "allwinner,sun50i-r329-mmc" },
 	{ /* sentinel */ }
 };
 
-- 
2.30.2



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

* [RFC PATCH 12/13] sunxi: sync R329 DTs from internal WIP kernel tree
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
                   ` (10 preceding siblings ...)
  2021-07-22  6:30 ` [RFC PATCH 11/13] mmc: sunxi: add support for R329 MMC controller Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  2021-07-22  6:30 ` [RFC PATCH 13/13] sunxi: add support for Sipeed Maix IIA Dock board Icenowy Zheng
  12 siblings, 0 replies; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 arch/arm/dts/Makefile                      |   2 +
 arch/arm/dts/sun50i-r329-maix-iia-dock.dts |  36 ++++
 arch/arm/dts/sun50i-r329-maix-iia.dtsi     |  45 +++++
 arch/arm/dts/sun50i-r329.dtsi              | 225 +++++++++++++++++++++
 4 files changed, 308 insertions(+)
 create mode 100644 arch/arm/dts/sun50i-r329-maix-iia-dock.dts
 create mode 100644 arch/arm/dts/sun50i-r329-maix-iia.dtsi
 create mode 100644 arch/arm/dts/sun50i-r329.dtsi

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 3941a08cf4..cfafb80a5f 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -643,6 +643,8 @@ dtb-$(CONFIG_MACH_SUN50I_H6) += \
 	sun50i-h6-tanix-tx6.dtb
 dtb-$(CONFIG_MACH_SUN50I_H616) += \
 	sun50i-h616-orangepi-zero2.dtb
+dtb-$(CONFIG_MACH_SUN50I_R329) += \
+	sun50i-r329-maix-iia-dock.dtb
 dtb-$(CONFIG_MACH_SUN50I) += \
 	sun50i-a64-amarula-relic.dtb \
 	sun50i-a64-bananapi-m64.dtb \
diff --git a/arch/arm/dts/sun50i-r329-maix-iia-dock.dts b/arch/arm/dts/sun50i-r329-maix-iia-dock.dts
new file mode 100644
index 0000000000..2588eb6adb
--- /dev/null
+++ b/arch/arm/dts/sun50i-r329-maix-iia-dock.dts
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (c) 2021 Sipeed
+
+/dts-v1/;
+
+#include "sun50i-r329-maix-iia.dtsi"
+
+/ {
+	model = "Sipeed MAIX-II A Dock";
+	compatible = "sipeed,maix-iia-dock", "sipeed,maix-iia",
+		     "allwinner,sun50i-r329";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pf_pins>;
+
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+	status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-r329-maix-iia.dtsi b/arch/arm/dts/sun50i-r329-maix-iia.dtsi
new file mode 100644
index 0000000000..ac5c5a88d3
--- /dev/null
+++ b/arch/arm/dts/sun50i-r329-maix-iia.dtsi
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (c) 2021 Sipeed
+
+#include "sun50i-r329.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	ext_osc32k: ext_osc32k_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+		clock-output-names = "ext_osc32k";
+	};
+
+	reg_vcc3v3: vcc3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&r_pio 1 0 GPIO_ACTIVE_LOW>; /* PM0 */
+		post-power-on-delay-ms = <200>;
+	};
+};
+
+&rtc {
+	clocks = <&ext_osc32k>;
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_clk_pg0>, <&mmc1_cmd_pg1>, <&mmc1_d0_pg2>,
+		    <&mmc1_d1_pg3>, <&mmc1_d2_pg4>, <&mmc1_d3_pg5>;
+
+	vmmc-supply = <&reg_vcc3v3>;
+	vqmmc-supply = <&reg_vcc3v3>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-r329.dtsi b/arch/arm/dts/sun50i-r329.dtsi
new file mode 100644
index 0000000000..b4752020df
--- /dev/null
+++ b/arch/arm/dts/sun50i-r329.dtsi
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (c) 2021 Sipeed
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun50i-r329-ccu.h>
+#include <dt-bindings/reset/sun50i-r329-ccu.h>
+#include <dt-bindings/clock/sun50i-r329-r-ccu.h>
+#include <dt-bindings/reset/sun50i-r329-r-ccu.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+			reg = <0>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu@1 {
+			compatible = "arm,cortex-a53";
+			device_type = "cpu";
+			reg = <1>;
+			enable-method = "psci";
+		};
+	};
+
+	osc24M: osc24M_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "osc24M";
+	};
+
+	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(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		pio: pinctrl@2000400 {
+			compatible = "allwinner,sun50i-r329-pinctrl";
+			reg = <0x02000400 0x400>;
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 73 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>;
+
+			uart0_pb_pins: uart0-pb-pins {
+				pins = "PB4", "PB5";
+				function = "uart0";
+			};
+
+			mmc0_pf_pins: mmc0-pf-pins {
+				pins = "PF0", "PF1", "PF2",
+				       "PF3", "PF4", "PF5";
+				function = "mmc0";
+			};
+
+			mmc1_clk_pg0: mmc1-clk-pg0 {
+				pins = "PG0";
+				function = "mmc1_clk";
+			};
+
+			mmc1_cmd_pg1: mmc1-clk-pg1 {
+				pins = "PG1";
+				function = "mmc1_cmd";
+			};
+
+			mmc1_d0_pg2: mmc1-clk-pg2 {
+				pins = "PG2";
+				function = "mmc1_d0";
+			};
+
+			mmc1_d1_pg3: mmc1-clk-pg3 {
+				pins = "PG3";
+				function = "mmc1_d1";
+			};
+
+			mmc1_d2_pg4: mmc1-clk-pg4 {
+				pins = "PG4";
+				function = "mmc1_d2";
+			};
+
+			mmc1_d3_pg5: mmc1-clk-pg5 {
+				pins = "PG5";
+				function = "mmc1_d3";
+			};
+
+			spi1_cs_ph0: spi1-cs-ph0 {
+				pins = "PH0";
+				function = "spi1";
+			};
+
+			spi1_clk_ph1: spi1-clk-ph1 {
+				pins = "PH1";
+				function = "spi1";
+			};
+
+			spi1_mosi_ph2: spi1-mosi-ph2 {
+				pins = "PH2";
+				function = "spi1";
+			};
+		};
+
+		ccu: clock@2001000 {
+			compatible = "allwinner,sun50i-r329-ccu";
+			reg = <0x02001000 0x1000>;
+			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
+			clock-names = "hosc", "losc", "iosc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		uart0: serial@2500000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x02500000 0x400>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu CLK_BUS_UART0>;
+			resets = <&ccu RST_BUS_UART0>;
+		};
+
+		gic: interrupt-controller@3021000 {
+			compatible = "arm,gic-400";
+			reg = <0x03021000 0x1000>,
+			      <0x03022000 0x2000>,
+			      <0x03024000 0x2000>,
+			      <0x03026000 0x2000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+		};
+
+		mmc0: mmc@4020000 {
+			compatible = "allwinner,sun50i-r329-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 40 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mmc1: mmc@4021000 {
+			compatible = "allwinner,sun50i-r329-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 41 IRQ_TYPE_LEVEL_HIGH>;
+			max-frequency = <150000000>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		r_ccu: clock@7010000 {
+			compatible = "allwinner,sun50i-r329-r-ccu";
+			reg = <0x07010000 0x10000>;
+			clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
+			clock-names = "hosc", "losc", "iosc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		r_pio: pinctrl@7022000 {
+			compatible = "allwinner,sun50i-r329-r-pinctrl";
+			reg = <0x07022000 0x400>;
+			interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 109 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>;
+		};
+
+		rtc: rtc@7090000 {
+			compatible = "allwinner,sun50i-r329-rtc";
+			reg = <0x07090000 0x400>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			clock-output-names = "osc32k", "osc32k-out", "iosc";
+			#clock-cells = <1>;
+		};
+	};
+};
-- 
2.30.2


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

* [RFC PATCH 13/13] sunxi: add support for Sipeed Maix IIA Dock board
  2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
                   ` (11 preceding siblings ...)
  2021-07-22  6:30 ` [RFC PATCH 12/13] sunxi: sync R329 DTs from internal WIP kernel tree Icenowy Zheng
@ 2021-07-22  6:30 ` Icenowy Zheng
  12 siblings, 0 replies; 17+ messages in thread
From: Icenowy Zheng @ 2021-07-22  6:30 UTC (permalink / raw)
  To: Jagan Teki, Andre Przywara, Jernej Skrabec, Samuel Holland
  Cc: u-boot, linux-sunxi, Icenowy Zheng

Maix IIA is a SoM by Sipeed, and a official baseboard is sold with it.

Add support for this official baseboard with Maix IIA attached.

Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>
---
 board/sunxi/MAINTAINERS                | 5 +++++
 configs/sipeed_maix_iia_dock_defconfig | 8 ++++++++
 2 files changed, 13 insertions(+)
 create mode 100644 configs/sipeed_maix_iia_dock_defconfig

diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index 4fc26077b2..ae7c6a131a 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -493,6 +493,11 @@ M:	VishnuPatekar <vishnupatekar0510@gmail.com>
 S:	Maintained
 F:	configs/Sinovoip_BPI_M3_defconfig
 
+SIPEED MAIX IIA DOCK BOARD
+M:	Icenowy Zheng <icenowy@sipeed.com>
+S:	Maintained
+F:	configs/sipeed_maix_iia_dock_defconfig
+
 SOPINE BOARD
 M:	Icenowy Zheng <icenowy@aosc.io>
 S:	Maintained
diff --git a/configs/sipeed_maix_iia_dock_defconfig b/configs/sipeed_maix_iia_dock_defconfig
new file mode 100644
index 0000000000..a839f65e10
--- /dev/null
+++ b/configs/sipeed_maix_iia_dock_defconfig
@@ -0,0 +1,8 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-r329-maix-iia-dock"
+CONFIG_SPL=y
+CONFIG_MACH_SUN50I_R329=y
+CONFIG_MMC0_CD_PIN="PF6"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_ENV_FAT_DEVICE_AND_PART="1:auto"
-- 
2.30.2


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

* Re: [RFC PATCH 01/13] sunxi: decide the inclusion of SCP by SCP_ADDR existence
  2021-07-22  6:30 ` [RFC PATCH 01/13] sunxi: decide the inclusion of SCP by SCP_ADDR existence Icenowy Zheng
@ 2021-07-22 13:35   ` Andre Przywara
  0 siblings, 0 replies; 17+ messages in thread
From: Andre Przywara @ 2021-07-22 13:35 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Jagan Teki, Jernej Skrabec, Samuel Holland, u-boot, linux-sunxi

On Thu, 22 Jul 2021 14:30:03 +0800
Icenowy Zheng <icenowy@sipeed.com> wrote:

> There are more Allwinner SoCs that do not have a SCP now.
> 
> When there's no SCP_ADDR macro defined, we can assume there's no SCP
> available.
> 
> Drop the scp part of FIT description when SCP_ADDR does not exist.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

I like that one, unless someone screams, I will take ASAP.

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

Cheers,
Andre

> ---
>  arch/arm/dts/sunxi-u-boot.dtsi | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
> index 06da009fa2..4a6ed3a7dd 100644
> --- a/arch/arm/dts/sunxi-u-boot.dtsi
> +++ b/arch/arm/dts/sunxi-u-boot.dtsi
> @@ -64,7 +64,7 @@
>  					};
>  				};
>  
> -#ifndef CONFIG_MACH_SUN50I_H616
> +#ifdef SCP_ADDR
>  				scp {
>  					description = "SCP firmware";
>  					type = "firmware";
> @@ -92,7 +92,7 @@
>  				@config-SEQ {
>  					description = "NAME";
>  					firmware = "atf";
> -#ifdef CONFIG_MACH_SUN50I_H616
> +#ifndef SCP_ADDR
>  					loadables = "uboot";
>  #else
>  					loadables = "scp", "uboot";


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

* Re: [RFC PATCH 02/13] sunxi: only include alias for eMMC when mmc2 used
  2021-07-22  6:30 ` [RFC PATCH 02/13] sunxi: only include alias for eMMC when mmc2 used Icenowy Zheng
@ 2021-07-22 13:46   ` Andre Przywara
  0 siblings, 0 replies; 17+ messages in thread
From: Andre Przywara @ 2021-07-22 13:46 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Jagan Teki, Jernej Skrabec, Samuel Holland, u-boot, linux-sunxi

On Thu, 22 Jul 2021 14:30:04 +0800
Icenowy Zheng <icenowy@sipeed.com> wrote:

> Some Allwinner SoCs (e.g. R329) doesn't have a MMC2 controller at all,
> and on boards that we do not utilize MMC2, the alias for it is just
> useless.
> 
> Only include the alias when we specify CONFIG_MMC_SUNXI_EXTRA_SLOT to 2.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

Meh, not a friend of #ifdefs everywhere, but ideally we get rid of this
one day anyway, and it's in U-Boot DT "overlay" only, so:

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

Cheers,
Andre

> ---
>  arch/arm/dts/sunxi-u-boot.dtsi | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
> index 4a6ed3a7dd..b7244c1112 100644
> --- a/arch/arm/dts/sunxi-u-boot.dtsi
> +++ b/arch/arm/dts/sunxi-u-boot.dtsi
> @@ -13,7 +13,9 @@
>  / {
>  	aliases {
>  		mmc0 = &mmc0;
> +#if CONFIG_MMC_SUNXI_EXTRA_SLOT == 2
>  		mmc1 = &mmc2;
> +#endif
>  	};
>  
>  	binman: binman {


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

* Re: [RFC PATCH 03/13] mmc: sunxi: conditionally include MMC2 initialization code
  2021-07-22  6:30 ` [RFC PATCH 03/13] mmc: sunxi: conditionally include MMC2 initialization code Icenowy Zheng
@ 2021-07-22 13:48   ` Andre Przywara
  0 siblings, 0 replies; 17+ messages in thread
From: Andre Przywara @ 2021-07-22 13:48 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Jagan Teki, Jernej Skrabec, Samuel Holland, u-boot, linux-sunxi

On Thu, 22 Jul 2021 14:30:05 +0800
Icenowy Zheng <icenowy@sipeed.com> wrote:

Hi Icenowy,

> Allwinner R329 has no MMC2.
> 
> Only include the code of MMC2 if the base address of it is defined.
> 
> Signed-off-by: Icenowy Zheng <icenowy@sipeed.com>

One day (TM) we will hopefully get somehow rid of those #ifdefs
somehow, but until then it looks OK.

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

Thanks!
Andre

> ---
>  drivers/mmc/sunxi_mmc.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
> index 178b8cf106..6b809c001f 100644
> --- a/drivers/mmc/sunxi_mmc.c
> +++ b/drivers/mmc/sunxi_mmc.c
> @@ -73,10 +73,12 @@ static int mmc_resource_init(int sdc_no)
>  		priv->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE;
>  		priv->mclkreg = &ccm->sd1_clk_cfg;
>  		break;
> +#ifdef SUNXI_MMC2_BASE
>  	case 2:
>  		priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE;
>  		priv->mclkreg = &ccm->sd2_clk_cfg;
>  		break;
> +#endif
>  #ifdef SUNXI_MMC3_BASE
>  	case 3:
>  		priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE;


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

end of thread, other threads:[~2021-07-22 13:49 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-22  6:30 [RFC PATCH 00/13] Add support for Allwinner R329 Icenowy Zheng
2021-07-22  6:30 ` [RFC PATCH 01/13] sunxi: decide the inclusion of SCP by SCP_ADDR existence Icenowy Zheng
2021-07-22 13:35   ` Andre Przywara
2021-07-22  6:30 ` [RFC PATCH 02/13] sunxi: only include alias for eMMC when mmc2 used Icenowy Zheng
2021-07-22 13:46   ` Andre Przywara
2021-07-22  6:30 ` [RFC PATCH 03/13] mmc: sunxi: conditionally include MMC2 initialization code Icenowy Zheng
2021-07-22 13:48   ` Andre Przywara
2021-07-22  6:30 ` [RFC PATCH 04/13] sunxi: add memory addresses for R329 SoC Icenowy Zheng
2021-07-22  6:30 ` [RFC PATCH 05/13] sunxi: add support for R329 clocks Icenowy Zheng
2021-07-22  6:30 ` [RFC PATCH 06/13] sunxi: add support for basical pinmux setup on R329 Icenowy Zheng
2021-07-22  6:30 ` [RFC PATCH 07/13] sunxi: add support for R329 DRAM controller Icenowy Zheng
2021-07-22  6:30 ` [RFC PATCH 08/13] sunxi: add Kconfig option for R329 Icenowy Zheng
2021-07-22  6:30 ` [RFC PATCH 09/13] sunxi: sync R329 CCU binding headers from internal WIP kernel tree Icenowy Zheng
2021-07-22  6:30 ` [RFC PATCH 10/13] clk: sunxi: add support for R329 in sunxi DM clock driver Icenowy Zheng
2021-07-22  6:30 ` [RFC PATCH 11/13] mmc: sunxi: add support for R329 MMC controller Icenowy Zheng
2021-07-22  6:30 ` [RFC PATCH 12/13] sunxi: sync R329 DTs from internal WIP kernel tree Icenowy Zheng
2021-07-22  6:30 ` [RFC PATCH 13/13] sunxi: add support for Sipeed Maix IIA Dock board Icenowy Zheng

This is a public inbox, see mirroring instructions
on how to clone and mirror all data and code used for this inbox