diff options
author | Chris Packham <judge.packham@gmail.com> | 2022-11-05 17:23:59 +1300 |
---|---|---|
committer | Stefan Roese <sr@denx.de> | 2022-11-07 07:46:28 +0100 |
commit | 7d7bb99e22783cfee4ecd078d054fcc4cd2948cb (patch) | |
tree | 7cf1934719c2f4ccde0c9596f18e8064947afd75 /arch/arm/mach-mvebu/alleycat5 | |
parent | c2499382146664e19b95292888158d9c844f4032 (diff) |
arm: mvebu: Support for 98DX25xx/98DX35xx SoC
Add support for the Allecat5/Alleycat5X SoC. These are L3 switches with
an integrated CPU (referred to as the CnM block in Marvell's
documentation). These have dual ARMv8.2 CPUs (Cortex-A55). This support
has been ported from Marvell's SDK which is based on a much older
version of U-Boot.
Signed-off-by: Chris Packham <judge.packham@gmail.com>
Diffstat (limited to 'arch/arm/mach-mvebu/alleycat5')
-rw-r--r-- | arch/arm/mach-mvebu/alleycat5/Makefile | 8 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/alleycat5/cpu.c | 124 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/alleycat5/soc.c | 298 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/alleycat5/soc.h | 7 |
4 files changed, 437 insertions, 0 deletions
diff --git a/arch/arm/mach-mvebu/alleycat5/Makefile b/arch/arm/mach-mvebu/alleycat5/Makefile new file mode 100644 index 0000000000..b897ad089a --- /dev/null +++ b/arch/arm/mach-mvebu/alleycat5/Makefile @@ -0,0 +1,8 @@ +# +# Copyright (C) 2016 Stefan Roese <sr@denx.de> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o +obj-y += soc.o diff --git a/arch/arm/mach-mvebu/alleycat5/cpu.c b/arch/arm/mach-mvebu/alleycat5/cpu.c new file mode 100644 index 0000000000..cc7f9794c5 --- /dev/null +++ b/arch/arm/mach-mvebu/alleycat5/cpu.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Marvell International Ltd. + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <linux/libfdt.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/arch/cpu.h> +#include <linux/sizes.h> +#include <asm/armv8/mmu.h> +#include "soc.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define RAM_SIZE SZ_1G + +static struct mm_region ac5_mem_map[] = { + { + /* RAM */ + .phys = CONFIG_SYS_SDRAM_BASE, + .virt = CONFIG_SYS_SDRAM_BASE, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, + { + /* MMIO regions */ + .phys = 0x00000000, + .virt = 0xa0000000, + .size = 0x100000, + + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { + /* MMIO regions */ + .phys = 0x100000, + .virt = 0x100000, + .size = 0x3ff00000, + + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { + /* MMIO regions */ + .phys = 0x7F000000, + .virt = 0x7F000000, + .size = 0x21000000, + + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { + 0, + } +}; + +struct mm_region *mem_map = ac5_mem_map; + +void reset_cpu(void) +{ +} + +int print_cpuinfo(void) +{ + soc_print_device_info(); + soc_print_clock_info(); + + return 0; +} + +int alleycat5_dram_init(void) +{ +#define SCRATCH_PAD_REG 0x80010018 + int ret; + + /* override DDR_FW size if DTS is set with size */ + ret = fdtdec_setup_mem_size_base(); + if (ret == -EINVAL) + gd->ram_size = readl(SCRATCH_PAD_REG) * 4ULL; + + /* if DRAM size == 0, print error message */ + if (gd->ram_size == 0) { + pr_err("DRAM size not initialized - check DRAM configuration\n"); + printf("\n Using temporary DRAM size of 512MB.\n\n"); + gd->ram_size = SZ_512M; + } + + ac5_mem_map[0].size = gd->ram_size; + + return 0; +} + +int alleycat5_dram_init_banksize(void) +{ + /* + * Config single DRAM bank + */ + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + gd->bd->bi_dram[0].size = gd->ram_size; + + return 0; +} + +int timer_init(void) +{ + return 0; +} + +/* + * get_ref_clk + * + * return: reference clock in MHz + */ +u32 get_ref_clk(void) +{ + return 25; +} diff --git a/arch/arm/mach-mvebu/alleycat5/soc.c b/arch/arm/mach-mvebu/alleycat5/soc.c new file mode 100644 index 0000000000..efbef233a1 --- /dev/null +++ b/arch/arm/mach-mvebu/alleycat5/soc.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Marvell International Ltd. + */ + +#include <common.h> +#include <asm/arch-armada8k/cache_llc.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/soc.h> +#include <dm/device.h> + +#define DEVICE_ID_REG 0x7F90004C +#define DEVICE_ID_MASK 0xffff0 +#define REV_ID_MASK 0xf +#define DEVICE_ID_OFFSET 4 +#define REV_ID_OFFSET 0 + +#define DEVICE_SAR_REG 0x944F8204 + +#define DEVICE_ID_SUB_REV (MVEBU_REGISTER(0x2400230)) +#define DEVICE_ID_SUB_REV_OFFSET 7 +#define DEVICE_ID_SUB_REV_MASK (0xffff << DEVICE_ID_SUB_REV_OFFSET) + +#define AC5X_DEV_ID 0x9800 + +struct soc_info { + u32 dev_id; + u32 rev_id; + char *soc_name; +}; + +static struct soc_info soc_info_table[] = { + /* Two reserved entries for unidentified devices - don't change */ + { 0xB4FF, 0x0, "Unidentified Alleycat5"}, + { 0x98FF, 0x0, "Unidentified Alleycat5x"}, + + { 0xB400, 0x2, "Alleycat5-plus 98DX2538-A2"}, + { 0xB401, 0x2, "Alleycat5-plus 98DX2535-A2"}, + { 0xB402, 0x2, "Alleycat5-plus 98DX2532-A2"}, + { 0xB403, 0x2, "Alleycat5-plus 98DX2531-A2"}, + { 0xB408, 0x2, "Alleycat5 98DX2528-A2"}, + { 0xB409, 0x2, "Alleycat5 98DX2525-A2"}, + { 0xB40A, 0x2, "Alleycat5 98DX2522-A2"}, + { 0xB40B, 0x2, "Alleycat5 98DX2521-A2"}, + { 0xB410, 0x2, "Alleycat5-lite 98DX2518-A2"}, + { 0xB411, 0x2, "Alleycat5-lite 98DX2515-A2"}, + { 0xB412, 0x2, "Alleycat5-lite 98DX2512-A2"}, + { 0xB413, 0x2, "Alleycat5-lite 98DX2511-A2"}, + + { 0xB400, 0x1, "Alleycat5-plus 98DX2538-A1"}, + { 0xB401, 0x1, "Alleycat5-plus 98DX2535-A1"}, + { 0xB402, 0x1, "Alleycat5-plus 98DX2532-A1"}, + { 0xB403, 0x1, "Alleycat5-plus 98DX2531-A1"}, + { 0xB408, 0x1, "Alleycat5 98DX2528-A1"}, + { 0xB409, 0x1, "Alleycat5 98DX2525-A1"}, + { 0xB40A, 0x1, "Alleycat5 98DX2522-A1"}, + { 0xB40B, 0x1, "Alleycat5 98DX2521-A1"}, + { 0xB410, 0x1, "Alleycat5-lite 98DX2518-A1"}, + { 0xB411, 0x1, "Alleycat5-lite 98DX2515-A1"}, + { 0xB412, 0x1, "Alleycat5-lite 98DX2512-A1"}, + { 0xB413, 0x1, "Alleycat5-lite 98DX2511-A1"}, + { 0x9800, 0x1, "Alleycat5X 98DX3500M-A1"}, + { 0x9806, 0x1, "Alleycat5X 98DX3501M-A1"}, + { 0x9801, 0x1, "Alleycat5X 98DX3510M-A1"}, + { 0x9802, 0x1, "Alleycat5X 98DX3520M-A1"}, + { 0x9803, 0x1, "Alleycat5X 98DX3530M-A1"}, + { 0x9804, 0x1, "Alleycat5X 98DX3540M-A1"}, + { 0x9805, 0x1, "Alleycat5X 98DX3550M-A1"}, + { 0x9820, 0x1, "Alleycat5X 98DX3500-A1"}, + { 0x9826, 0x1, "Alleycat5X 98DX3501-A1"}, + { 0x9821, 0x1, "Alleycat5X 98DX3510-A1"}, + { 0x9861, 0x1, "Alleycat5X 98DX3510H-A1"}, + { 0x9841, 0x1, "Alleycat5X 98DX3510MH-A1"}, + { 0x9822, 0x1, "Alleycat5X 98DX3520-A1"}, + { 0x9823, 0x1, "Alleycat5X 98DX3530-A1"}, + { 0x9863, 0x1, "Alleycat5X 98DX3530H-A1"}, + { 0x9824, 0x1, "Alleycat5X 98DX3540-A1"}, + { 0x9825, 0x1, "Alleycat5X 98DX3550-A1"}, + + { 0xB400, 0x0, "Alleycat5-plus 98DX2538-A0"}, + { 0xB401, 0x0, "Alleycat5-plus 98DX2535-A0"}, + { 0xB402, 0x0, "Alleycat5-plus 98DX2532-A0"}, + { 0xB403, 0x0, "Alleycat5-plus 98DX2531-A0"}, + { 0xB408, 0x0, "Alleycat5 98DX2528-A0"}, + { 0xB409, 0x0, "Alleycat5 98DX2525-A0"}, + { 0xB40A, 0x0, "Alleycat5 98DX2522-A0"}, + { 0xB40B, 0x0, "Alleycat5 98DX2521-A0"}, + { 0xB410, 0x0, "Alleycat5-lite 98DX2518-A0"}, + { 0xB411, 0x0, "Alleycat5-lite 98DX2515-A0"}, + { 0xB412, 0x0, "Alleycat5-lite 98DX2512-A0"}, + { 0xB413, 0x0, "Alleycat5-lite 98DX2511-A0"}, + { 0x9800, 0x0, "Alleycat5X 98DX3500M-A0"}, + { 0x9806, 0x0, "Alleycat5X 98DX3501M-A0"}, + { 0x9801, 0x0, "Alleycat5X 98DX3510M-A0"}, + { 0x9802, 0x0, "Alleycat5X 98DX3520M-A0"}, + { 0x9803, 0x0, "Alleycat5X 98DX3530M-A0"}, + { 0x9804, 0x0, "Alleycat5X 98DX3540M-A0"}, + { 0x9805, 0x0, "Alleycat5X 98DX3550M-A0"}, + { 0x9820, 0x0, "Alleycat5X 98DX3500-A0"}, + { 0x9826, 0x0, "Alleycat5X 98DX3501-A0"}, + { 0x9821, 0x0, "Alleycat5X 98DX3510-A0"}, + { 0x9861, 0x0, "Alleycat5X 98DX3510H-A0"}, + { 0x9841, 0x0, "Alleycat5X 98DX3510MH-A0"}, + { 0x9822, 0x0, "Alleycat5X 98DX3520-A0"}, + { 0x9823, 0x0, "Alleycat5X 98DX3530-A0"}, + { 0x9863, 0x0, "Alleycat5X 98DX3530H-A0"}, + { 0x9824, 0x0, "Alleycat5X 98DX3540-A0"}, + { 0x9825, 0x0, "Alleycat5X 98DX3550-A0"}, +}; + +#define BIT_VAL(b) ((1ULL << ((b) + 1)) - 1) +#define BIT_RANGE(bl, bh) (BIT_VAL(bh) - BIT_VAL((bl) - 1)) + +#define PLL_MAX_CHOICE 4 + +#define CPU_TYPE_AC5 0 +#define CPU_TYPE_AC5x 1 +#define CPU_TYPE_LAST 2 + +enum mvebu_sar_opts { + SAR_CPU_FREQ = 0, + SAR_DDR_FREQ, + SAR_AP_FABRIC_FREQ, + SAR_CP_FABRIC_FREQ, + SAR_CP0_PCIE0_CLK, + SAR_CP0_PCIE1_CLK, + SAR_CP1_PCIE0_CLK, + SAR_CP1_PCIE1_CLK, + SAR_BOOT_SRC, + SAR_MAX_IDX +}; + +static const u32 pll_freq_tbl[CPU_TYPE_LAST][SAR_AP_FABRIC_FREQ + 1][PLL_MAX_CHOICE] = { + [CPU_TYPE_AC5] = { + [SAR_CPU_FREQ] = { + 800, 1200, 1400, 1000 + }, + [SAR_DDR_FREQ] = { + 1200, 800, 0, 0 + }, + [SAR_AP_FABRIC_FREQ] = { + 396, 290, 197, 0 + }, + }, + [CPU_TYPE_AC5x] = { + [SAR_CPU_FREQ] = { + 800, 1200, 1500, 1600 + }, + [SAR_DDR_FREQ] = { + 1200, 800, 0, 0 + }, + [SAR_AP_FABRIC_FREQ] = { + 0, 0, 0, 0 + } + } +}; + +static const u32 soc_sar_masks_tbl[CPU_TYPE_LAST][SAR_AP_FABRIC_FREQ + 1] = { + [CPU_TYPE_AC5] = { + [SAR_CPU_FREQ] = BIT_RANGE(18, 20), + [SAR_DDR_FREQ] = BIT_RANGE(16, 17), + [SAR_AP_FABRIC_FREQ] = BIT_RANGE(22, 23), + }, + [CPU_TYPE_AC5x] = { + [SAR_CPU_FREQ] = BIT_RANGE(8, 10), + [SAR_DDR_FREQ] = BIT_RANGE(6, 7), + [SAR_AP_FABRIC_FREQ] = 1, + }, +}; + +static int get_soc_type_rev(u32 *type, u32 *rev) +{ + *type = (readl(DEVICE_ID_REG) & DEVICE_ID_MASK) >> DEVICE_ID_OFFSET; + *rev = (readl(DEVICE_ID_REG) & REV_ID_MASK) >> REV_ID_OFFSET; + + return 0; +} + +static void get_one_sar_freq(int cpu_type, u32 sar_reg_val, enum mvebu_sar_opts sar_opt, u32 *freq) +{ + u32 mask; + unsigned char choice; + + mask = soc_sar_masks_tbl[cpu_type][sar_opt]; + choice = (sar_reg_val & mask) >> (__builtin_ffs(mask) - 1); + *freq = pll_freq_tbl[cpu_type][sar_opt][choice]; +} + +void get_sar_freq(struct sar_freq_modes *sar_freq) +{ + int cpu_type; + u32 soc_type, rev; + u32 sar_reg_val = readl(DEVICE_SAR_REG); + + get_soc_type_rev(&soc_type, &rev); + cpu_type = (soc_type & 0xFF00) == AC5X_DEV_ID ? CPU_TYPE_AC5x : CPU_TYPE_AC5; + + get_one_sar_freq(cpu_type, sar_reg_val, SAR_CPU_FREQ, &sar_freq->p_clk); + get_one_sar_freq(cpu_type, sar_reg_val, SAR_AP_FABRIC_FREQ, &sar_freq->nb_clk); + get_one_sar_freq(cpu_type, sar_reg_val, SAR_DDR_FREQ, &sar_freq->d_clk); +} + +static int get_soc_table_index(u32 *index) +{ + u32 soc_type; + u32 rev, i, ret = 1; + + *index = 0; + get_soc_type_rev(&soc_type, &rev); + + for (i = 0; i < ARRAY_SIZE(soc_info_table) && ret != 0; i++) { + if (soc_type != soc_info_table[i].dev_id || + rev != soc_info_table[i].rev_id) + continue; + + *index = i; + ret = 0; + } + + if (ret && ((soc_type & 0xFF00) == AC5X_DEV_ID)) + *index = 1; + + return ret; +} + +static int get_soc_name(char **soc_name) +{ + u32 index; + + get_soc_table_index(&index); + *soc_name = soc_info_table[index].soc_name; + + return 0; +} + +/* Print device's SoC name and AP & CP information */ +void soc_print_device_info(void) +{ + char *soc_name = NULL; + + get_soc_name(&soc_name); + + printf("SoC: %s\n", soc_name); +} + +void soc_print_clock_info(void) +{ + struct sar_freq_modes sar_freq; + + get_sar_freq(&sar_freq); + printf("Clock: CPU %4d MHz\n", sar_freq.p_clk); + printf("\tDDR %4d MHz\n", sar_freq.d_clk); + printf("\tFABRIC %4d MHz\n", sar_freq.nb_clk); + printf("\tMSS %4d MHz\n", 200); +} + +/* + * Override of __weak int mach_cpu_init(void) : + * SoC/machine dependent CPU setup + */ +int mach_cpu_init(void) +{ + u32 phy_i; + u64 new_val, phy_base = 0x7F080800; + + /* Init USB PHY */ +#define USB_STEPPING 0x20000 +#define WRITE_MASK(addr, mask, val) \ + { new_val = (readl(addr) & (~(mask))) | (val);\ + writel(new_val, addr); } + + for (phy_i = 0; phy_i < 2; phy_i++, phy_base += USB_STEPPING) { + WRITE_MASK(phy_base + 0x4, 0x3, 0x2); + WRITE_MASK(phy_base + 0xC, 0x3000000, 0x2000000); + WRITE_MASK(phy_base + 0x1C, 0x3, 0x2); + WRITE_MASK(phy_base + 0x0, 0x1FF007F, 0x600005); + WRITE_MASK(phy_base + 0xC, 0x000F000, 0x0002000); + /* Calibration Threshold Setting = 4*/ + WRITE_MASK(phy_base + 0x8, 0x700, 0x400) + WRITE_MASK(phy_base + 0x14, 0x000000F, 0x000000a); + /* Change AMP to 4*/ + WRITE_MASK(phy_base + 0xC, 0x3700000, 0x3400000); + WRITE_MASK(phy_base + 0x4, 0x3, 0x3); + /* Impedance calibration triggering is performed by USB probe */ + } + + return 0; +} + +int arch_misc_init(void) +{ + u32 type, rev; + + get_soc_type_rev(&type, &rev); + + return 0; +} diff --git a/arch/arm/mach-mvebu/alleycat5/soc.h b/arch/arm/mach-mvebu/alleycat5/soc.h new file mode 100644 index 0000000000..97663d2c01 --- /dev/null +++ b/arch/arm/mach-mvebu/alleycat5/soc.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _ALLEYCAT5_SOC_H +#define _ALLEYCAT5_SOC_H +void soc_print_device_info(void); +void soc_print_clock_info(void); +#endif /* _ALLEYCAT5_SOC_H */ |