diff mbox series

[v3,5/6] arm: mvebu: Support for 98DX25xx/98DX35xx SoC

Message ID 20220921045941.571980-6-judge.packham@gmail.com
State Superseded
Delegated to: Stefan Roese
Headers show
Series arm: mvebu: Support for 98DX25xx/98DX35xx (AlleyCat5) | expand

Commit Message

Chris Packham Sept. 21, 2022, 4:59 a.m. UTC
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>
---

Changes in v3:
- Remove unnecessary dma-ranges property from ethernet nodes (mvneta now
  correctly parses the property from the parent node).
- Keep soc_print_clock_info and soc_print_device_info local to
  alleycat5.

 arch/arm/dts/ac5-98dx25xx.dtsi         | 290 +++++++++++++++++++++++++
 arch/arm/dts/ac5-98dx35xx.dtsi         |  17 ++
 arch/arm/mach-mvebu/Kconfig            |   4 +
 arch/arm/mach-mvebu/Makefile           |   1 +
 arch/arm/mach-mvebu/alleycat5/Makefile |   9 +
 arch/arm/mach-mvebu/alleycat5/clock.c  |  49 +++++
 arch/arm/mach-mvebu/alleycat5/clock.h  |  11 +
 arch/arm/mach-mvebu/alleycat5/cpu.c    | 129 +++++++++++
 arch/arm/mach-mvebu/alleycat5/soc.c    | 229 +++++++++++++++++++
 arch/arm/mach-mvebu/alleycat5/soc.h    |   6 +
 arch/arm/mach-mvebu/arm64-common.c     |   5 +
 arch/arm/mach-mvebu/include/mach/cpu.h |   4 +
 12 files changed, 754 insertions(+)
 create mode 100644 arch/arm/dts/ac5-98dx25xx.dtsi
 create mode 100644 arch/arm/dts/ac5-98dx35xx.dtsi
 create mode 100644 arch/arm/mach-mvebu/alleycat5/Makefile
 create mode 100644 arch/arm/mach-mvebu/alleycat5/clock.c
 create mode 100644 arch/arm/mach-mvebu/alleycat5/clock.h
 create mode 100644 arch/arm/mach-mvebu/alleycat5/cpu.c
 create mode 100644 arch/arm/mach-mvebu/alleycat5/soc.c
 create mode 100644 arch/arm/mach-mvebu/alleycat5/soc.h

Comments

Stefan Roese Sept. 21, 2022, 5:58 a.m. UTC | #1
On 21.09.22 06:59, Chris Packham wrote:
> 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>
> ---
> 
> Changes in v3:
> - Remove unnecessary dma-ranges property from ethernet nodes (mvneta now
>    correctly parses the property from the parent node).
> - Keep soc_print_clock_info and soc_print_device_info local to
>    alleycat5.
> 
>   arch/arm/dts/ac5-98dx25xx.dtsi         | 290 +++++++++++++++++++++++++
>   arch/arm/dts/ac5-98dx35xx.dtsi         |  17 ++
>   arch/arm/mach-mvebu/Kconfig            |   4 +
>   arch/arm/mach-mvebu/Makefile           |   1 +
>   arch/arm/mach-mvebu/alleycat5/Makefile |   9 +
>   arch/arm/mach-mvebu/alleycat5/clock.c  |  49 +++++
>   arch/arm/mach-mvebu/alleycat5/clock.h  |  11 +
>   arch/arm/mach-mvebu/alleycat5/cpu.c    | 129 +++++++++++
>   arch/arm/mach-mvebu/alleycat5/soc.c    | 229 +++++++++++++++++++
>   arch/arm/mach-mvebu/alleycat5/soc.h    |   6 +
>   arch/arm/mach-mvebu/arm64-common.c     |   5 +
>   arch/arm/mach-mvebu/include/mach/cpu.h |   4 +
>   12 files changed, 754 insertions(+)
>   create mode 100644 arch/arm/dts/ac5-98dx25xx.dtsi
>   create mode 100644 arch/arm/dts/ac5-98dx35xx.dtsi
>   create mode 100644 arch/arm/mach-mvebu/alleycat5/Makefile
>   create mode 100644 arch/arm/mach-mvebu/alleycat5/clock.c
>   create mode 100644 arch/arm/mach-mvebu/alleycat5/clock.h
>   create mode 100644 arch/arm/mach-mvebu/alleycat5/cpu.c
>   create mode 100644 arch/arm/mach-mvebu/alleycat5/soc.c
>   create mode 100644 arch/arm/mach-mvebu/alleycat5/soc.h
> 
> diff --git a/arch/arm/dts/ac5-98dx25xx.dtsi b/arch/arm/dts/ac5-98dx25xx.dtsi
> new file mode 100644
> index 0000000000..64516938e8
> --- /dev/null
> +++ b/arch/arm/dts/ac5-98dx25xx.dtsi
> @@ -0,0 +1,290 @@
> +// 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>;
> +	};
> +
> +	config-space {
> +		#address-cells = <0x1>;
> +		#size-cells = <0x1>;
> +		compatible = "simple-bus";
> +
> +		sar-reg {
> +			compatible = "marvell,sample-at-reset-common";
> +			sar-driver = "ac5_sar";
> +			sar-name = "ac5_sar";
> +			status = "okay";
> +		};
> +	};
> +
> +	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>;
> +		};
> +	};
> +};
> diff --git a/arch/arm/dts/ac5-98dx35xx.dtsi b/arch/arm/dts/ac5-98dx35xx.dtsi
> new file mode 100644
> index 0000000000..2ab72f854b
> --- /dev/null
> +++ b/arch/arm/dts/ac5-98dx35xx.dtsi
> @@ -0,0 +1,17 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Device Tree For AC5X.
> + *
> + * Copyright (C) 2022 Allied Telesis Labs
> + */
> +
> +#include "ac5-98dx25xx.dtsi"
> +
> +/ {
> +	model = "Marvell AC5X SoC";
> +	compatible = "marvell,ac5x", "marvell,ac5";
> +};
> +
> +&cnm_clock {
> +	clock-frequency = <325000000>;
> +};
> diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
> index a81b8e2b0d..45efa24194 100644
> --- a/arch/arm/mach-mvebu/Kconfig
> +++ b/arch/arm/mach-mvebu/Kconfig
> @@ -49,6 +49,10 @@ config ARMADA_8K
>   	bool
>   	select ARM64
>   
> +config ALLEYCAT_5
> +	bool
> +	select ARM64
> +
>   # Armada PLL frequency (used for NAND clock generation)
>   config SYS_MVEBU_PLL_CLOCK
>   	int
> diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
> index 103e64cf20..f7d7f5f8ef 100644
> --- a/arch/arm/mach-mvebu/Makefile
> +++ b/arch/arm/mach-mvebu/Makefile
> @@ -6,6 +6,7 @@ ifdef CONFIG_ARM64
>   
>   obj-$(CONFIG_ARMADA_3700) += armada3700/
>   obj-$(CONFIG_ARMADA_8K) += armada8k/
> +obj-$(CONFIG_ALLEYCAT_5) += alleycat5/
>   obj-y += arm64-common.o
>   
>   else # CONFIG_ARM64
> diff --git a/arch/arm/mach-mvebu/alleycat5/Makefile b/arch/arm/mach-mvebu/alleycat5/Makefile
> new file mode 100644
> index 0000000000..43b8b70c84
> --- /dev/null
> +++ b/arch/arm/mach-mvebu/alleycat5/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# Copyright (C) 2016 Stefan Roese <sr@denx.de>
> +#
> +# SPDX-License-Identifier:	GPL-2.0+
> +#
> +
> +obj-y = cpu.o
> +obj-y += soc.o
> +obj-y += clock.o
> diff --git a/arch/arm/mach-mvebu/alleycat5/clock.c b/arch/arm/mach-mvebu/alleycat5/clock.c
> new file mode 100644
> index 0000000000..7c64da1ab6
> --- /dev/null
> +++ b/arch/arm/mach-mvebu/alleycat5/clock.c
> @@ -0,0 +1,49 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2018 Marvell International Ltd.
> + */
> +
> +#include <common.h>
> +#include <mvebu/mvebu_chip_sar.h>
> +#include "clock.h"
> +
> +#define CONFIG_MSS_FREQUENCY    (200 * 1000000)
> +
> +static u32 soc_ring_clk_get(void)
> +{
> +	struct sar_val sar;
> +
> +	mvebu_sar_value_get(SAR_AP_FABRIC_FREQ, &sar);
> +	return sar.freq;
> +}
> +
> +static u32 soc_mss_clk_get(void)
> +{
> +	return CONFIG_MSS_FREQUENCY;
> +}
> +
> +static u32 soc_cpu_clk_get(void)
> +{
> +	struct sar_val sar;
> +
> +	mvebu_sar_value_get(SAR_CPU_FREQ, &sar);
> +	return sar.freq;
> +}
> +
> +static u32 soc_ddr_clk_get(void)
> +{
> +	struct sar_val sar;
> +
> +	mvebu_sar_value_get(SAR_DDR_FREQ, &sar);
> +	return sar.freq;
> +}
> +
> +void soc_print_clock_info(void)
> +{
> +	char buf[32];
> +
> +	printf("Clock:  CPU     %4s MHz\n", strmhz(buf, soc_cpu_clk_get()));
> +	printf("\tDDR     %4s MHz\n", strmhz(buf, soc_ddr_clk_get()));
> +	printf("\tFABRIC  %4s MHz\n", strmhz(buf, soc_ring_clk_get()));
> +	printf("\tMSS     %4s MHz\n", strmhz(buf, soc_mss_clk_get()));
> +}
> diff --git a/arch/arm/mach-mvebu/alleycat5/clock.h b/arch/arm/mach-mvebu/alleycat5/clock.h
> new file mode 100644
> index 0000000000..6d6927446c
> --- /dev/null
> +++ b/arch/arm/mach-mvebu/alleycat5/clock.h
> @@ -0,0 +1,11 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2018 Marvell International Ltd.
> + */
> +
> +#ifndef _ALLEYCAT5_CLOCK_H_
> +#define _ALLEYCAT5_CLOCK_H_
> +
> +void soc_print_clock_info(void);
> +
> +#endif /* _ALLEYCAT5_CLOCK_H_ */
> diff --git a/arch/arm/mach-mvebu/alleycat5/cpu.c b/arch/arm/mach-mvebu/alleycat5/cpu.c
> new file mode 100644
> index 0000000000..b29f01be8b
> --- /dev/null
> +++ b/arch/arm/mach-mvebu/alleycat5/cpu.c
> @@ -0,0 +1,129 @@
> +// 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/arch/soc.h>
> +#include <asm/armv8/mmu.h>
> +#include "clock.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)
> +{
> +}
> +
> +#if defined(CONFIG_DISPLAY_CPUINFO)
> +int print_cpuinfo(void)
> +{
> +	soc_print_device_info();
> +	soc_print_clock_info();
> +
> +	return 0;
> +}
> +#endif

Remove this #ifdef here?

> +
> +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;
> +

Nitpick: Remove empty line.

> +	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..f388d4ee40
> --- /dev/null
> +++ b/arch/arm/mach-mvebu/alleycat5/soc.c
> @@ -0,0 +1,229 @@
> +// 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/soc.h>
> +#include <mvebu/mvebu_chip_sar.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 AP_DEV_ID_STATUS_REG		(SOC_REGS_PHY_BASE + 0x6F8240)
> +#define JTAG_DEV_ID_STATUS_REG		(SOC_REGS_PHY_BASE + 0x6F8244)
> +#define AP_DEV_ID_STATUS_MASK		0xfff
> +#define AP_DEV_REV_ID_STATUS_MASK	0xf0000000
> +#define SW_REV_STATUS_OFFSET		16
> +#define AP_REV_STATUS_OFFSET		28
> +#define SW_REV_STATUS_MASK		0xf
> +
> +#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 NF_CLOCK_SEL_MASK		0x1
> +#define SOC_MUX_NAND_EN_MASK		0x1
> +#define CLOCK_1Mhz			1000000
> +#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"},
> +};
> +
> +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 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);
> +}
> +
> +/* Return NAND clock in Hz */
> +u32 mvebu_get_nand_clock(void)
> +{
> +	return 200 * 1000000;
> +}

Is this still needed?

> +
> +int soc_early_init_f(void)
> +{
> +#ifdef CONFIG_MVEBU_SAR
> +/* Sample at reset register init */
> +	mvebu_sar_init();
> +#endif

Won't CONFIG_MVEBU_SAR always be enabled? Remove the #ifdef in this
case.

> +	return 0;
> +}
> +
> +/*
> + * Override of __weak int mach_cpu_init(void) :
> + * SoC/machine dependent CPU setup
> + */
> +int mach_cpu_init(void)
> +{
> +	u32 phy_i;
> +	u64 newVal, phyBase = 0x7F080800;

No CamelCase please.

> +
> +	/* Init USB PHY */
> +#define USB_STEPPING	0x20000
> +#define WRITE_MASK(addr, mask, val)		\
> +	{ newVal = (readl(addr) & (~(mask))) | val;\
> +	writel(newVal, addr); }
> +
> +	for (phy_i = 0; phy_i < 2; phy_i++, phyBase += USB_STEPPING) {
> +		WRITE_MASK(phyBase + 0x4,     0x3,	   0x2);
> +		WRITE_MASK(phyBase + 0xC,     0x3000000,   0x2000000);
> +		WRITE_MASK(phyBase + 0x1C,    0x3,         0x2);
> +		WRITE_MASK(phyBase + 0x0,     0x1FF007F,   0x600005);
> +		WRITE_MASK(phyBase + 0xC,     0x000F000,   0x0002000);
> +		/* Calibration Threshold Setting = 4*/
> +		WRITE_MASK(phyBase + 0x8,     0x700,	   0x400)
> +		WRITE_MASK(phyBase + 0x14,    0x000000F,   0x000000a);
> +		/* Change AMP to 4*/
> +		WRITE_MASK(phyBase + 0xC,     0x3700000,   0x3400000);
> +		WRITE_MASK(phyBase + 0x4,     0x3,	   0x3);
> +		/* Impedance calibration triggering is performed by USB probe */
> +	}
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_ARCH_MISC_INIT
> +int arch_misc_init(void)
> +{
> +	u32 type, rev;
> +
> +	get_soc_type_rev(&type, &rev);
> +
> +	return 0;
> +}
> +#endif

Remove the #ifdef here as well?

Thanks,
Stefan

> diff --git a/arch/arm/mach-mvebu/alleycat5/soc.h b/arch/arm/mach-mvebu/alleycat5/soc.h
> new file mode 100644
> index 0000000000..97bf3554d7
> --- /dev/null
> +++ b/arch/arm/mach-mvebu/alleycat5/soc.h
> @@ -0,0 +1,6 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +
> +#ifndef _ALLEYCAT5_SOC_H
> +#define _ALLEYCAT5_SOC_H
> +void soc_print_device_info(void);
> +#endif /* _ALLEYCAT5_SOC_H */
> diff --git a/arch/arm/mach-mvebu/arm64-common.c b/arch/arm/mach-mvebu/arm64-common.c
> index 238edbe6ba..7b8f7641b4 100644
> --- a/arch/arm/mach-mvebu/arm64-common.c
> +++ b/arch/arm/mach-mvebu/arm64-common.c
> @@ -53,6 +53,8 @@ __weak int dram_init_banksize(void)
>   		return a8k_dram_init_banksize();
>   	else if (CONFIG_IS_ENABLED(ARMADA_3700))
>   		return a3700_dram_init_banksize();
> +	else if (CONFIG_IS_ENABLED(ALLEYCAT_5))
> +		return alleycat5_dram_init_banksize();
>   	else
>   		return fdtdec_setup_memory_banksize();
>   }
> @@ -68,6 +70,9 @@ __weak int dram_init(void)
>   	if (CONFIG_IS_ENABLED(ARMADA_3700))
>   		return a3700_dram_init();
>   
> +	if (CONFIG_IS_ENABLED(ALLEYCAT_5))
> +		return alleycat5_dram_init();
> +
>   	if (fdtdec_setup_mem_size_base() != 0)
>   		return -EINVAL;
>   
> diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
> index b127fce865..c17c2440f1 100644
> --- a/arch/arm/mach-mvebu/include/mach/cpu.h
> +++ b/arch/arm/mach-mvebu/include/mach/cpu.h
> @@ -174,6 +174,10 @@ int a3700_dram_init_banksize(void);
>   /* A3700 PCIe regions fixer for device tree */
>   int a3700_fdt_fix_pcie_regions(void *blob);
>   
> +/* Alleycat5 dram functions */
> +int alleycat5_dram_init(void);
> +int alleycat5_dram_init_banksize(void);
> +
>   /*
>    * get_ref_clk
>    *

Viele Grüße,
Stefan Roese
Chris Packham Sept. 21, 2022, 9:05 p.m. UTC | #2
On Wed, Sep 21, 2022 at 5:58 PM Stefan Roese <sr@denx.de> wrote:
>
> On 21.09.22 06:59, Chris Packham wrote:
> > 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>
> > ---
> >
<snip>

> > diff --git a/arch/arm/mach-mvebu/alleycat5/soc.c b/arch/arm/mach-mvebu/alleycat5/soc.c
> > new file mode 100644
> > index 0000000000..f388d4ee40
> > --- /dev/null
> > +++ b/arch/arm/mach-mvebu/alleycat5/soc.c
<snip>
> > +/* Return NAND clock in Hz */
> > +u32 mvebu_get_nand_clock(void)
> > +{
> > +     return 200 * 1000000;
> > +}
>
> Is this still needed?
>

It will be needed eventually. After I get this landed I'll start work
on getting our board upstreamed and that does make use of the NAND
interface. There are some NAND driver changes that go along with this
so I'll move this over into that patch series.
Chris Packham Sept. 21, 2022, 9:25 p.m. UTC | #3
On Wed, Sep 21, 2022 at 5:58 PM Stefan Roese <sr@denx.de> wrote:
>
> On 21.09.22 06:59, Chris Packham wrote:
> > 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>
> > ---
> >

<snip>

> > diff --git a/arch/arm/mach-mvebu/alleycat5/soc.c b/arch/arm/mach-mvebu/alleycat5/soc.c
> > new file mode 100644
> > index 0000000000..f388d4ee40
> > --- /dev/null
> > +++ b/arch/arm/mach-mvebu/alleycat5/soc.c

<snip>

> > +int soc_early_init_f(void)
> > +{
> > +#ifdef CONFIG_MVEBU_SAR
> > +/* Sample at reset register init */
> > +     mvebu_sar_init();
> > +#endif
>
> Won't CONFIG_MVEBU_SAR always be enabled? Remove the #ifdef in this
> case.
>
> > +     return 0;
> > +}

Currently it is possible to turn it off. As I've said I think I do
need to look at the whole SAR business and see if it can be done
differently.

One useful thing it does do is tell me about how the hardware has been
strapped. U-Boot itself doesn't care about that specifically as the
separate mv_ddr blob that runs before ATF is the thing that actually
uses the SAR values. But U-
Boot is the first place that can give me some friendly output about
the board and knowing the CPU/DDR clock speed is useful at that level.
Pali Rohár Sept. 21, 2022, 9:40 p.m. UTC | #4
On Thursday 22 September 2022 09:25:37 Chris Packham wrote:
> On Wed, Sep 21, 2022 at 5:58 PM Stefan Roese <sr@denx.de> wrote:
> >
> > On 21.09.22 06:59, Chris Packham wrote:
> > > 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>
> > > ---
> > >
> 
> <snip>
> 
> > > diff --git a/arch/arm/mach-mvebu/alleycat5/soc.c b/arch/arm/mach-mvebu/alleycat5/soc.c
> > > new file mode 100644
> > > index 0000000000..f388d4ee40
> > > --- /dev/null
> > > +++ b/arch/arm/mach-mvebu/alleycat5/soc.c
> 
> <snip>
> 
> > > +int soc_early_init_f(void)
> > > +{
> > > +#ifdef CONFIG_MVEBU_SAR
> > > +/* Sample at reset register init */
> > > +     mvebu_sar_init();
> > > +#endif
> >
> > Won't CONFIG_MVEBU_SAR always be enabled? Remove the #ifdef in this
> > case.
> >
> > > +     return 0;
> > > +}
> 
> Currently it is possible to turn it off. As I've said I think I do
> need to look at the whole SAR business and see if it can be done
> differently.
> 
> One useful thing it does do is tell me about how the hardware has been
> strapped. U-Boot itself doesn't care about that specifically as the
> separate mv_ddr blob that runs before ATF is the thing that actually
> uses the SAR values. But U-
> Boot is the first place that can give me some friendly output about
> the board and knowing the CPU/DDR clock speed is useful at that level.

I agree that the last thing - print information about CPU/DDR clock
speed is useful [1]. But I do not see reason why to complicate it such
much via new uclass OOP model for other things in DTS, which moreover
use already deprecated structure and requires hack in fdtdec.c file.

I think that the whole SAR code can be simplified and written
straightforward for AC5 to be easier for developer to read... but this
step is not probably such simple as it is required to first understand
what is this "complicated" code doing and it is probably boring job :-(

For 32-bit Armada there is already very simple SAR register handling to
check and detect TCLK speed. So I think AC5 is similar in this area, but
more has more complicated code logic and "very simple 32-bit SAR" is not
suitable to reuse.


[1] - Btw, I added this print in A3720 secure firmware, because it is
really useful and important (!) and secure firmware is who configures it
Chris Packham Sept. 21, 2022, 9:55 p.m. UTC | #5
On Thu, Sep 22, 2022 at 9:40 AM Pali Rohár <pali@kernel.org> wrote:
>
> On Thursday 22 September 2022 09:25:37 Chris Packham wrote:
> > On Wed, Sep 21, 2022 at 5:58 PM Stefan Roese <sr@denx.de> wrote:
> > >
> > > On 21.09.22 06:59, Chris Packham wrote:
> > > > 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>
> > > > ---
> > > >
> >
> > <snip>
> >
> > > > diff --git a/arch/arm/mach-mvebu/alleycat5/soc.c b/arch/arm/mach-mvebu/alleycat5/soc.c
> > > > new file mode 100644
> > > > index 0000000000..f388d4ee40
> > > > --- /dev/null
> > > > +++ b/arch/arm/mach-mvebu/alleycat5/soc.c
> >
> > <snip>
> >
> > > > +int soc_early_init_f(void)
> > > > +{
> > > > +#ifdef CONFIG_MVEBU_SAR
> > > > +/* Sample at reset register init */
> > > > +     mvebu_sar_init();
> > > > +#endif
> > >
> > > Won't CONFIG_MVEBU_SAR always be enabled? Remove the #ifdef in this
> > > case.
> > >
> > > > +     return 0;
> > > > +}
> >
> > Currently it is possible to turn it off. As I've said I think I do
> > need to look at the whole SAR business and see if it can be done
> > differently.
> >
> > One useful thing it does do is tell me about how the hardware has been
> > strapped. U-Boot itself doesn't care about that specifically as the
> > separate mv_ddr blob that runs before ATF is the thing that actually
> > uses the SAR values. But U-
> > Boot is the first place that can give me some friendly output about
> > the board and knowing the CPU/DDR clock speed is useful at that level.
>
> I agree that the last thing - print information about CPU/DDR clock
> speed is useful [1]. But I do not see reason why to complicate it such
> much via new uclass OOP model for other things in DTS, which moreover
> use already deprecated structure and requires hack in fdtdec.c file.
>

Agreed. The fact that I can turn the driver off and (after fixing some
code that calls into it directly) everything still works (except for
the reporting of the clock speeds) it does indicate that I don't
really need this.

> I think that the whole SAR code can be simplified and written
> straightforward for AC5 to be easier for developer to read... but this
> step is not probably such simple as it is required to first understand
> what is this "complicated" code doing and it is probably boring job :-(

Not boring but it doesn't help that Marvell don't document the SAR
registers so I can only go by following their overly complicated code.

>
> For 32-bit Armada there is already very simple SAR register handling to
> check and detect TCLK speed. So I think AC5 is similar in this area, but
> more has more complicated code logic and "very simple 32-bit SAR" is not
> suitable to reuse.
>

I think I can come up with something that replaces the sar-uclass
business with code that just accesses the relevant register(s)
directly in the alleycat5/soc.c code.

>
> [1] - Btw, I added this print in A3720 secure firmware, because it is
> really useful and important (!) and secure firmware is who configures it
Pali Rohár Sept. 21, 2022, 10:12 p.m. UTC | #6
On Thursday 22 September 2022 09:55:24 Chris Packham wrote:
> Not boring but it doesn't help that Marvell don't document the SAR
> registers so I can only go by following their overly complicated code.

Ah :-( This is never ending story with Marvell... nobody is able to gain
access to the documentation. And developers than has to just guess what
it could mean...
diff mbox series

Patch

diff --git a/arch/arm/dts/ac5-98dx25xx.dtsi b/arch/arm/dts/ac5-98dx25xx.dtsi
new file mode 100644
index 0000000000..64516938e8
--- /dev/null
+++ b/arch/arm/dts/ac5-98dx25xx.dtsi
@@ -0,0 +1,290 @@ 
+// 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>;
+	};
+
+	config-space {
+		#address-cells = <0x1>;
+		#size-cells = <0x1>;
+		compatible = "simple-bus";
+
+		sar-reg {
+			compatible = "marvell,sample-at-reset-common";
+			sar-driver = "ac5_sar";
+			sar-name = "ac5_sar";
+			status = "okay";
+		};
+	};
+
+	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>;
+		};
+	};
+};
diff --git a/arch/arm/dts/ac5-98dx35xx.dtsi b/arch/arm/dts/ac5-98dx35xx.dtsi
new file mode 100644
index 0000000000..2ab72f854b
--- /dev/null
+++ b/arch/arm/dts/ac5-98dx35xx.dtsi
@@ -0,0 +1,17 @@ 
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree For AC5X.
+ *
+ * Copyright (C) 2022 Allied Telesis Labs
+ */
+
+#include "ac5-98dx25xx.dtsi"
+
+/ {
+	model = "Marvell AC5X SoC";
+	compatible = "marvell,ac5x", "marvell,ac5";
+};
+
+&cnm_clock {
+	clock-frequency = <325000000>;
+};
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index a81b8e2b0d..45efa24194 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -49,6 +49,10 @@  config ARMADA_8K
 	bool
 	select ARM64
 
+config ALLEYCAT_5
+	bool
+	select ARM64
+
 # Armada PLL frequency (used for NAND clock generation)
 config SYS_MVEBU_PLL_CLOCK
 	int
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 103e64cf20..f7d7f5f8ef 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -6,6 +6,7 @@  ifdef CONFIG_ARM64
 
 obj-$(CONFIG_ARMADA_3700) += armada3700/
 obj-$(CONFIG_ARMADA_8K) += armada8k/
+obj-$(CONFIG_ALLEYCAT_5) += alleycat5/
 obj-y += arm64-common.o
 
 else # CONFIG_ARM64
diff --git a/arch/arm/mach-mvebu/alleycat5/Makefile b/arch/arm/mach-mvebu/alleycat5/Makefile
new file mode 100644
index 0000000000..43b8b70c84
--- /dev/null
+++ b/arch/arm/mach-mvebu/alleycat5/Makefile
@@ -0,0 +1,9 @@ 
+#
+# Copyright (C) 2016 Stefan Roese <sr@denx.de>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y = cpu.o
+obj-y += soc.o
+obj-y += clock.o
diff --git a/arch/arm/mach-mvebu/alleycat5/clock.c b/arch/arm/mach-mvebu/alleycat5/clock.c
new file mode 100644
index 0000000000..7c64da1ab6
--- /dev/null
+++ b/arch/arm/mach-mvebu/alleycat5/clock.c
@@ -0,0 +1,49 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ */
+
+#include <common.h>
+#include <mvebu/mvebu_chip_sar.h>
+#include "clock.h"
+
+#define CONFIG_MSS_FREQUENCY    (200 * 1000000)
+
+static u32 soc_ring_clk_get(void)
+{
+	struct sar_val sar;
+
+	mvebu_sar_value_get(SAR_AP_FABRIC_FREQ, &sar);
+	return sar.freq;
+}
+
+static u32 soc_mss_clk_get(void)
+{
+	return CONFIG_MSS_FREQUENCY;
+}
+
+static u32 soc_cpu_clk_get(void)
+{
+	struct sar_val sar;
+
+	mvebu_sar_value_get(SAR_CPU_FREQ, &sar);
+	return sar.freq;
+}
+
+static u32 soc_ddr_clk_get(void)
+{
+	struct sar_val sar;
+
+	mvebu_sar_value_get(SAR_DDR_FREQ, &sar);
+	return sar.freq;
+}
+
+void soc_print_clock_info(void)
+{
+	char buf[32];
+
+	printf("Clock:  CPU     %4s MHz\n", strmhz(buf, soc_cpu_clk_get()));
+	printf("\tDDR     %4s MHz\n", strmhz(buf, soc_ddr_clk_get()));
+	printf("\tFABRIC  %4s MHz\n", strmhz(buf, soc_ring_clk_get()));
+	printf("\tMSS     %4s MHz\n", strmhz(buf, soc_mss_clk_get()));
+}
diff --git a/arch/arm/mach-mvebu/alleycat5/clock.h b/arch/arm/mach-mvebu/alleycat5/clock.h
new file mode 100644
index 0000000000..6d6927446c
--- /dev/null
+++ b/arch/arm/mach-mvebu/alleycat5/clock.h
@@ -0,0 +1,11 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ */
+
+#ifndef _ALLEYCAT5_CLOCK_H_
+#define _ALLEYCAT5_CLOCK_H_
+
+void soc_print_clock_info(void);
+
+#endif /* _ALLEYCAT5_CLOCK_H_ */
diff --git a/arch/arm/mach-mvebu/alleycat5/cpu.c b/arch/arm/mach-mvebu/alleycat5/cpu.c
new file mode 100644
index 0000000000..b29f01be8b
--- /dev/null
+++ b/arch/arm/mach-mvebu/alleycat5/cpu.c
@@ -0,0 +1,129 @@ 
+// 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/arch/soc.h>
+#include <asm/armv8/mmu.h>
+#include "clock.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)
+{
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	soc_print_device_info();
+	soc_print_clock_info();
+
+	return 0;
+}
+#endif
+
+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..f388d4ee40
--- /dev/null
+++ b/arch/arm/mach-mvebu/alleycat5/soc.c
@@ -0,0 +1,229 @@ 
+// 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/soc.h>
+#include <mvebu/mvebu_chip_sar.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 AP_DEV_ID_STATUS_REG		(SOC_REGS_PHY_BASE + 0x6F8240)
+#define JTAG_DEV_ID_STATUS_REG		(SOC_REGS_PHY_BASE + 0x6F8244)
+#define AP_DEV_ID_STATUS_MASK		0xfff
+#define AP_DEV_REV_ID_STATUS_MASK	0xf0000000
+#define SW_REV_STATUS_OFFSET		16
+#define AP_REV_STATUS_OFFSET		28
+#define SW_REV_STATUS_MASK		0xf
+
+#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 NF_CLOCK_SEL_MASK		0x1
+#define SOC_MUX_NAND_EN_MASK		0x1
+#define CLOCK_1Mhz			1000000
+#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"},
+};
+
+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 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);
+}
+
+/* Return NAND clock in Hz */
+u32 mvebu_get_nand_clock(void)
+{
+	return 200 * 1000000;
+}
+
+int soc_early_init_f(void)
+{
+#ifdef CONFIG_MVEBU_SAR
+/* Sample at reset register init */
+	mvebu_sar_init();
+#endif
+	return 0;
+}
+
+/*
+ * Override of __weak int mach_cpu_init(void) :
+ * SoC/machine dependent CPU setup
+ */
+int mach_cpu_init(void)
+{
+	u32 phy_i;
+	u64 newVal, phyBase = 0x7F080800;
+
+	/* Init USB PHY */
+#define USB_STEPPING	0x20000
+#define WRITE_MASK(addr, mask, val)		\
+	{ newVal = (readl(addr) & (~(mask))) | val;\
+	writel(newVal, addr); }
+
+	for (phy_i = 0; phy_i < 2; phy_i++, phyBase += USB_STEPPING) {
+		WRITE_MASK(phyBase + 0x4,     0x3,	   0x2);
+		WRITE_MASK(phyBase + 0xC,     0x3000000,   0x2000000);
+		WRITE_MASK(phyBase + 0x1C,    0x3,         0x2);
+		WRITE_MASK(phyBase + 0x0,     0x1FF007F,   0x600005);
+		WRITE_MASK(phyBase + 0xC,     0x000F000,   0x0002000);
+		/* Calibration Threshold Setting = 4*/
+		WRITE_MASK(phyBase + 0x8,     0x700,	   0x400)
+		WRITE_MASK(phyBase + 0x14,    0x000000F,   0x000000a);
+		/* Change AMP to 4*/
+		WRITE_MASK(phyBase + 0xC,     0x3700000,   0x3400000);
+		WRITE_MASK(phyBase + 0x4,     0x3,	   0x3);
+		/* Impedance calibration triggering is performed by USB probe */
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_ARCH_MISC_INIT
+int arch_misc_init(void)
+{
+	u32 type, rev;
+
+	get_soc_type_rev(&type, &rev);
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-mvebu/alleycat5/soc.h b/arch/arm/mach-mvebu/alleycat5/soc.h
new file mode 100644
index 0000000000..97bf3554d7
--- /dev/null
+++ b/arch/arm/mach-mvebu/alleycat5/soc.h
@@ -0,0 +1,6 @@ 
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _ALLEYCAT5_SOC_H
+#define _ALLEYCAT5_SOC_H
+void soc_print_device_info(void);
+#endif /* _ALLEYCAT5_SOC_H */
diff --git a/arch/arm/mach-mvebu/arm64-common.c b/arch/arm/mach-mvebu/arm64-common.c
index 238edbe6ba..7b8f7641b4 100644
--- a/arch/arm/mach-mvebu/arm64-common.c
+++ b/arch/arm/mach-mvebu/arm64-common.c
@@ -53,6 +53,8 @@  __weak int dram_init_banksize(void)
 		return a8k_dram_init_banksize();
 	else if (CONFIG_IS_ENABLED(ARMADA_3700))
 		return a3700_dram_init_banksize();
+	else if (CONFIG_IS_ENABLED(ALLEYCAT_5))
+		return alleycat5_dram_init_banksize();
 	else
 		return fdtdec_setup_memory_banksize();
 }
@@ -68,6 +70,9 @@  __weak int dram_init(void)
 	if (CONFIG_IS_ENABLED(ARMADA_3700))
 		return a3700_dram_init();
 
+	if (CONFIG_IS_ENABLED(ALLEYCAT_5))
+		return alleycat5_dram_init();
+
 	if (fdtdec_setup_mem_size_base() != 0)
 		return -EINVAL;
 
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index b127fce865..c17c2440f1 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -174,6 +174,10 @@  int a3700_dram_init_banksize(void);
 /* A3700 PCIe regions fixer for device tree */
 int a3700_fdt_fix_pcie_regions(void *blob);
 
+/* Alleycat5 dram functions */
+int alleycat5_dram_init(void);
+int alleycat5_dram_init_banksize(void);
+
 /*
  * get_ref_clk
  *