sunxi: Add support for Allwinner A64 SoCs

The Allwinner A64 SoC is used in the Pine64. This patch adds
all bits necessary to compile U-Boot for it running in AArch64
mode.

Unfortunately SPL is not ready yet due to legal problems, so
we need to boot using the binary boot0 for now.

Signed-off-by: Siarhei Siamashka <siarhei.siamashka@gmail.com>
[agraf: remove SPL code, move to AArch64]
Signed-off-by: Alexander Graf <agraf@suse.de>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
index 5e72fac..464fa0f 100644
--- a/board/sunxi/Kconfig
+++ b/board/sunxi/Kconfig
@@ -77,6 +77,11 @@
 	select SUPPORT_SPL
 	select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
 
+config MACH_SUN50I
+	bool "sun50i (Allwinner A64)"
+	select ARM64
+	select SUNXI_GEN_SUN6I
+
 config MACH_SUN8I_A83T
 	bool "sun8i (Allwinner A83T)"
 	select CPU_V7
@@ -213,6 +218,7 @@
 endif
 
 config SYS_CLK_FREQ
+	default 816000000 if MACH_SUN50I
 	default 912000000 if MACH_SUN7I
 	default 1008000000 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN8I
 
@@ -223,6 +229,7 @@
 	default "sun7i" if MACH_SUN7I
 	default "sun8i" if MACH_SUN8I
 	default "sun9i" if MACH_SUN9I
+	default "sun50i" if MACH_SUN50I
 
 config SYS_BOARD
 	default "sunxi"
@@ -604,7 +611,7 @@
 	Set the GMAC Transmit Clock Delay Chain value.
 
 config SPL_STACK_R_ADDR
-	default 0x4fe00000 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN7I || MACH_SUN8I
+	default 0x4fe00000 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN7I || MACH_SUN8I || MACH_SUN50I
 	default 0x2fe00000 if MACH_SUN9I
 
 endif
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 2271c89..ccf4129 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -21,6 +21,9 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/usb_phy.h>
+#ifndef CONFIG_ARM64
+#include <asm/armv7.h>
+#endif
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <nand.h>
@@ -73,18 +76,38 @@
 /* add board specific code here */
 int board_init(void)
 {
-	int id_pfr1, ret;
+	__maybe_unused int id_pfr1, ret;
 
 	gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
 
+#ifndef CONFIG_ARM64
 	asm volatile("mrc p15, 0, %0, c0, c1, 1" : "=r"(id_pfr1));
 	debug("id_pfr1: 0x%08x\n", id_pfr1);
 	/* Generic Timer Extension available? */
-	if ((id_pfr1 >> 16) & 0xf) {
+	if ((id_pfr1 >> CPUID_ARM_GENTIMER_SHIFT) & 0xf) {
+		uint32_t freq;
+
 		debug("Setting CNTFRQ\n");
-		/* CNTFRQ == 24 MHz */
-		asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r"(24000000));
+
+		/*
+		 * CNTFRQ is a secure register, so we will crash if we try to
+		 * write this from the non-secure world (read is OK, though).
+		 * In case some bootcode has already set the correct value,
+		 * we avoid the risk of writing to it.
+		 */
+		asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r"(freq));
+		if (freq != CONFIG_TIMER_CLK_FREQ) {
+			debug("arch timer frequency is %d Hz, should be %d, fixing ...\n",
+			      freq, CONFIG_TIMER_CLK_FREQ);
+#ifdef CONFIG_NON_SECURE
+			printf("arch timer frequency is wrong, but cannot adjust it\n");
+#else
+			asm volatile("mcr p15, 0, %0, c14, c0, 0"
+				     : : "r"(CONFIG_TIMER_CLK_FREQ));
+#endif
+		}
 	}
+#endif /* !CONFIG_ARM64 */
 
 	ret = axp_gpio_init();
 	if (ret)
@@ -264,7 +287,7 @@
 			sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
 			sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
 		}
-#elif defined(CONFIG_MACH_SUN8I)
+#elif defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN50I)
 		/* SDC2: PC5-PC6, PC8-PC16 */
 		for (pin = SUNXI_GPC(5); pin <= SUNXI_GPC(6); pin++) {
 			sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
@@ -547,7 +570,7 @@
  */
 static void parse_spl_header(const uint32_t spl_addr)
 {
-	struct boot_file_head *spl = (void *)spl_addr;
+	struct boot_file_head *spl = (void *)(ulong)spl_addr;
 	if (memcmp(spl->spl_signature, SPL_SIGNATURE, 3) == 0) {
 		uint8_t spl_header_version = spl->spl_signature[3];
 		if (spl_header_version == SPL_HEADER_VERSION) {