From 4a84cf06aa05b10b31b876e6d6f43168945213af Mon Sep 17 00:00:00 2001 From: "Chia-Wei, Wang" Date: Mon, 14 Dec 2020 13:54:28 +0800 Subject: [PATCH] aspeed: Add AST2600 platform support Add low level platform initialization for the AST2600 SoC. The 2-stage booting with U-Boot SPL are leveraged to support different booting mode. However, currently the patch supports only the booting from memory-mapped SPI flash. Signed-off-by: Chia-Wei, Wang Reviewed-by: Ryan Chen --- arch/arm/include/asm/arch-aspeed/boot0.h | 23 ++ arch/arm/include/asm/arch-aspeed/platform.h | 5 + arch/arm/mach-aspeed/Kconfig | 20 ++ arch/arm/mach-aspeed/Makefile | 1 + arch/arm/mach-aspeed/ast2600/Kconfig | 17 ++ arch/arm/mach-aspeed/ast2600/Makefile | 2 + arch/arm/mach-aspeed/ast2600/board_common.c | 105 +++++++++ arch/arm/mach-aspeed/ast2600/lowlevel_init.S | 233 +++++++++++++++++++ arch/arm/mach-aspeed/ast2600/spl.c | 55 +++++ board/aspeed/evb_ast2600/Kconfig | 12 + board/aspeed/evb_ast2600/Makefile | 1 + board/aspeed/evb_ast2600/evb_ast2600.c | 5 + drivers/sysreset/sysreset_ast.c | 5 + include/configs/evb_ast2600.h | 16 ++ 14 files changed, 500 insertions(+) create mode 100644 arch/arm/include/asm/arch-aspeed/boot0.h create mode 100644 arch/arm/mach-aspeed/ast2600/Kconfig create mode 100644 arch/arm/mach-aspeed/ast2600/Makefile create mode 100644 arch/arm/mach-aspeed/ast2600/board_common.c create mode 100644 arch/arm/mach-aspeed/ast2600/lowlevel_init.S create mode 100644 arch/arm/mach-aspeed/ast2600/spl.c create mode 100644 board/aspeed/evb_ast2600/Kconfig create mode 100644 board/aspeed/evb_ast2600/Makefile create mode 100644 board/aspeed/evb_ast2600/evb_ast2600.c create mode 100644 include/configs/evb_ast2600.h diff --git a/arch/arm/include/asm/arch-aspeed/boot0.h b/arch/arm/include/asm/arch-aspeed/boot0.h new file mode 100644 index 0000000000..368becc87a --- /dev/null +++ b/arch/arm/include/asm/arch-aspeed/boot0.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) Aspeed Technology Inc. + */ + +#ifndef _ASM_ARCH_BOOT0_H +#define _ASM_ARCH_BOOT0_H + +_start: + ARM_VECTORS + + .word 0x0 /* key location */ + .word 0x0 /* start address of image */ + .word 0xfc00 /* maximum image size: 63KB */ + .word 0x0 /* signature address */ + .word 0x0 /* header revision ID low */ + .word 0x0 /* header revision ID high */ + .word 0x0 /* reserved */ + .word 0x0 /* checksum */ + .word 0x0 /* BL2 secure header */ + .word 0x0 /* public key or digest offset for BL2 */ + +#endif diff --git a/arch/arm/include/asm/arch-aspeed/platform.h b/arch/arm/include/asm/arch-aspeed/platform.h index 6cee036f54..d50ec5f8a9 100644 --- a/arch/arm/include/asm/arch-aspeed/platform.h +++ b/arch/arm/include/asm/arch-aspeed/platform.h @@ -13,6 +13,11 @@ #define ASPEED_DRAM_BASE 0x80000000 #define ASPEED_SRAM_BASE 0x1e720000 #define ASPEED_SRAM_SIZE 0x9000 +#elif defined(CONFIG_ASPEED_AST2600) +#define ASPEED_MAC_COUNT 4 +#define ASPEED_DRAM_BASE 0x80000000 +#define ASPEED_SRAM_BASE 0x10000000 +#define ASPEED_SRAM_SIZE 0x10000 #else #err "Unrecognized Aspeed platform." #endif diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig index 4f021baa06..9a725f195a 100644 --- a/arch/arm/mach-aspeed/Kconfig +++ b/arch/arm/mach-aspeed/Kconfig @@ -9,6 +9,11 @@ config SYS_SOC config SYS_TEXT_BASE default 0x00000000 +choice + prompt "Aspeed SoC select" + depends on ARCH_ASPEED + default ASPEED_AST2500 + config ASPEED_AST2500 bool "Support Aspeed AST2500 SoC" depends on DM_RESET @@ -18,6 +23,21 @@ config ASPEED_AST2500 It is used as Board Management Controller on many server boards, which is enabled by support of LPC and eSPI peripherals. +config ASPEED_AST2600 + bool "Support Aspeed AST2600 SoC" + select CPU_V7A + select CPU_V7_HAS_NONSEC + select SYS_ARCH_TIMER + select SUPPORT_SPL + select ENABLE_ARM_SOC_BOOT0_HOOK + help + The Aspeed AST2600 is a ARM-based SoC with Cortex-A7 CPU. + It is used as Board Management Controller on many server boards, + which is enabled by support of LPC and eSPI peripherals. + +endchoice + source "arch/arm/mach-aspeed/ast2500/Kconfig" +source "arch/arm/mach-aspeed/ast2600/Kconfig" endif diff --git a/arch/arm/mach-aspeed/Makefile b/arch/arm/mach-aspeed/Makefile index 33f65b50b2..42599c125b 100644 --- a/arch/arm/mach-aspeed/Makefile +++ b/arch/arm/mach-aspeed/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_ARCH_ASPEED) += ast_wdt.o obj-$(CONFIG_ASPEED_AST2500) += ast2500/ +obj-$(CONFIG_ASPEED_AST2600) += ast2600/ diff --git a/arch/arm/mach-aspeed/ast2600/Kconfig b/arch/arm/mach-aspeed/ast2600/Kconfig new file mode 100644 index 0000000000..f3a53387a1 --- /dev/null +++ b/arch/arm/mach-aspeed/ast2600/Kconfig @@ -0,0 +1,17 @@ +if ASPEED_AST2600 + +config SYS_CPU + default "armv7" + +config TARGET_EVB_AST2600 + bool "EVB-AST2600" + depends on ASPEED_AST2600 + help + EVB-AST2600 is Aspeed evaluation board for AST2600A0 chip. + It has 512M of RAM, 32M of SPI flash, two Ethernet ports, + 4 Serial ports, 4 USB ports, VGA port, PCIe, SD card slot, + 20 pin JTAG, pinouts for 14 I2Cs, 3 SPIs and eSPI, 8 PWMs. + +source "board/aspeed/evb_ast2600/Kconfig" + +endif diff --git a/arch/arm/mach-aspeed/ast2600/Makefile b/arch/arm/mach-aspeed/ast2600/Makefile new file mode 100644 index 0000000000..448d3201af --- /dev/null +++ b/arch/arm/mach-aspeed/ast2600/Makefile @@ -0,0 +1,2 @@ +obj-y += lowlevel_init.o board_common.o +obj-$(CONFIG_SPL_BUILD) += spl.o diff --git a/arch/arm/mach-aspeed/ast2600/board_common.c b/arch/arm/mach-aspeed/ast2600/board_common.c new file mode 100644 index 0000000000..a53e1632f6 --- /dev/null +++ b/arch/arm/mach-aspeed/ast2600/board_common.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) Aspeed Technology Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* Memory Control registers */ +#define MCR_BASE 0x1e6e0000 +#define MCR_CONF (MCR_BASE + 0x004) + +/* bit fields of MCR_CONF */ +#define MCR_CONF_ECC_EN BIT(7) +#define MCR_CONF_VGA_MEMSZ_MASK GENMASK(3, 2) +#define MCR_CONF_VGA_MEMSZ_SHIFT 2 +#define MCR_CONF_MEMSZ_MASK GENMASK(1, 0) +#define MCR_CONF_MEMSZ_SHIFT 0 + +int dram_init(void) +{ + int ret; + struct udevice *dev; + struct ram_info ram; + + ret = uclass_get_device(UCLASS_RAM, 0, &dev); + if (ret) { + debug("cannot get DRAM driver\n"); + return ret; + } + + ret = ram_get_info(dev, &ram); + if (ret) { + debug("cannot get DRAM information\n"); + return ret; + } + + gd->ram_size = ram.size; + return 0; +} + +int board_init(void) +{ + int i = 0, rc; + struct udevice *dev; + + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + + while (1) { + rc = uclass_get_device(UCLASS_MISC, i++, &dev); + if (rc) + break; + } + + return 0; +} + +void board_add_ram_info(int use_default) +{ + int rc; + uint32_t conf; + uint32_t ecc, act_size, vga_rsvd; + struct udevice *scu_dev; + struct ast2600_scu *scu; + + rc = uclass_get_device_by_driver(UCLASS_CLK, + DM_DRIVER_GET(aspeed_ast2600_scu), &scu_dev); + if (rc) { + debug("%s: cannot find SCU device, rc=%d\n", __func__, rc); + return; + } + + scu = devfdt_get_addr_ptr(scu_dev); + if (IS_ERR_OR_NULL(scu)) { + debug("%s: cannot get SCU address pointer\n", __func__); + return; + } + + conf = readl(MCR_CONF); + + ecc = conf & MCR_CONF_ECC_EN; + act_size = 0x100 << ((conf & MCR_CONF_MEMSZ_MASK) >> MCR_CONF_MEMSZ_SHIFT); + vga_rsvd = 0x8 << ((conf & MCR_CONF_VGA_MEMSZ_MASK) >> MCR_CONF_VGA_MEMSZ_SHIFT); + + /* no VGA reservation if efuse VGA disable bit is set */ + if (readl(scu->efuse) & SCU_EFUSE_DIS_VGA) + vga_rsvd = 0; + + printf(" (capacity:%d MiB, VGA:%d MiB), ECC %s", act_size, + vga_rsvd, (ecc) ? "on" : "off"); +} + +void enable_caches(void) +{ + /* get rid of the warning message */ +} diff --git a/arch/arm/mach-aspeed/ast2600/lowlevel_init.S b/arch/arm/mach-aspeed/ast2600/lowlevel_init.S new file mode 100644 index 0000000000..594963d039 --- /dev/null +++ b/arch/arm/mach-aspeed/ast2600/lowlevel_init.S @@ -0,0 +1,233 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) ASPEED Technology Inc. + */ +#include +#include +#include +#include + +/* SCU register offsets */ +#define SCU_BASE 0x1e6e2000 +#define SCU_PROT_KEY1 (SCU_BASE + 0x000) +#define SCU_PROT_KEY2 (SCU_BASE + 0x010) +#define SCU_SMP_BOOT (SCU_BASE + 0x180) +#define SCU_HWSTRAP1 (SCU_BASE + 0x510) +#define SCU_CA7_PARITY_CHK (SCU_BASE + 0x820) +#define SCU_CA7_PARITY_CLR (SCU_BASE + 0x824) +#define SCU_MMIO_DEC (SCU_BASE + 0xc24) + +/* FMC SPI register offsets */ +#define FMC_BASE 0x1e620000 +#define FMC_CE0_CTRL (FMC_BASE + 0x010) +#define FMC_SW_RST_CTRL (FMC_BASE + 0x050) +#define FMC_WDT1_CTRL_MODE (FMC_BASE + 0x060) +#define FMC_WDT2_CTRL_MODE (FMC_BASE + 0x064) + +/* + * The SMP mailbox provides a space with few instructions in it + * for secondary cores to execute on and wait for the signal of + * SMP core bring up. + * + * SMP mailbox + * +----------------------+ + * | | + * | mailbox insn. for | + * | cpuN polling SMP go | + * | | + * +----------------------+ 0xC + * | mailbox ready signal | + * +----------------------+ 0x8 + * | cpuN GO signal | + * +----------------------+ 0x4 + * | cpuN entrypoint | + * +----------------------+ SMP_MAILBOX_BASE + */ +#define SMP_MBOX_BASE (SCU_SMP_BOOT) +#define SMP_MBOX_FIELD_ENTRY (SMP_MBOX_BASE + 0x0) +#define SMP_MBOX_FIELD_GOSIGN (SMP_MBOX_BASE + 0x4) +#define SMP_MBOX_FIELD_READY (SMP_MBOX_BASE + 0x8) +#define SMP_MBOX_FIELD_POLLINSN (SMP_MBOX_BASE + 0xc) + +.macro scu_unlock + movw r0, #(SCU_UNLOCK_KEY & 0xffff) + movt r0, #(SCU_UNLOCK_KEY >> 16) + + ldr r1, =SCU_PROT_KEY1 + str r0, [r1] + ldr r1, =SCU_PROT_KEY2 + str r0, [r1] +.endm + +.macro timer_init + ldr r1, =SCU_HWSTRAP1 + ldr r1, [r1] + and r1, #0x700 + lsr r1, #0x8 + + /* 1.2GHz */ + cmp r1, #0x0 + movweq r0, #0x8c00 + movteq r0, #0x4786 + + /* 1.6GHz */ + cmp r1, #0x1 + movweq r0, #0x1000 + movteq r0, #0x5f5e + + /* 1.2GHz */ + cmp r1, #0x2 + movweq r0, #0x8c00 + movteq r0, #0x4786 + + /* 1.6GHz */ + cmp r1, #0x3 + movweq r0, #0x1000 + movteq r0, #0x5f5e + + /* 800MHz */ + cmp r1, #0x4 + movwge r0, #0x0800 + movtge r0, #0x2faf + + mcr p15, 0, r0, c14, c0, 0 @; update CNTFRQ +.endm + + +.globl lowlevel_init + +lowlevel_init: +#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD) + mov pc, lr +#else + /* setup ARM arch timer frequency */ + timer_init + + /* reset SMP mailbox as early as possible */ + mov r0, #0x0 + ldr r1, =SMP_MBOX_FIELD_READY + str r0, [r1] + + /* set ACTLR.SMP to enable cache use */ + mrc p15, 0, r0, c1, c0, 1 + orr r0, #0x40 + mcr p15, 0, r0, c1, c0, 1 + + /* + * we treat cpu0 as the primary core and + * put secondary core (cpuN) to sleep + */ + mrc p15, 0, r0, c0, c0, 5 @; Read CPU ID register + ands r0, #0xff @; Mask off, leaving the CPU ID field + movw r2, #0xab00 + movt r2, #0xabba + orr r2, r0 + + beq do_primary_core_setup + + /* hold cpuN until mailbox is ready */ +poll_mailbox_ready: + wfe + ldr r0, =SMP_MBOX_FIELD_READY + ldr r0, [r0] + movw r1, #0xcafe + movt r1, #0xbabe + cmp r1, r0 + bne poll_mailbox_ready + + /* parameters for relocated SMP go polling insn. */ + ldr r0, =SMP_MBOX_FIELD_GOSIGN + ldr r1, =SMP_MBOX_FIELD_ENTRY + + /* no return */ + ldr pc, =SMP_MBOX_FIELD_POLLINSN + +do_primary_core_setup: + scu_unlock + + /* MMIO decode setting */ + ldr r0, =SCU_MMIO_DEC + mov r1, #0x2000 + str r1, [r0] + + /* enable CA7 cache parity check */ + mov r0, #0 + ldr r1, =SCU_CA7_PARITY_CLR + str r0, [r1] + + mov r0, #0x1 + ldr r1, =SCU_CA7_PARITY_CHK + str r0, [r1] + + /* do not fill FMC50[1] if boot from eMMC */ + ldr r0, =SCU_HWSTRAP1 + ldr r1, [r0] + ands r1, #0x04 + bne skip_fill_wip_bit + + /* fill FMC50[1] for waiting WIP idle */ + mov r0, #0x02 + ldr r1, =FMC_SW_RST_CTRL + str r0, [r1] + +skip_fill_wip_bit: + /* disable FMC WDT for SPI address mode detection */ + mov r0, #0 + ldr r1, =FMC_WDT1_CTRL_MODE + str r0, [r1] + + /* relocate mailbox insn. for cpuN polling SMP go signal */ + adrl r0, mailbox_insn + adrl r1, mailbox_insn_end + + ldr r2, =#SMP_MBOX_FIELD_POLLINSN + +relocate_mailbox_insn: + ldr r3, [r0], #0x4 + str r3, [r2], #0x4 + cmp r0, r1 + bne relocate_mailbox_insn + + /* reset SMP go sign */ + mov r0, #0 + ldr r1, =SMP_MBOX_FIELD_GOSIGN + str r0, [r1] + + /* notify cpuN mailbox is ready */ + movw r0, #0xCAFE + movt r0, #0xBABE + ldr r1, =SMP_MBOX_FIELD_READY + str r0, [r1] + sev + + /* back to arch calling code */ + mov pc, lr + +/* + * insn. inside mailbox to poll SMP go signal. + * + * Note that as this code will be relocated, any + * pc-relative assembly should NOT be used. + */ +mailbox_insn: + /* + * r0 ~ r3 are parameters: + * r0 = SMP_MBOX_FIELD_GOSIGN + * r1 = SMP_MBOX_FIELD_ENTRY + * r2 = per-cpu go sign value + * r3 = no used now + */ +poll_mailbox_smp_go: + wfe + ldr r4, [r0] + cmp r2, r4 + bne poll_mailbox_smp_go + + /* SMP GO signal confirmed, release cpuN */ + ldr pc, [r1] + +mailbox_insn_end: + /* should never reach */ + b . + +#endif diff --git a/arch/arm/mach-aspeed/ast2600/spl.c b/arch/arm/mach-aspeed/ast2600/spl.c new file mode 100644 index 0000000000..9201d4a4d4 --- /dev/null +++ b/arch/arm/mach-aspeed/ast2600/spl.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) Aspeed Technology Inc. + */ +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +void board_init_f(ulong dummy) +{ + spl_early_init(); + preloader_console_init(); + timer_init(); + dram_init(); +} + +u32 spl_boot_device(void) +{ + return BOOT_DEVICE_RAM; +} + +struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +{ + /* + * When boot from SPI, AST2600 already remap 0x00000000 ~ 0x0fffffff + * to BMC SPI memory space 0x20000000 ~ 0x2fffffff. The next stage BL + * has been located in SPI for XIP. In this case, the load buffer for + * SPL image loading will be set to the remapped address of the next + * BL instead of the DRAM space CONFIG_SYS_LOAD_ADDR + */ + return (struct image_header *)(CONFIG_SYS_TEXT_BASE); +} + +#ifdef CONFIG_SPL_OS_BOOT +int spl_start_uboot(void) +{ + /* boot linux */ + return 0; +} +#endif + +#ifdef CONFIG_SPL_LOAD_FIT +int board_fit_config_name_match(const char *name) +{ + /* just empty function now - can't decide what to choose */ + debug("%s: %s\n", __func__, name); + return 0; +} +#endif diff --git a/board/aspeed/evb_ast2600/Kconfig b/board/aspeed/evb_ast2600/Kconfig new file mode 100644 index 0000000000..42008cd033 --- /dev/null +++ b/board/aspeed/evb_ast2600/Kconfig @@ -0,0 +1,12 @@ +if TARGET_EVB_AST2600 + +config SYS_BOARD + default "evb_ast2600" + +config SYS_VENDOR + default "aspeed" + +config SYS_CONFIG_NAME + default "evb_ast2600" + +endif diff --git a/board/aspeed/evb_ast2600/Makefile b/board/aspeed/evb_ast2600/Makefile new file mode 100644 index 0000000000..9291db6ee1 --- /dev/null +++ b/board/aspeed/evb_ast2600/Makefile @@ -0,0 +1 @@ +obj-y += evb_ast2600.o diff --git a/board/aspeed/evb_ast2600/evb_ast2600.c b/board/aspeed/evb_ast2600/evb_ast2600.c new file mode 100644 index 0000000000..e6dc8c7952 --- /dev/null +++ b/board/aspeed/evb_ast2600/evb_ast2600.c @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) Aspeed Technology Inc. + */ +#include diff --git a/drivers/sysreset/sysreset_ast.c b/drivers/sysreset/sysreset_ast.c index ee941c7770..d747ed00a7 100644 --- a/drivers/sysreset/sysreset_ast.c +++ b/drivers/sysreset/sysreset_ast.c @@ -12,6 +12,7 @@ #include #include #include +#include static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type) { @@ -33,11 +34,15 @@ static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type) return -EPROTONOSUPPORT; } +#if !defined(CONFIG_SPL_BUILD) ret = wdt_expire_now(wdt, reset_mode); if (ret) { debug("Sysreset failed: %d", ret); return ret; } +#else + hang(); +#endif return -EINPROGRESS; } diff --git a/include/configs/evb_ast2600.h b/include/configs/evb_ast2600.h new file mode 100644 index 0000000000..e7975bf66d --- /dev/null +++ b/include/configs/evb_ast2600.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) Aspeed Technology Inc. + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include + +#define CONFIG_SYS_UBOOT_BASE CONFIG_SYS_TEXT_BASE + +/* Memory Info */ +#define CONFIG_SYS_LOAD_ADDR 0x83000000 + +#endif /* __CONFIG_H */