sunxi: add R528/T113-s3/D1(s) DRAM initialisation code

The Allwinner R528/T113-s/D1/D1s SoCs all share the same die, so use the
same DRAM initialisation code.
Make use of prior art here and lift some code from awboot[1], which
carried init code based on earlier decompilation efforts, but with a
GPL2 license tag.
This code has been heavily reworked and cleaned up, to match previous
DRAM routines for other SoCs, and also to be closer to U-Boot's coding
style and support routines.
The actual DRAM chip timing parameters are included in the main file,
since they cover all DRAM types, and are protected by a new Kconfig
CONFIG_SUNXI_DRAM_TYPE symbol, which allows the compiler to pick only
the relevant settings, at build time.

The relevant DRAM chips/board specific configuration parameters are
delivered via Kconfig, so this code here should work for all supported
SoCs and DRAM chips combinations.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Tested-by: Sam Edwards <CFSworks@gmail.com>
diff --git a/drivers/ram/sunxi/dram_sun20i_d1.h b/drivers/ram/sunxi/dram_sun20i_d1.h
new file mode 100644
index 0000000..91383f6
--- /dev/null
+++ b/drivers/ram/sunxi/dram_sun20i_d1.h
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier:	GPL-2.0+
+/*
+ * D1/R528/T113 DRAM controller register and constant defines
+ *
+ * (C) Copyright 2022 Arm Ltd.
+ * Based on H6 and H616 header, which are:
+ * (C) Copyright 2017  Icenowy Zheng <icenowy@aosc.io>
+ * (C) Copyright 2020  Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ */
+
+#ifndef _SUNXI_DRAM_SUN20I_D1_H
+#define _SUNXI_DRAM_SUN20I_D1_H
+
+enum sunxi_dram_type {
+	SUNXI_DRAM_TYPE_DDR2 = 2,
+	SUNXI_DRAM_TYPE_DDR3 = 3,
+	SUNXI_DRAM_TYPE_LPDDR2 = 6,
+	SUNXI_DRAM_TYPE_LPDDR3 = 7,
+};
+
+/*
+ * This structure contains a mixture of fixed configuration settings,
+ * variables that are used at runtime to communicate settings between
+ * different stages and functions, and unused values.
+ * This is copied from Allwinner's boot0 data structure, which can be
+ * found at offset 0x38 in any boot0 binary. To allow matching up some
+ * board specific settings, this struct is kept compatible, even though
+ * we don't need all members in our code.
+ */
+typedef struct dram_para {
+	/* normal configuration */
+	const u32	dram_clk;
+	const u32	dram_type;
+	const u32	dram_zq;
+	const u32	dram_odt_en;
+
+	/* timing configuration */
+	const u32	dram_mr0;
+	const u32	dram_mr1;
+	const u32	dram_mr2;
+	const u32	dram_mr3;
+	const u32	dram_tpr0;	//DRAMTMG0
+	const u32	dram_tpr1;	//DRAMTMG1
+	const u32	dram_tpr2;	//DRAMTMG2
+	const u32	dram_tpr3;	//DRAMTMG3
+	const u32	dram_tpr4;	//DRAMTMG4
+	const u32	dram_tpr5;	//DRAMTMG5
+	const u32	dram_tpr6;	//DRAMTMG8
+	const u32	dram_tpr7;
+	const u32	dram_tpr8;
+	const u32	dram_tpr9;
+	const u32	dram_tpr10;
+	const u32	dram_tpr11;
+	const u32	dram_tpr12;
+} dram_para_t;
+
+typedef struct dram_config {
+	/* control configuration */
+	u32	dram_para1;
+	u32	dram_para2;
+	/* contains a bitfield of DRAM setup settings */
+	u32	dram_tpr13;
+} dram_config_t;
+
+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);
+}
+
+#endif /* _SUNXI_DRAM_SUN20I_D1_H */