--- /dev/null
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree For AC5.
+ *
+ * Copyright (C) 2021 Marvell
+ * Copyright (C) 2022 Allied Telesis Labs
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ model = "Marvell AC5 SoC";
+ compatible = "marvell,ac5";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu0>;
+ };
+ core1 {
+ cpu = <&cpu1>;
+ };
+ };
+ };
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ next-level-cache = <&l2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a55";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ next-level-cache = <&l2>;
+ };
+
+ l2: l2-cache {
+ compatible = "cache";
+ };
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_PPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pmu {
+ compatible = "arm,armv8-pmuv3";
+ interrupts = <GIC_PPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ dma-ranges;
+
+ internal-regs@7f000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ /* 16M internal register @ 0x7f00_0000 */
+ ranges = <0x0 0x0 0x7f000000 0x1000000>;
+ dma-coherent;
+
+ uart0: serial@12000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x12000 0x100>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ reg-io-width = <1>;
+ clocks = <&cnm_clock>;
+ status = "okay";
+ };
+
+ uart1: serial@12100 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x12100 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ clocks = <&cnm_clock>;
+ status = "disabled";
+ };
+
+ uart2: serial@12200 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x12200 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ clocks = <&cnm_clock>;
+ status = "disabled";
+ };
+
+ uart3: serial@12300 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x12300 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ clocks = <&cnm_clock>;
+ status = "disabled";
+ };
+
+ mdio: mdio@22004 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "marvell,orion-mdio";
+ reg = <0x22004 0x4>;
+ clocks = <&cnm_clock>;
+ };
+
+ i2c0: i2c@11000 {
+ compatible = "marvell,mv78230-i2c";
+ reg = <0x11000 0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ clocks = <&cnm_clock>;
+ clock-names = "core";
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency=<100000>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@11100 {
+ compatible = "marvell,mv78230-i2c";
+ reg = <0x11100 0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ clocks = <&cnm_clock>;
+ clock-names = "core";
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency=<100000>;
+ status = "disabled";
+ };
+
+ gpio0: gpio@18100 {
+ compatible = "marvell,orion-gpio";
+ reg = <0x18100 0x40>;
+ ngpios = <32>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ status = "okay";
+ };
+
+ gpio1: gpio@18140 {
+ reg = <0x18140 0x40>;
+ compatible = "marvell,orion-gpio";
+ ngpios = <14>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ status = "okay";
+ };
+ };
+
+ /*
+ * Dedicated section for devices behind 32bit controllers so we
+ * can configure specific DMA mapping for them
+ */
+ behind-32bit-controller@7f000000 {
+ compatible = "simple-bus";
+ #address-cells = <0x2>;
+ #size-cells = <0x2>;
+ ranges = <0x0 0x0 0x0 0x7f000000 0x0 0x1000000>;
+ /* Host phy ram starts at 0x200M */
+ dma-ranges = <0x0 0x0 0x2 0x0 0x1 0x0>;
+ dma-coherent;
+
+ eth0: ethernet@20000 {
+ compatible = "marvell,armada-ac5-neta";
+ reg = <0x0 0x20000 0x0 0x4000>;
+ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cnm_clock>;
+ phy-mode = "sgmii";
+ status = "disabled";
+ };
+
+ eth1: ethernet@24000 {
+ compatible = "marvell,armada-ac5-neta";
+ reg = <0x0 0x24000 0x0 0x4000>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cnm_clock>;
+ phy-mode = "sgmii";
+ status = "disabled";
+ };
+
+ usb0: usb@80000 {
+ compatible = "marvell,ac5-ehci";
+ reg = <0x0 0x80000 0x0 0x500>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ usb1: usb@a0000 {
+ compatible = "marvell,ac5-ehci";
+ reg = <0x0 0xa0000 0x0 0x500>;
+ interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+ };
+
+ pinctrl0: pinctrl@80020100 {
+ compatible = "marvell,mvebu-pinctrl";
+ reg = <0 0x80020100 0 0x20>;
+ pin-count = <46>;
+ max-func = <0xf>;
+ status = "okay";
+ };
+
+ spi0: spi@805a0000 {
+ compatible = "marvell,armada-3700-spi";
+ reg = <0x0 0x805a0000 0x0 0x50>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ clocks = <&spi_clock>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ num-cs = <1>;
+ status = "disabled";
+ };
+
+ spi1: spi@805a8000 {
+ compatible = "marvell,armada-3700-spi";
+ reg = <0x0 0x805a8000 0x0 0x50>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ clocks = <&spi_clock>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ num-cs = <1>;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@80600000 {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x0 0x80600000 0x0 0x10000>, /* GICD */
+ <0x0 0x80660000 0x0 0x40000>; /* GICR */
+ interrupts = <GIC_PPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
+ clocks {
+ cnm_clock: cnm-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <328000000>;
+ };
+
+ spi_clock: spi-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <200000000>;
+ };
+ };
+};
--- /dev/null
+// 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;
+}