From f61aefc150a30347db2d8aa2427b57d1c78e4357 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 17 May 2016 15:00:30 +0200 Subject: [PATCH] arm64: mvebu: Add support for the Marvell Armada 3700 SoC The Armada 3700 integrates the following interfaces (not complete list): - Dual Cortex-A53 ARMv8 - USB 3.0 - SATA 3.0 - PCIe 2.0 - 2 x Gigabit Ethernet 1Gbps / 2.5Gbps - ... This patch adds basic support for this ARMv8 based SoC into U-Boot. Future patches will integrate other device drivers and board support for the Marvell DB-88F3720 development board. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot --- arch/arm/Kconfig | 6 - arch/arm/mach-mvebu/Kconfig | 25 +++- arch/arm/mach-mvebu/Makefile | 15 +- arch/arm/mach-mvebu/armada3700/Makefile | 8 + arch/arm/mach-mvebu/armada3700/cpu.c | 188 ++++++++++++++++++++++++ arch/arm/mach-mvebu/armada3700/sata.c | 45 ++++++ arch/arm/mach-mvebu/include/mach/cpu.h | 7 + arch/arm/mach-mvebu/include/mach/soc.h | 2 +- 8 files changed, 284 insertions(+), 12 deletions(-) create mode 100644 arch/arm/mach-mvebu/armada3700/Makefile create mode 100644 arch/arm/mach-mvebu/armada3700/cpu.c create mode 100644 arch/arm/mach-mvebu/armada3700/sata.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 38ad59058f..9ae442e781 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -165,8 +165,6 @@ config KIRKWOOD config ARCH_MVEBU bool "Marvell MVEBU family (Armada XP/375/38x)" - select CPU_V7 - select SUPPORT_SPL select OF_CONTROL select OF_SEPARATE select DM @@ -174,10 +172,6 @@ config ARCH_MVEBU select DM_SERIAL select DM_SPI select DM_SPI_FLASH - select SPL_DM - select SPL_DM_SEQ_ALIAS - select SPL_OF_CONTROL - select SPL_SIMPLE_BUS config TARGET_DEVKIT3250 bool "Support devkit3250" diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 0fd71a717a..f169fc5b70 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -1,14 +1,37 @@ if ARCH_MVEBU +config ARMADA_32BIT + bool + select CPU_V7 + select SUPPORT_SPL + select SPL_DM + select SPL_DM_SEQ_ALIAS + select SPL_OF_CONTROL + select SPL_SIMPLE_BUS + +config ARMADA_64BIT + bool + select ARM64 + +# ARMv7 SoCs... config ARMADA_375 bool + select ARMADA_32BIT config ARMADA_38X bool + select ARMADA_32BIT config ARMADA_XP bool + select ARMADA_32BIT + +# ARMv8 SoCs... +config ARMADA_3700 + bool + select ARM64 +# Armada XP/38x SoC types... config MV78230 bool select ARMADA_XP @@ -26,7 +49,7 @@ config 88F6820 select ARMADA_38X choice - prompt "Marvell MVEBU (Armada XP/375/38x) board select" + prompt "Marvell MVEBU (Armada XP/375/38x/3700) board select" optional config TARGET_CLEARFOG diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index ac009a36da..07dc16c817 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -1,16 +1,22 @@ # -# Copyright (C) 2014-2015 Stefan Roese +# Copyright (C) 2014-2016 Stefan Roese # # SPDX-License-Identifier: GPL-2.0+ # +ifdef CONFIG_ARM64 + +obj-$(CONFIG_ARMADA_3700) += armada3700/ + +else # CONFIG_ARM64 + ifdef CONFIG_KIRKWOOD obj-y = dram.o obj-y += gpio.o obj-y += timer.o -else +else # CONFIG_KIRKWOOD obj-y = cpu.o obj-y += dram.o @@ -18,7 +24,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o -endif +endif # CONFIG_SPL_BUILD obj-y += gpio.o obj-y += mbus.o obj-y += timer.o @@ -28,4 +34,5 @@ obj-$(CONFIG_SPL_BUILD) += lowlevel_spl.o obj-$(CONFIG_ARMADA_38X) += serdes/a38x/ obj-$(CONFIG_ARMADA_XP) += serdes/axp/ -endif +endif # CONFIG_KIRKWOOD +endif # CONFIG_ARM64 diff --git a/arch/arm/mach-mvebu/armada3700/Makefile b/arch/arm/mach-mvebu/armada3700/Makefile new file mode 100644 index 0000000000..b1fac578a0 --- /dev/null +++ b/arch/arm/mach-mvebu/armada3700/Makefile @@ -0,0 +1,8 @@ +# +# Copyright (C) 2016 Stefan Roese +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o +obj-y += sata.o diff --git a/arch/arm/mach-mvebu/armada3700/cpu.c b/arch/arm/mach-mvebu/armada3700/cpu.c new file mode 100644 index 0000000000..7d8f7b8686 --- /dev/null +++ b/arch/arm/mach-mvebu/armada3700/cpu.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2016 Stefan Roese + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* Armada 3700 */ +#define MVEBU_GPIO_NB_REG_BASE (MVEBU_REGISTER(0x13800)) + +#define MVEBU_TEST_PIN_LATCH_N (MVEBU_GPIO_NB_REG_BASE + 0x8) +#define MVEBU_XTAL_MODE_MASK BIT(9) +#define MVEBU_XTAL_MODE_OFFS 9 +#define MVEBU_XTAL_CLOCK_25MHZ 0x0 +#define MVEBU_XTAL_CLOCK_40MHZ 0x1 + +#define MVEBU_NB_WARM_RST_REG (MVEBU_GPIO_NB_REG_BASE + 0x40) +#define MVEBU_NB_WARM_RST_MAGIC_NUM 0x1d1e + +static struct mm_region mvebu_mem_map[] = { + { + /* RAM */ + .phys = 0x0UL, + .virt = 0x0UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, + { + /* SRAM, MMIO regions */ + .phys = 0xd0000000UL, + .virt = 0xd0000000UL, + .size = 0x02000000UL, /* 32MiB internal registers */ + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE + }, + { + /* List terminator */ + 0, + } +}; + +struct mm_region *mem_map = mvebu_mem_map; + +/* + * On ARMv8, MBus is not configured in U-Boot. To enable compilation + * of the already implemented drivers, lets add a dummy version of + * this function so that linking does not fail. + */ +const struct mbus_dram_target_info *mvebu_mbus_dram_info(void) +{ + return NULL; +} + +void reset_cpu(ulong ignored) +{ + /* + * Write magic number of 0x1d1e to North Bridge Warm Reset register + * to trigger warm reset + */ + writel(MVEBU_NB_WARM_RST_MAGIC_NUM, MVEBU_NB_WARM_RST_REG); +} + +/* + * get_ref_clk + * + * return: reference clock in MHz (25 or 40) + */ +u32 get_ref_clk(void) +{ + u32 regval; + + regval = (readl(MVEBU_TEST_PIN_LATCH_N) & MVEBU_XTAL_MODE_MASK) >> + MVEBU_XTAL_MODE_OFFS; + + if (regval == MVEBU_XTAL_CLOCK_25MHZ) + return 25; + else + return 40; +} + +/* DRAM init code ... */ + +static const void *get_memory_reg_prop(const void *fdt, int *lenp) +{ + int offset; + + offset = fdt_path_offset(fdt, "/memory"); + if (offset < 0) + return NULL; + + return fdt_getprop(fdt, offset, "reg", lenp); +} + +int dram_init(void) +{ + const void *fdt = gd->fdt_blob; + const fdt32_t *val; + int ac, sc, len; + + ac = fdt_address_cells(fdt, 0); + sc = fdt_size_cells(fdt, 0); + if (ac < 0 || sc < 1 || sc > 2) { + printf("invalid address/size cells\n"); + return -EINVAL; + } + + val = get_memory_reg_prop(fdt, &len); + if (len / sizeof(*val) < ac + sc) + return -EINVAL; + + val += ac; + + gd->ram_size = fdtdec_get_number(val, sc); + + debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size); + + return 0; +} + +void dram_init_banksize(void) +{ + const void *fdt = gd->fdt_blob; + const fdt32_t *val; + int ac, sc, cells, len, i; + + val = get_memory_reg_prop(fdt, &len); + if (len < 0) + return; + + ac = fdt_address_cells(fdt, 0); + sc = fdt_size_cells(fdt, 0); + if (ac < 1 || sc > 2 || sc < 1 || sc > 2) { + printf("invalid address/size cells\n"); + return; + } + + cells = ac + sc; + + len /= sizeof(*val); + + for (i = 0; i < CONFIG_NR_DRAM_BANKS && len >= cells; + i++, len -= cells) { + gd->bd->bi_dram[i].start = fdtdec_get_number(val, ac); + val += ac; + gd->bd->bi_dram[i].size = fdtdec_get_number(val, sc); + val += sc; + + debug("DRAM bank %d: start = %08lx, size = %08lx\n", + i, (unsigned long)gd->bd->bi_dram[i].start, + (unsigned long)gd->bd->bi_dram[i].size); + } +} + +int arch_cpu_init(void) +{ + /* Nothing to do (yet) */ + return 0; +} + +int arch_early_init_r(void) +{ + struct udevice *dev; + int ret; + + /* Call the comphy code via the MISC uclass driver */ + ret = uclass_get_device(UCLASS_MISC, 0, &dev); + if (ret) { + debug("COMPHY init failed: %d\n", ret); + return -ENODEV; + } + + /* Cause the SATA device to do its early init */ + uclass_first_device(UCLASS_AHCI, &dev); + + return 0; +} diff --git a/arch/arm/mach-mvebu/armada3700/sata.c b/arch/arm/mach-mvebu/armada3700/sata.c new file mode 100644 index 0000000000..e0e8381fab --- /dev/null +++ b/arch/arm/mach-mvebu/armada3700/sata.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 Stefan Roese + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Dummy implementation that can be overwritten by a board + * specific function + */ +__weak int board_ahci_enable(void) +{ + return 0; +} + +static int mvebu_ahci_probe(struct udevice *dev) +{ + /* + * Board specific SATA / AHCI enable code, e.g. enable the + * AHCI power or deassert reset + */ + board_ahci_enable(); + + ahci_init(dev_get_addr_ptr(dev)); + + return 0; +} + +static const struct udevice_id mvebu_ahci_ids[] = { + { .compatible = "marvell,armada-3700-ahci" }, + { } +}; + +U_BOOT_DRIVER(ahci_mvebu_drv) = { + .name = "ahci_mvebu", + .id = UCLASS_AHCI, + .of_match = mvebu_ahci_ids, + .probe = mvebu_ahci_probe, +}; diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h index cbec876c42..66f7680fb3 100644 --- a/arch/arm/mach-mvebu/include/mach/cpu.h +++ b/arch/arm/mach-mvebu/include/mach/cpu.h @@ -166,5 +166,12 @@ struct mvebu_lcd_info { int mvebu_lcd_register_init(struct mvebu_lcd_info *lcd_info); +/* + * get_ref_clk + * + * return: reference clock in MHz (25 or 40) + */ +u32 get_ref_clk(void); + #endif /* __ASSEMBLY__ */ #endif /* _MVEBU_CPU_H */ diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h index 6342cdc35c..063d6ccabd 100644 --- a/arch/arm/mach-mvebu/include/mach/soc.h +++ b/arch/arm/mach-mvebu/include/mach/soc.h @@ -37,7 +37,7 @@ /* SOC specific definations */ #define INTREG_BASE 0xd0000000 #define INTREG_BASE_ADDR_REG (INTREG_BASE + 0x20080) -#if defined(CONFIG_SPL_BUILD) +#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_ARMADA_3700) /* * The SPL U-Boot version still runs with the default * address for the internal registers, configured by -- 2.39.2