* [PATCH 01/10] ARM: socfpga: kconfig: sort entries
2024-10-29 8:42 [PATCH 00/10] ARM: SoCFPGA: Add initial support for Agilex5 Steffen Trumtrar
@ 2024-10-29 8:42 ` Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 02/10] mach: socfpga: debug_ll: rework putc_ll Steffen Trumtrar
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Steffen Trumtrar @ 2024-10-29 8:42 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
Sort the SoCFPGA entries in the menu by soc type. Add a comment while at it.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
arch/arm/mach-socfpga/Kconfig | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index a4d71777978869c29443e4499c262875a835437d..80a15377b2e4be4d1386904a298a9aadcffbab00 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -23,6 +23,10 @@ config ARCH_SOCFPGA_ARRIA10
select OFDEVICE
select OFTREE
+if 32BIT
+
+comment "Cyclone5 boards"
+
config MACH_SOCFPGA_ALTERA_SOCDK
select ARCH_SOCFPGA_CYCLONE5
bool "Altera SoCFPGA Development Kit"
@@ -31,14 +35,6 @@ config MACH_SOCFPGA_EBV_SOCRATES
select ARCH_SOCFPGA_CYCLONE5
bool "EBV Socrates"
-config MACH_SOCFPGA_ENCLUSTRA_AA1
- select ARCH_SOCFPGA_ARRIA10
- bool "Enclustra AA1"
-
-config MACH_SOCFPGA_REFLEX_ACHILLES
- select ARCH_SOCFPGA_ARRIA10
- bool "Reflex Achilles"
-
config MACH_SOCFPGA_TERASIC_DE0_NANO_SOC
select ARCH_SOCFPGA_CYCLONE5
bool "Terasic DE0-NANO-SoC aka Atlas"
@@ -51,4 +47,15 @@ config MACH_SOCFPGA_TERASIC_SOCKIT
select ARCH_SOCFPGA_CYCLONE5
bool "Terasic SoCKit"
+comment "Arria10 boards"
+
+config MACH_SOCFPGA_ENCLUSTRA_AA1
+ select ARCH_SOCFPGA_ARRIA10
+ bool "Enclustra AA1"
+
+config MACH_SOCFPGA_REFLEX_ACHILLES
+ select ARCH_SOCFPGA_ARRIA10
+ bool "Reflex Achilles"
+
+endif
endif
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 02/10] mach: socfpga: debug_ll: rework putc_ll
2024-10-29 8:42 [PATCH 00/10] ARM: SoCFPGA: Add initial support for Agilex5 Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 01/10] ARM: socfpga: kconfig: sort entries Steffen Trumtrar
@ 2024-10-29 8:42 ` Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 03/10] reset: reset-socfpga: build only for 32-bit socfpga Steffen Trumtrar
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Steffen Trumtrar @ 2024-10-29 8:42 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
Cleanup the debug_ll code for SoCFPGA. The old Gen5 Socfpga have a
narrower ioport width for the NS16550. All newer generations support
32-bit access. Invert the logic and add new *_uart_putc functions for
use with pbl_set_putc.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
arch/arm/mach-socfpga/arria10-init.c | 2 +-
arch/arm/mach-socfpga/cyclone5-init.c | 2 +-
include/mach/socfpga/debug_ll.h | 44 +++++++++++++++++++++++------------
3 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-socfpga/arria10-init.c b/arch/arm/mach-socfpga/arria10-init.c
index f8a15ec8b46a761904e470d66bd0900fdb0686ec..14cee3196ade7d36adbb1b70c5b0041bce3cc193 100644
--- a/arch/arm/mach-socfpga/arria10-init.c
+++ b/arch/arm/mach-socfpga/arria10-init.c
@@ -147,7 +147,7 @@ void arria10_finish_io(uint32_t *pinmux)
arria10_reset_deassert_fpga_peripherals();
- INIT_LL();
+ socfpga_uart_setup_ll();
puts_ll("lowlevel init done\n");
}
diff --git a/arch/arm/mach-socfpga/cyclone5-init.c b/arch/arm/mach-socfpga/cyclone5-init.c
index 79a9b15d8761baa8b576a83871a06fbf0559ce91..63ec48b8e48d7e8daa9ce9c158ad5716739b9b3d 100644
--- a/arch/arm/mach-socfpga/cyclone5-init.c
+++ b/arch/arm/mach-socfpga/cyclone5-init.c
@@ -56,5 +56,5 @@ void socfpga_lowlevel_init(struct socfpga_cm_config *cm_config,
writel(0x18, CYCLONE5_L3REGS_ADDRESS);
writel(0x1, 0xfffefc00);
- INIT_LL();
+ socfpga_uart_setup_ll();
}
diff --git a/include/mach/socfpga/debug_ll.h b/include/mach/socfpga/debug_ll.h
index 25b3581634704ac523b031a915b73408b674e0c5..698cca60373f7e382db12344e83925dbcb3b35aa 100644
--- a/include/mach/socfpga/debug_ll.h
+++ b/include/mach/socfpga/debug_ll.h
@@ -30,6 +30,26 @@
#define SCR 0x1c
#define THR 0x30
+static inline void socfpga_gen5_uart_putc(void *base, int c)
+{
+ /* Wait until there is space in the FIFO */
+ while ((readb(base + LSR) & LSR_THRE) == 0);
+ /* Send the character */
+ writeb(c, base + THR);
+ /* Wait to make sure it hits the line, in case we die too soon. */
+ while ((readb(base + LSR) & LSR_THRE) == 0);
+}
+
+static inline void socfpga_uart_putc(void *base, int c)
+{
+ /* Wait until there is space in the FIFO */
+ while ((readl(base + LSR) & LSR_THRE) == 0);
+ /* Send the character */
+ writel(c, base + THR);
+ /* Wait to make sure it hits the line, in case we die too soon. */
+ while ((readl(base + LSR) & LSR_THRE) == 0);
+}
+
#ifdef CONFIG_DEBUG_LL
static inline unsigned int ns16550_calc_divisor(unsigned int clk,
unsigned int baudrate)
@@ -37,7 +57,7 @@ static inline unsigned int ns16550_calc_divisor(unsigned int clk,
return (clk / 16 / baudrate);
}
-static inline void INIT_LL(void)
+static inline void socfpga_uart_setup_ll(void)
{
unsigned int div = ns16550_calc_divisor(CONFIG_DEBUG_SOCFPGA_UART_CLOCK,
115200);
@@ -53,25 +73,19 @@ static inline void INIT_LL(void)
writel(FCRVAL, UART_BASE + FCR);
}
-#ifdef CONFIG_ARCH_SOCFPGA_ARRIA10
+#if defined(CONFIG_ARCH_SOCFPGA_CYCLONE5)
static inline void PUTC_LL(char c)
{
- /* Wait until there is space in the FIFO */
- while ((readl(UART_BASE + LSR) & LSR_THRE) == 0);
- /* Send the character */
- writel(c, UART_BASE + THR);
- /* Wait to make sure it hits the line, in case we die too soon. */
- while ((readl(UART_BASE + LSR) & LSR_THRE) == 0);
+ void __iomem *base = IOMEM(UART_BASE);
+
+ socfpga_gen5_uart_putc(base, c);
}
#else
static inline void PUTC_LL(char c)
{
- /* Wait until there is space in the FIFO */
- while ((readb(UART_BASE + LSR) & LSR_THRE) == 0);
- /* Send the character */
- writeb(c, UART_BASE + THR);
- /* Wait to make sure it hits the line, in case we die too soon. */
- while ((readb(UART_BASE + LSR) & LSR_THRE) == 0);
+ void __iomem *base = IOMEM(UART_BASE);
+
+ socfpga_uart_putc(base, c);
}
#endif
@@ -80,7 +94,7 @@ static inline unsigned int ns16550_calc_divisor(unsigned int clk,
unsigned int baudrate) {
return -ENOSYS;
}
-static inline void INIT_LL(void) {}
+static inline void socfpga_uart_setup_ll(void) {}
static inline void PUTC_LL(char c) {}
#endif
#endif /* __MACH_SOCFPGA_DEBUG_LL_H__ */
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 03/10] reset: reset-socfpga: build only for 32-bit socfpga
2024-10-29 8:42 [PATCH 00/10] ARM: SoCFPGA: Add initial support for Agilex5 Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 01/10] ARM: socfpga: kconfig: sort entries Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 02/10] mach: socfpga: debug_ll: rework putc_ll Steffen Trumtrar
@ 2024-10-29 8:42 ` Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 04/10] arm: socfgpa: add support for SoCFPGA Agilex5 Steffen Trumtrar
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Steffen Trumtrar @ 2024-10-29 8:42 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
The 64-bit SoCFPGA platforms will use reset-simple.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
drivers/reset/Kconfig | 6 ++++++
drivers/reset/Makefile | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 16c05d50f0e30cb93609c6fbaa4287975894509a..c3779f087490f57deeabf2178723983a87d0446c 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -57,4 +57,10 @@ config RESET_SCMI
This driver uses SCMI Message Protocol to interact with the
firmware controlling all the reset signals.
+config RESET_SOCFPGA32
+ bool "SoCFPGA 32-bit Reset Driver"
+ default ARCH_SOCFPGA && 32BIT
+ help
+ This enables the reset controller driver for 32-bit SoCFPGA platforms.
+
endif
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index b1668433d76af89a49ef577ad9d0cdc4af48de8d..a446cb20d0b7ddb6404fdf385498bdf6a076e34e 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_RESET_CONTROLLER) += core.o
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
-obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
+obj-$(CONFIG_RESET_SOCFPGA32) += reset-socfpga.o
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
obj-$(CONFIG_RESET_STARFIVE) += reset-starfive-vic.o
obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 04/10] arm: socfgpa: add support for SoCFPGA Agilex5
2024-10-29 8:42 [PATCH 00/10] ARM: SoCFPGA: Add initial support for Agilex5 Steffen Trumtrar
` (2 preceding siblings ...)
2024-10-29 8:42 ` [PATCH 03/10] reset: reset-socfpga: build only for 32-bit socfpga Steffen Trumtrar
@ 2024-10-29 8:42 ` Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 05/10] ARM: socfpga: add Arrow AXE5 Agilex5 board Steffen Trumtrar
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Steffen Trumtrar @ 2024-10-29 8:42 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
Add initial support for the Intel Agilex5 SoCFPGA platform.
The Agilex5 devices have:
- Quad-core cluster consisting of Dual-core 64-bit Arm Cortex-A76, and dual-core 64-bit Arm Cortex-A55 (SoC only)
- High-Speed transceivers, up to 17.1 Gbps (group B) and 28.1 Gbps (group A)
- PCIe Gen4 x4
- DDR4/LPDDR4/LPDDR5, and DDR5 (group A)
- Native MIPI CSI-2 and D-PHY (multiple channels)
- Secure Device Manager (SDM) to support secure configuration and tamper prevention, and hardened cryptographic engines
(from https://www.rocketboards.org/foswiki/Documentation/ArrowAXE5EagleDevelopmentKit)
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
arch/arm/Kconfig | 3 -
arch/arm/dts/socfpga_agilex5.dtsi | 71 ++++
arch/arm/mach-socfpga/Kconfig | 37 +-
arch/arm/mach-socfpga/Makefile | 13 +
arch/arm/mach-socfpga/agilex5-clock-manager.c | 411 +++++++++++++++++++
arch/arm/mach-socfpga/agilex5-sdram.c | 352 ++++++++++++++++
arch/arm/mach-socfpga/agilex5-secreg.c | 289 ++++++++++++++
arch/arm/mach-socfpga/atf.c | 34 ++
arch/arm/mach-socfpga/cpu_init.c | 43 ++
arch/arm/mach-socfpga/iossm_mailbox.c | 551 ++++++++++++++++++++++++++
arch/arm/mach-socfpga/iossm_mailbox.h | 152 +++++++
arch/arm/mach-socfpga/mailbox_s10.c | 407 +++++++++++++++++++
arch/arm/mach-socfpga/secure_reg_helper.c | 75 ++++
arch/arm/mach-socfpga/smc_api.c | 43 ++
arch/arm/mach-socfpga/soc64-system-manager.c | 102 +++++
arch/arm/mach-socfpga/soc64-wrap-handoff.c | 124 ++++++
common/Kconfig.debug_ll | 17 +
firmware/Kconfig | 3 +
firmware/Makefile | 1 +
images/Makefile.socfpga | 8 +
include/dt-bindings/clock/agilex5-clock.h | 71 ++++
include/linux/intel-smc.h | 545 +++++++++++++++++++++++++
include/mach/socfpga/agilex5-clk.h | 266 +++++++++++++
include/mach/socfpga/atf.h | 14 +
include/mach/socfpga/generic.h | 3 +
include/mach/socfpga/init.h | 2 +
include/mach/socfpga/mailbox_s10.h | 199 ++++++++++
include/mach/socfpga/secure_reg_helper.h | 19 +
include/mach/socfpga/smc_api.h | 12 +
include/mach/socfpga/soc64-firewall.h | 177 +++++++++
include/mach/socfpga/soc64-handoff.h | 50 +++
include/mach/socfpga/soc64-init.h | 4 +
include/mach/socfpga/soc64-regs.h | 195 +++++++++
include/mach/socfpga/soc64-reset-manager.h | 40 ++
include/mach/socfpga/soc64-sdram.h | 203 ++++++++++
include/mach/socfpga/soc64-system-manager.h | 176 ++++++++
36 files changed, 4705 insertions(+), 7 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9b90c8009a352cb3f572e6e92a7b7571c94dad4d..6a8fd6d4973b0a8149f781eed493896bf3abed1a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -103,10 +103,7 @@ config ARCH_PXA
config ARCH_SOCFPGA
bool "Altera SOCFPGA"
- depends on 32BIT
select HAS_DEBUG_LL
- select ARM_SMP_TWD
- select CPU_V7
select COMMON_CLK
config ARCH_TEGRA
diff --git a/arch/arm/dts/socfpga_agilex5.dtsi b/arch/arm/dts/socfpga_agilex5.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..24bebf7c3a951acaad03c9b43e14735a5923ca04
--- /dev/null
+++ b/arch/arm/dts/socfpga_agilex5.dtsi
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2023 Intel Corporation <www.intel.com>
+ */
+
+&soc {
+ gmac0: ethernet@10810000 {
+ compatible = "intel,socfpga-dwxgmac", "snps,dwxgmac-2.10", "snps,dwxgmac";
+ reg = <0x10810000 0x3500>;
+ interrupts = <0 190 4>;
+ interrupt-names = "macirq";
+ resets = <&rst EMAC0_RESET>, <&rst EMAC0_OCP_RESET>;
+ reset-names = "stmmaceth", "stmmaceth-ocp";
+ tx-fifo-depth = <32768>;
+ rx-fifo-depth = <16384>;
+ altr,sysmgr-syscon = <&sysmgr 0x44 0>;
+ clocks = <&clkmgr AGILEX5_EMAC0_CLK>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+ };
+
+ gmac1: ethernet@10820000 {
+ compatible = "intel,socfpga-dwxgmac", "snps,dwxgmac-2.10", "snps,dwxgmac";
+ reg = <0x10820000 0x3500>;
+ interrupts = <0 207 4>;
+ interrupt-names = "macirq";
+ resets = <&rst EMAC1_RESET>, <&rst EMAC1_OCP_RESET>;
+ reset-names = "stmmaceth", "stmmaceth-ocp";
+ tx-fifo-depth = <32768>;
+ rx-fifo-depth = <16384>;
+ altr,sysmgr-syscon = <&sysmgr 0x48 0>;
+ clocks = <&clkmgr AGILEX5_EMAC1_CLK>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+ };
+
+ gmac2: ethernet@10830000 {
+ compatible = "intel,socfpga-dwxgmac", "snps,dwxgmac-2.10", "snps,dwxgmac";
+ reg = <0x10830000 0x3500>;
+ interrupts = <0 224 4>;
+ interrupt-names = "macirq";
+ resets = <&rst EMAC2_RESET>, <&rst EMAC2_OCP_RESET>;
+ reset-names = "stmmaceth", "stmmaceth-ocp";
+ tx-fifo-depth = <32768>;
+ rx-fifo-depth = <16384>;
+ altr,sysmgr-syscon = <&sysmgr 0x4c 0>;
+ clocks = <&clkmgr AGILEX5_EMAC2_CLK>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+ };
+
+ gpio0: gpio@10c03200 {
+ compatible = "snps,dw-apb-gpio";
+ reg = <0x10c03200 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ resets = <&rst GPIO0_RESET>;
+ status = "disabled";
+
+ porta: gpio-controller@0 {
+ compatible = "snps,dw-apb-gpio-port";
+ reg = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ snps,nr-gpios = <24>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+};
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index 80a15377b2e4be4d1386904a298a9aadcffbab00..f0dce3bad0429d38840975a2f3c3640731e7a605 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -4,13 +4,17 @@ if ARCH_SOCFPGA
config ARCH_SOCFPGA_XLOAD
bool
- prompt "Build preloader image"
+ depends on ARCH_SOCFPGA_CYCLONE5
+ prompt "Build SoCFPGA preloader image"
-comment "Altera SoCFPGA System-on-Chip"
+menu "SoCFPGA boards"
+
+if 32BIT
config ARCH_SOCFPGA_CYCLONE5
bool
select CPU_V7
+ select ARM_SMP_TWD
select OFDEVICE if !ARCH_SOCFPGA_XLOAD
select OFTREE if !ARCH_SOCFPGA_XLOAD
select GPIOLIB if !ARCH_SOCFPGA_XLOAD
@@ -18,13 +22,12 @@ config ARCH_SOCFPGA_CYCLONE5
config ARCH_SOCFPGA_ARRIA10
bool
select CPU_V7
+ select ARM_SMP_TWD
select ARM_USE_COMPRESSED_DTB
select RESET_CONTROLLER
select OFDEVICE
select OFTREE
-if 32BIT
-
comment "Cyclone5 boards"
config MACH_SOCFPGA_ALTERA_SOCDK
@@ -58,4 +61,30 @@ config MACH_SOCFPGA_REFLEX_ACHILLES
bool "Reflex Achilles"
endif
+
+if 64BIT
+
+config ARCH_SOCFPGA_AGILEX5
+ bool
+ select CPU_V8
+ select ARM_USE_COMPRESSED_DTB
+ select RESET_CONTROLLER
+ select RESET_SIMPLE
+ select OFDEVICE
+ select OFTREE
+ select FIRMWARE_AGILEX5_ATF
+ select ARM_ATF
+ select ARM_SMCCC
+
+
+comment "SoCFPGA Agilex5 boards"
+
+config MACH_SOCFPGA_ARROW_AXE5_EAGLE
+ bool "Arrow AXE5 Eagle"
+ select ARCH_SOCFPGA_AGILEX5
+
+endif
+
+endmenu
+
endif
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
index 008dbc38877211fe1f317cb8eb660d8514611ddd..81934a3ded7fe6dcfb4c8ac26473a25a96560863 100644
--- a/arch/arm/mach-socfpga/Makefile
+++ b/arch/arm/mach-socfpga/Makefile
@@ -14,6 +14,19 @@ obj-pbl-$(CONFIG_ARCH_SOCFPGA_ARRIA10) += arria10-bootsource.o \
arria10-init.o \
arria10-sdram.o
+pbl-$(CONFIG_ARCH_SOCFPGA_AGILEX5) += soc64-system-manager.o \
+ soc64-wrap-handoff.o \
+ iossm_mailbox.o \
+ mailbox_s10.o \
+ agilex5-sdram.o \
+ agilex5-secreg.o \
+ agilex5-clock-manager.o \
+ atf.o
+
+obj-$(CONFIG_ARCH_SOCFPGA_AGILEX5) += secure_reg_helper.o \
+ mailbox_s10.o \
+ smc_api.o
+
ifdef CONFIG_ARCH_SOCFPGA_CYCLONE5
obj-$(CONFIG_ARCH_SOCFPGA_XLOAD) += xload.o
endif
diff --git a/arch/arm/mach-socfpga/agilex5-clock-manager.c b/arch/arm/mach-socfpga/agilex5-clock-manager.c
new file mode 100644
index 0000000000000000000000000000000000000000..2d5c742644396cad627643c2a4b422fecbf0eeac
--- /dev/null
+++ b/arch/arm/mach-socfpga/agilex5-clock-manager.c
@@ -0,0 +1,411 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2023 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <io.h>
+#include <asm/system.h>
+#include <dt-bindings/clock/agilex5-clock.h>
+#include <linux/bitops.h>
+#include <clock.h>
+#include <mach/socfpga/agilex5-clk.h>
+#include <mach/socfpga/generic.h>
+#include <mach/socfpga/soc64-handoff.h>
+#include <mach/socfpga/soc64-regs.h>
+
+#define MPIDR_AFF1_OFFSET 8
+#define MPIDR_AFF1_MASK 0x3
+#define CORE0 1
+#define CORE1 2
+#define CORE2 3
+#define CORE3 4
+
+/* Derived from l4_main_clk (PSS clock) */
+#define COUNTER_FREQUENCY_REAL 400000000
+
+struct socfpga_clk_plat {
+ void __iomem *regs;
+};
+
+static void cm_wait_for_lock(u32 mask)
+{
+ u32 inter_val;
+ u32 retry = 0;
+
+ do {
+ inter_val = readl(SOCFPGA_CLKMGR_ADDRESS + CLKMGR_STAT) & mask;
+ /* Wait for stable lock */
+ if (inter_val == mask)
+ retry++;
+ else
+ retry = 0;
+ if (retry >= 10)
+ break;
+ } while (1);
+}
+
+/* function to poll in the fsm busy bit */
+static void cm_wait_for_fsm(void)
+{
+ register u32 inter_val;
+
+ do {
+ inter_val = readl(SOCFPGA_CLKMGR_ADDRESS + CLKMGR_STAT) &
+ CLKMGR_STAT_BUSY;
+ } while (inter_val);
+}
+
+/*
+ * function to write the bypass register which requires a poll of the
+ * busy bit
+ */
+static void clk_write_bypass_mainpll(struct socfpga_clk_plat *plat, u32 val)
+{
+ CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_BYPASS);
+ cm_wait_for_fsm();
+}
+
+static void clk_write_bypass_perpll(struct socfpga_clk_plat *plat, u32 val)
+{
+ CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_BYPASS);
+ cm_wait_for_fsm();
+}
+
+/* function to write the ctrl register which requires a poll of the busy bit */
+static void clk_write_ctrl(struct socfpga_clk_plat *plat, u32 val)
+{
+ CM_REG_WRITEL(plat, val, CLKMGR_CTRL);
+ cm_wait_for_fsm();
+}
+
+#define MEMBUS_MAINPLL 0
+#define MEMBUS_PERPLL 1
+#define MEMBUS_TIMEOUT 1000
+
+#define MEMBUS_CLKSLICE_REG 0x27
+#define MEMBUS_SYNTHCALFOSC_INIT_CENTERFREQ_REG 0xb3
+#define MEMBUS_SYNTHPPM_WATCHDOGTMR_VF01_REG 0xe6
+#define MEMBUS_CALCLKSLICE0_DUTY_LOCOVR_REG 0x03
+#define MEMBUS_CALCLKSLICE1_DUTY_LOCOVR_REG 0x07
+
+static const struct {
+ u32 reg;
+ u32 val;
+ u32 mask;
+} membus_pll[] = {
+ {
+ MEMBUS_CLKSLICE_REG,
+ /*
+ * BIT[7:7]
+ * Enable source synchronous mode
+ */
+ BIT(7),
+ BIT(7)
+ },
+ {
+ MEMBUS_SYNTHCALFOSC_INIT_CENTERFREQ_REG,
+ /*
+ * BIT[0:0]
+ * Sets synthcalfosc_init_centerfreq=1 to limit overshoot
+ * frequency during lock
+ */
+ BIT(0),
+ BIT(0)
+ },
+ {
+ MEMBUS_SYNTHPPM_WATCHDOGTMR_VF01_REG,
+ /*
+ * BIT[0:0]
+ * Sets synthppm_watchdogtmr_vf0=1 to give the pll more time
+ * to settle before lock is asserted.
+ */
+ BIT(0),
+ BIT(0)
+ },
+ {
+ MEMBUS_CALCLKSLICE0_DUTY_LOCOVR_REG,
+ /*
+ * BIT[6:0]
+ * Centering duty cycle for clkslice0 output
+ */
+ 0x4a,
+ GENMASK(6, 0)
+ },
+ {
+ MEMBUS_CALCLKSLICE1_DUTY_LOCOVR_REG,
+ /*
+ * BIT[6:0]
+ * Centering duty cycle for clkslice1 output
+ */
+ 0x4a,
+ GENMASK(6, 0)
+ },
+};
+
+static int membus_wait_for_req(struct socfpga_clk_plat *plat, u32 pll,
+ int timeout)
+{
+ int cnt = 0;
+ u32 req_status;
+
+ if (pll == MEMBUS_MAINPLL)
+ req_status = CM_REG_READL(plat, CLKMGR_MAINPLL_MEM);
+ else
+ req_status = CM_REG_READL(plat, CLKMGR_PERPLL_MEM);
+
+ while ((cnt < timeout) && (req_status & CLKMGR_MEM_REQ_SET_MSK)) {
+ if (pll == MEMBUS_MAINPLL)
+ req_status = CM_REG_READL(plat, CLKMGR_MAINPLL_MEM);
+ else
+ req_status = CM_REG_READL(plat, CLKMGR_PERPLL_MEM);
+ cnt++;
+ }
+
+ if (cnt >= timeout)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int membus_write_pll(struct socfpga_clk_plat *plat, u32 pll,
+ u32 addr_offset, u32 wdat, int timeout)
+{
+ u32 addr;
+ u32 val;
+
+ addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK);
+
+ val = (CLKMGR_MEM_REQ_SET_MSK | CLKMGR_MEM_WR_SET_MSK |
+ (wdat << CLKMGR_MEM_WDAT_LSB_OFFSET) | addr);
+
+ if (pll == MEMBUS_MAINPLL)
+ CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_MEM);
+ else
+ CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_MEM);
+
+ return membus_wait_for_req(plat, pll, timeout);
+}
+
+static int membus_read_pll(struct socfpga_clk_plat *plat, u32 pll,
+ u32 addr_offset, u32 *rdata, int timeout)
+{
+ u32 addr;
+ u32 val;
+
+ addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK);
+
+ val = ((CLKMGR_MEM_REQ_SET_MSK & ~CLKMGR_MEM_WR_SET_MSK) | addr);
+
+ if (pll == MEMBUS_MAINPLL)
+ CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_MEM);
+ else
+ CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_MEM);
+
+ *rdata = 0;
+
+ if (membus_wait_for_req(plat, pll, timeout))
+ return -ETIMEDOUT;
+
+ if (pll == MEMBUS_MAINPLL)
+ *rdata = CM_REG_READL(plat, CLKMGR_MAINPLL_MEMSTAT);
+ else
+ *rdata = CM_REG_READL(plat, CLKMGR_PERPLL_MEMSTAT);
+
+ return 0;
+}
+
+static void membus_pll_configs(struct socfpga_clk_plat *plat, u32 pll)
+{
+ int i;
+ u32 rdata;
+
+ for (i = 0; i < ARRAY_SIZE(membus_pll); i++) {
+ membus_read_pll(plat, pll, membus_pll[i].reg,
+ &rdata, MEMBUS_TIMEOUT);
+ membus_write_pll(plat, pll, membus_pll[i].reg,
+ ((rdata & ~membus_pll[i].mask) | membus_pll[i].val),
+ MEMBUS_TIMEOUT);
+ }
+}
+
+static u32 calc_vocalib_pll(u32 pllm, u32 pllglob)
+{
+ u32 mdiv, refclkdiv, arefclkdiv, drefclkdiv, mscnt, hscnt, vcocalib;
+
+ mdiv = pllm & CLKMGR_PLLM_MDIV_MASK;
+ arefclkdiv = (pllglob & CLKMGR_PLLGLOB_AREFCLKDIV_MASK) >>
+ CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET;
+ drefclkdiv = (pllglob & CLKMGR_PLLGLOB_DREFCLKDIV_MASK) >>
+ CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET;
+ refclkdiv = (pllglob & CLKMGR_PLLGLOB_REFCLKDIV_MASK) >>
+ CLKMGR_PLLGLOB_REFCLKDIV_OFFSET;
+ mscnt = CLKMGR_VCOCALIB_MSCNT_CONST / (mdiv * BIT(drefclkdiv));
+ if (!mscnt)
+ mscnt = 1;
+ hscnt = (mdiv * mscnt * BIT(drefclkdiv) / refclkdiv) -
+ CLKMGR_VCOCALIB_HSCNT_CONST;
+ vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
+ ((mscnt << CLKMGR_VCOCALIB_MSCNT_OFFSET) &
+ CLKMGR_VCOCALIB_MSCNT_MASK);
+
+ return vcocalib;
+}
+
+/*
+ * Setup clocks while making no assumptions about previous state of the clocks.
+ */
+static void clk_basic_init(struct socfpga_clk_plat *plat,
+ const struct cm_config * const cfg)
+{
+ u32 vcocalib;
+ u32 cntfrq = COUNTER_FREQUENCY_REAL;
+ u32 counter_freq = 0;
+
+
+ if (!cfg)
+ return;
+
+ /* Always force clock manager into boot mode before any configuration */
+ clk_write_ctrl(plat,
+ CM_REG_READL(plat, CLKMGR_CTRL) | CLKMGR_CTRL_BOOTMODE);
+
+ /* Put both PLLs in bypass */
+ clk_write_bypass_mainpll(plat, CLKMGR_BYPASS_MAINPLL_ALL);
+ clk_write_bypass_perpll(plat, CLKMGR_BYPASS_PERPLL_ALL);
+
+ /* Put both PLLs in Reset and Power Down */
+ CM_REG_CLRBITS(plat, CLKMGR_MAINPLL_PLLGLOB,
+ CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
+ CM_REG_CLRBITS(plat, CLKMGR_PERPLL_PLLGLOB,
+ CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
+
+ /* setup main PLL dividers where calculate the vcocalib value */
+ vcocalib = calc_vocalib_pll(cfg->main_pll_pllm, cfg->main_pll_pllglob);
+ CM_REG_WRITEL(plat, cfg->main_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK,
+ CLKMGR_MAINPLL_PLLGLOB);
+ CM_REG_WRITEL(plat, cfg->main_pll_fdbck, CLKMGR_MAINPLL_FDBCK);
+ CM_REG_WRITEL(plat, vcocalib, CLKMGR_MAINPLL_VCOCALIB);
+ CM_REG_WRITEL(plat, cfg->main_pll_pllc0, CLKMGR_MAINPLL_PLLC0);
+ CM_REG_WRITEL(plat, cfg->main_pll_pllc1, CLKMGR_MAINPLL_PLLC1);
+ CM_REG_WRITEL(plat, cfg->main_pll_pllc2, CLKMGR_MAINPLL_PLLC2);
+ CM_REG_WRITEL(plat, cfg->main_pll_pllc3, CLKMGR_MAINPLL_PLLC3);
+ CM_REG_WRITEL(plat, cfg->main_pll_pllm, CLKMGR_MAINPLL_PLLM);
+ CM_REG_WRITEL(plat, cfg->main_pll_nocclk, CLKMGR_MAINPLL_NOCCLK);
+ CM_REG_WRITEL(plat, cfg->main_pll_nocdiv, CLKMGR_MAINPLL_NOCDIV);
+
+ /* setup peripheral PLL dividers where calculate the vcocalib value */
+ vcocalib = calc_vocalib_pll(cfg->per_pll_pllm, cfg->per_pll_pllglob);
+ CM_REG_WRITEL(plat, cfg->per_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK,
+ CLKMGR_PERPLL_PLLGLOB);
+ CM_REG_WRITEL(plat, cfg->per_pll_fdbck, CLKMGR_PERPLL_FDBCK);
+ CM_REG_WRITEL(plat, vcocalib, CLKMGR_PERPLL_VCOCALIB);
+ CM_REG_WRITEL(plat, cfg->per_pll_pllc0, CLKMGR_PERPLL_PLLC0);
+ CM_REG_WRITEL(plat, cfg->per_pll_pllc1, CLKMGR_PERPLL_PLLC1);
+ CM_REG_WRITEL(plat, cfg->per_pll_pllc2, CLKMGR_PERPLL_PLLC2);
+ CM_REG_WRITEL(plat, cfg->per_pll_pllc3, CLKMGR_PERPLL_PLLC3);
+ CM_REG_WRITEL(plat, cfg->per_pll_pllm, CLKMGR_PERPLL_PLLM);
+ CM_REG_WRITEL(plat, cfg->per_pll_emacctl, CLKMGR_PERPLL_EMACCTL);
+ CM_REG_WRITEL(plat, cfg->per_pll_gpiodiv, CLKMGR_PERPLL_GPIODIV);
+
+ /* Configure ping pong counters in control group */
+ CM_REG_WRITEL(plat, cfg->ctl_emacactr, CLKMGR_CTL_EMACACTR);
+ CM_REG_WRITEL(plat, cfg->ctl_emacbctr, CLKMGR_CTL_EMACBCTR);
+ CM_REG_WRITEL(plat, cfg->ctl_emacptpctr, CLKMGR_CTL_EMACPTPCTR);
+ CM_REG_WRITEL(plat, cfg->ctl_gpiodbctr, CLKMGR_CTL_GPIODBCTR);
+ CM_REG_WRITEL(plat, cfg->ctl_s2fuser0ctr, CLKMGR_CTL_S2FUSER0CTR);
+ CM_REG_WRITEL(plat, cfg->ctl_s2fuser1ctr, CLKMGR_CTL_S2FUSER1CTR);
+ CM_REG_WRITEL(plat, cfg->ctl_psirefctr, CLKMGR_CTL_PSIREFCTR);
+ CM_REG_WRITEL(plat, cfg->ctl_usb31ctr, CLKMGR_CTL_USB31CTR);
+ CM_REG_WRITEL(plat, cfg->ctl_dsuctr, CLKMGR_CTL_DSUCTR);
+ CM_REG_WRITEL(plat, cfg->ctl_core01ctr, CLKMGR_CTL_CORE01CTR);
+ CM_REG_WRITEL(plat, cfg->ctl_core23ctr, CLKMGR_CTL_CORE23CTR);
+ CM_REG_WRITEL(plat, cfg->ctl_core2ctr, CLKMGR_CTL_CORE2CTR);
+ CM_REG_WRITEL(plat, cfg->ctl_core3ctr, CLKMGR_CTL_CORE3CTR);
+
+ /* Take both PLL out of reset and power up */
+ CM_REG_SETBITS(plat, CLKMGR_MAINPLL_PLLGLOB,
+ CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
+ CM_REG_SETBITS(plat, CLKMGR_PERPLL_PLLGLOB,
+ CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
+
+ /* Membus programming for mainpll */
+ membus_pll_configs(plat, MEMBUS_MAINPLL);
+ /* Membus programming for peripll */
+ membus_pll_configs(plat, MEMBUS_PERPLL);
+
+ /* Enable Main pll clkslices */
+ CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC0) |
+ CLKMGR_PLLCX_EN_SET_MSK,
+ CLKMGR_MAINPLL_PLLC0);
+ CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC1) |
+ CLKMGR_PLLCX_EN_SET_MSK,
+ CLKMGR_MAINPLL_PLLC1);
+ CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC2) |
+ CLKMGR_PLLCX_EN_SET_MSK,
+ CLKMGR_MAINPLL_PLLC2);
+ CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC3) |
+ CLKMGR_PLLCX_EN_SET_MSK,
+ CLKMGR_MAINPLL_PLLC3);
+
+ /* Enable Periph pll clkslices */
+ CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLC0) |
+ CLKMGR_PLLCX_EN_SET_MSK,
+ CLKMGR_PERPLL_PLLC0);
+ CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLC1) |
+ CLKMGR_PLLCX_EN_SET_MSK,
+ CLKMGR_PERPLL_PLLC1);
+ CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLC2) |
+ CLKMGR_PLLCX_EN_SET_MSK,
+ CLKMGR_PERPLL_PLLC2);
+ CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLC3) |
+ CLKMGR_PLLCX_EN_SET_MSK,
+ CLKMGR_PERPLL_PLLC3);
+
+ cm_wait_for_lock(CLKMGR_STAT_ALLPLL_LOCKED_MASK);
+
+ CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_MAINPLL_LOSTLOCK);
+ CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_PERPLL_LOSTLOCK);
+
+ CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLGLOB) |
+ CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
+ CLKMGR_MAINPLL_PLLGLOB);
+ CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLGLOB) |
+ CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
+ CLKMGR_PERPLL_PLLGLOB);
+
+ /* Take all PLLs out of bypass */
+ clk_write_bypass_mainpll(plat, 0);
+ clk_write_bypass_perpll(plat, 0);
+
+ /* Clear the loss of lock bits (write 1 to clear) */
+ CM_REG_CLRBITS(plat, CLKMGR_INTRCLR,
+ CLKMGR_INTER_PERPLLLOST_MASK |
+ CLKMGR_INTER_MAINPLLLOST_MASK);
+
+ /* Take all ping pong counters out of reset */
+ CM_REG_CLRBITS(plat, CLKMGR_CTL_EXTCNTRST,
+ CLKMGR_CTL_EXTCNTRST_ALLCNTRST);
+
+ /* Update with accurate clock frequency */
+ if (current_el() == 3) {
+ asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory");
+ asm volatile("mrs %0, cntfrq_el0" : "=r" (counter_freq));
+ }
+
+ /* Out of boot mode */
+ clk_write_ctrl(plat, CM_REG_READL(plat, CLKMGR_CTRL) &
+ ~CLKMGR_CTRL_BOOTMODE);
+}
+
+int agilex5_clk_init(void)
+{
+ struct socfpga_clk_plat plat;
+ const struct cm_config *cm_default_cfg = cm_get_default_config();
+
+ plat.regs = (void __iomem *)SOCFPGA_CLKMGR_ADDRESS;
+
+ clk_basic_init(&plat, cm_default_cfg);
+
+ return 0;
+}
diff --git a/arch/arm/mach-socfpga/agilex5-sdram.c b/arch/arm/mach-socfpga/agilex5-sdram.c
new file mode 100644
index 0000000000000000000000000000000000000000..4e1b03f400add0ebeab038716b1c02e8a228f237
--- /dev/null
+++ b/arch/arm/mach-socfpga/agilex5-sdram.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2024 Intel Corporation <www.intel.com>
+ *
+ */
+#include <common.h>
+#include <errno.h>
+#include "iossm_mailbox.h"
+#include <xfuncs.h>
+#include <linux/sizes.h>
+#include <linux/bitfield.h>
+#include <mach/socfpga/soc64-firewall.h>
+#include <mach/socfpga/soc64-handoff.h>
+#include <mach/socfpga/soc64-regs.h>
+#include <mach/socfpga/soc64-sdram.h>
+#include <mach/socfpga/soc64-system-manager.h>
+
+/* MPFE NOC registers */
+#define F2SDRAM_SIDEBAND_FLAGOUTSET0 0x50
+#define F2SDRAM_SIDEBAND_FLAGOUTSTATUS0 0x58
+#define SIDEBANDMGR_FLAGOUTSET0_REG SOCFPGA_F2SDRAM_MGR_ADDRESS +\
+ F2SDRAM_SIDEBAND_FLAGOUTSET0
+#define SIDEBANDMGR_FLAGOUTSTATUS0_REG SOCFPGA_F2SDRAM_MGR_ADDRESS +\
+ F2SDRAM_SIDEBAND_FLAGOUTSTATUS0
+
+#define PORT_EMIF_CONFIG_OFFSET 4
+
+/* Reset type */
+enum reset_type {
+ POR_RESET,
+ WARM_RESET,
+ COLD_RESET,
+ NCONFIG,
+ JTAG_CONFIG,
+ RSU_RECONFIG
+};
+
+phys_addr_t io96b_csr_reg_addr[] = {
+ 0x18400000, /* IO96B_0 CSR registers address */
+ 0x18800000 /* IO96B_1 CSR registers address */
+};
+
+static enum reset_type get_reset_type(u32 reg)
+{
+ return (reg & ALT_SYSMGR_SCRATCH_REG_3_DDR_RESET_TYPE_MASK) >>
+ ALT_SYSMGR_SCRATCH_REG_3_DDR_RESET_TYPE_SHIFT;
+}
+
+static int set_mpfe_config(void)
+{
+ /* Set mpfe_lite_intfcsel */
+ setbits_le32(IOMEM(SOCFPGA_SYSMGR_ADDRESS) + SYSMGR_SOC64_MPFE_CONFIG, BIT(2));
+
+ /* Set mpfe_lite_active */
+ setbits_le32(IOMEM(SOCFPGA_SYSMGR_ADDRESS) + SYSMGR_SOC64_MPFE_CONFIG, BIT(8));
+
+ pr_debug("%s: mpfe_config: 0x%x\n", __func__,
+ readl(IOMEM(SOCFPGA_SYSMGR_ADDRESS) + SYSMGR_SOC64_MPFE_CONFIG));
+
+ return 0;
+}
+
+static bool is_ddr_init_hang(void)
+{
+ u32 reg = readl(IOMEM(SOCFPGA_SYSMGR_ADDRESS) +
+ SYSMGR_SOC64_BOOT_SCRATCH_POR0);
+
+ if (reg & ALT_SYSMGR_SCRATCH_REG_POR_0_DDR_PROGRESS_MASK)
+ return true;
+
+ return false;
+}
+
+static void ddr_init_inprogress(bool start)
+{
+ if (start)
+ setbits_le32(IOMEM(SOCFPGA_SYSMGR_ADDRESS) +
+ SYSMGR_SOC64_BOOT_SCRATCH_POR0,
+ ALT_SYSMGR_SCRATCH_REG_POR_0_DDR_PROGRESS_MASK);
+ else
+ clrbits_le32(IOMEM(SOCFPGA_SYSMGR_ADDRESS) +
+ SYSMGR_SOC64_BOOT_SCRATCH_POR0,
+ ALT_SYSMGR_SCRATCH_REG_POR_0_DDR_PROGRESS_MASK);
+}
+
+static int populate_ddr_handoff(struct altera_sdram_plat *plat, struct io96b_info *io96b_ctrl)
+{
+ int i;
+ u32 len = SOC64_HANDOFF_SDRAM_LEN;
+ u32 handoff_table[len];
+
+ /* Read handoff for DDR configuration */
+ socfpga_handoff_read((void *)SOC64_HANDOFF_SDRAM, handoff_table, len);
+
+ /* Read handoff - dual port
+ FIXME: Intel u-boot has a patch that HACKs this to 0
+ https://github.com/altera-opensource/meta-intel-fpga-refdes/ \
+ blob/master/recipes-bsp/u-boot/files/v1-0001-HSD-15015933655-ddr-altera-agilex5-Hack-dual-port-DO-NOT-MERGE.patch
+ Patch doesn't say why or what is broken here: handoff files? dualport RAM access?
+ */
+ //plat->dualport = FIELD_GET(BIT(0), handoff_table[PORT_EMIF_CONFIG_OFFSET]);
+ plat->dualport = 0;
+ pr_debug("%s: dualport from handoff: 0x%x\n", __func__, plat->dualport);
+
+ if (plat->dualport)
+ io96b_ctrl->num_port = 2;
+ else
+ io96b_ctrl->num_port = 1;
+
+ /* Read handoff - dual EMIF */
+ plat->dualemif = FIELD_GET(BIT(1), handoff_table[PORT_EMIF_CONFIG_OFFSET]);
+ pr_debug("%s: dualemif from handoff: 0x%x\n", __func__, plat->dualemif);
+
+ if (plat->dualemif)
+ io96b_ctrl->num_instance = 2;
+ else
+ io96b_ctrl->num_instance = 1;
+
+ /* Assign IO96B CSR base address if it is valid */
+ for (i = 0; i < io96b_ctrl->num_instance; i++) {
+ io96b_ctrl->io96b[i].io96b_csr_addr = io96b_csr_reg_addr[i];
+ pr_debug("%s: IO96B 0x%llx CSR enabled\n", __func__
+ , io96b_ctrl->io96b[i].io96b_csr_addr);
+ }
+
+ return 0;
+}
+
+static int config_mpfe_sideband_mgr(struct altera_sdram_plat *plat)
+{
+ /* Dual port setting */
+ if (plat->dualport)
+ setbits_le32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(4));
+
+ /* Dual EMIF setting */
+ if (plat->dualemif) {
+ set_mpfe_config();
+ setbits_le32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(5));
+ }
+
+ pr_debug("%s: SIDEBANDMGR_FLAGOUTSTATUS0: 0x%x\n", __func__,
+ readl(SIDEBANDMGR_FLAGOUTSTATUS0_REG));
+
+ return 0;
+}
+
+static void config_ccu_mgr(struct altera_sdram_plat *plat)
+{
+ int ret = 0;
+
+ if (plat->dualport || plat->dualemif) {
+ pr_debug("%s: config interleaving on ccu reg\n", __func__);
+ agilex5_security_interleaving_on();
+ } else {
+ pr_debug("%s: config interleaving off ccu reg\n", __func__);
+ agilex5_security_interleaving_off();
+ }
+
+ if (ret) {
+ printf("interleaving on/off ccu settings init failed: %d\n", ret);
+ hang();
+ }
+}
+
+static bool hps_ocram_dbe_status(void)
+{
+ u32 reg = readl(IOMEM(SOCFPGA_SYSMGR_ADDRESS) +
+ SYSMGR_SOC64_BOOT_SCRATCH_COLD3);
+
+ if (reg & ALT_SYSMGR_SCRATCH_REG_3_OCRAM_DBE_MASK)
+ return true;
+
+ return false;
+}
+
+static bool ddr_ecc_dbe_status(void)
+{
+ u32 reg = readl(IOMEM(SOCFPGA_SYSMGR_ADDRESS) +
+ SYSMGR_SOC64_BOOT_SCRATCH_COLD3);
+
+ if (reg & ALT_SYSMGR_SCRATCH_REG_3_DDR_DBE_MASK)
+ return true;
+
+ return false;
+}
+
+static void sdram_set_firewall(phys_size_t hw_size)
+{
+ phys_size_t value;
+ u32 lower, upper;
+
+ value = SOCFPGA_AGILEX5_DDR_BASE;
+ /* Keep first 1MB of SDRAM memory region as secure region when
+ * using ATF flow, where the ATF code is located.
+ */
+ value += SZ_1M;
+
+ /* Setting non-secure MPU region base and base extended */
+ lower = lower_32_bits(value);
+ upper = upper_32_bits(value);
+ FW_MPU_DDR_SCR_WRITEL(lower, FW_MPU_DDR_SCR_MPUREGION0ADDR_BASE);
+ FW_MPU_DDR_SCR_WRITEL(upper & 0xff, FW_MPU_DDR_SCR_MPUREGION0ADDR_BASEEXT);
+ FW_F2SDRAM_DDR_SCR_WRITEL(lower, FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASE);
+ FW_F2SDRAM_DDR_SCR_WRITEL(upper & 0xff, FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASEEXT);
+
+ /* Setting non-secure Non-MPU region base and base extended */
+ FW_MPU_DDR_SCR_WRITEL(lower, FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASE);
+ FW_MPU_DDR_SCR_WRITEL(upper & 0xff, FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT);
+
+ /* Setting non-secure MPU limit and limit extended */
+ value = SOCFPGA_AGILEX5_DDR_BASE + hw_size - 1;
+
+ lower = lower_32_bits(value);
+ upper = upper_32_bits(value);
+
+ FW_MPU_DDR_SCR_WRITEL(lower, FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT);
+ FW_MPU_DDR_SCR_WRITEL(upper & 0xff, FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT);
+
+ /* Setting non-secure Non-MPU limit and limit extended */
+ FW_MPU_DDR_SCR_WRITEL(lower, FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT);
+ FW_MPU_DDR_SCR_WRITEL(upper & 0xff, FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT);
+ FW_MPU_DDR_SCR_WRITEL(BIT(0) | BIT(8), FW_MPU_DDR_SCR_EN_SET);
+
+ FW_F2SDRAM_DDR_SCR_WRITEL(lower, FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMIT);
+ FW_F2SDRAM_DDR_SCR_WRITEL(upper & 0xff, FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMITEXT);
+ FW_F2SDRAM_DDR_SCR_WRITEL(BIT(0), FW_F2SDRAM_DDR_SCR_EN_SET);
+}
+
+int agilex5_ddr_init_full(void)
+{
+ int ret;
+ int i;
+ phys_size_t hw_size;
+ struct altera_sdram_plat plat;
+ struct io96b_info io96b_ctrl;
+
+ enum reset_type reset_t = get_reset_type(SOCFPGA_SYSMGR_ADDRESS +
+ SYSMGR_SOC64_BOOT_SCRATCH_COLD3);
+ bool full_mem_init = false;
+
+ /* DDR initialization progress status tracking */
+ bool is_ddr_hang_be4_rst = is_ddr_init_hang();
+
+ pr_debug("DDR: SDRAM init in progress ...\n");
+ ddr_init_inprogress(true);
+
+ plat.mpfe_base_addr = IOMEM(SOCFPGA_MPFE_CSR_ADDRESS);
+
+ pr_debug("DDR: Address MPFE 0x%p\n", plat.mpfe_base_addr);
+
+ /* Populating DDR handoff data */
+ pr_debug("DDR: Checking SDRAM configuration in progress ...\n");
+ ret = populate_ddr_handoff(&plat, &io96b_ctrl);
+ if (ret) {
+ pr_debug("DDR: Failed to populate DDR handoff\n");
+ return ret;
+ }
+
+ /* Configuring MPFE sideband manager registers - dual port & dual emif*/
+ ret = config_mpfe_sideband_mgr(&plat);
+ if (ret) {
+ pr_debug("DDR: Failed to configure dual port dual emif\n");
+ return ret;
+ }
+
+ /* Configuring Interleave/Non-interleave ccu registers */
+ config_ccu_mgr(&plat);
+
+ /* Configure if polling is needed for IO96B GEN PLL locked */
+ io96b_ctrl.ckgen_lock = true;
+
+ /* Ensure calibration status passing */
+ init_mem_cal(&io96b_ctrl);
+
+ /* Initiate IOSSM mailbox */
+ io96b_mb_init(&io96b_ctrl);
+
+ /* Need to trigger re-calibration for DDR DBE */
+ if (ddr_ecc_dbe_status()) {
+ for (i = 0; i < io96b_ctrl.num_instance; i++)
+ io96b_ctrl.io96b[i].cal_status = false;
+
+ io96b_ctrl.overall_cal_status = false;
+ }
+
+ /* Trigger re-calibration if calibration failed */
+ if (!(io96b_ctrl.overall_cal_status)) {
+ pr_debug("DDR: Re-calibration in progress...\n");
+ trig_mem_cal(&io96b_ctrl);
+ }
+
+ pr_debug("DDR: Calibration success\n");
+
+ /* DDR type, DDR size and ECC status) */
+ ret = get_mem_technology(&io96b_ctrl);
+ if (ret) {
+ pr_debug("DDR: Failed to get DDR type\n");
+ return ret;
+ }
+
+ ret = get_mem_width_info(&io96b_ctrl);
+ if (ret) {
+ pr_debug("DDR: Failed to get DDR size\n");
+ return ret;
+ }
+
+ hw_size = (phys_size_t)io96b_ctrl.overall_size * SZ_1G / SZ_8;
+
+ pr_debug("%s: %lld MiB\n", io96b_ctrl.ddr_type, hw_size >> 20);
+
+ ret = ecc_enable_status(&io96b_ctrl);
+ if (ret) {
+ pr_debug("DDR: Failed to get DDR ECC status\n");
+ return ret;
+ }
+
+ /* Is HPS cold or warm reset? If yes, Skip full memory initialization if ECC
+ * enabled to preserve memory content
+ */
+ if (io96b_ctrl.ecc_status) {
+ full_mem_init = hps_ocram_dbe_status() | ddr_ecc_dbe_status() |
+ is_ddr_hang_be4_rst;
+ if (full_mem_init || !(reset_t == WARM_RESET || reset_t == COLD_RESET)) {
+ ret = bist_mem_init_start(&io96b_ctrl);
+ if (ret) {
+ pr_debug("DDR: Failed to fully initialize DDR memory\n");
+ return ret;
+ }
+ }
+
+ pr_debug("SDRAM-ECC: Initialized success\n");
+ }
+
+ sdram_set_firewall(hw_size);
+
+ /* Firewall setting for MPFE CSR */
+ /* IO96B0_reg */
+ writel(0x1, 0x18000d00);
+ /* IO96B1_reg */
+ writel(0x1, 0x18000d04);
+ /* noc_csr */
+ writel(0x1, 0x18000d08);
+
+ pr_debug("DDR: firewall init success\n");
+
+ /* Ending DDR driver initialization success tracking */
+ ddr_init_inprogress(false);
+
+ pr_debug("DDR: init success\n");
+
+ return 0;
+}
diff --git a/arch/arm/mach-socfpga/agilex5-secreg.c b/arch/arm/mach-socfpga/agilex5-secreg.c
new file mode 100644
index 0000000000000000000000000000000000000000..042ba10db71c6fbd4a7d164603d3a3600b9ccc1a
--- /dev/null
+++ b/arch/arm/mach-socfpga/agilex5-secreg.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <common.h>
+#include <io.h>
+#include <mach/socfpga/debug_ll.h>
+#include <mach/socfpga/soc64-regs.h>
+#include <mach/socfpga/soc64-system-manager.h>
+
+#define BUILD_SOC64_WRITE_SECREG(name, addr) \
+ static inline void soc64_write_##name(const int offset, \
+ const int val, \
+ const int mask) \
+ { \
+ void __iomem *iomem = IOMEM(addr); \
+ soc64_set(iomem, offset, val, mask); \
+ }
+
+static inline void soc64_set(void __iomem *addr, int offset, u32 val, int mask)
+{
+ u32 set_mask;
+
+ if (mask == 0xffffffff)
+ writel(val, addr + offset);
+ else {
+ set_mask = mask & val;
+
+ clrsetbits_le32(addr + offset, mask, set_mask);
+ }
+
+ pr_debug("%s: set 0x%p = 0x%08x & 0x%08x\n", __func__,
+ addr + offset, val, mask);
+}
+
+BUILD_SOC64_WRITE_SECREG(ccu, SOCFPGA_CCU_ADDRESS)
+BUILD_SOC64_WRITE_SECREG(dce0, SOCFPGA_DCE0_ADDRESS)
+BUILD_SOC64_WRITE_SECREG(dce1, SOCFPGA_DCE1_ADDRESS)
+BUILD_SOC64_WRITE_SECREG(dmi0, SOCFPGA_DMI0_ADDRESS)
+BUILD_SOC64_WRITE_SECREG(dmi1, SOCFPGA_DMI1_ADDRESS)
+BUILD_SOC64_WRITE_SECREG(fpga2soc, SOCFPGA_FPGA2SOC_ADDRESS)
+BUILD_SOC64_WRITE_SECREG(gic_m, SOCFPGA_GIC_M_ADDRESS)
+BUILD_SOC64_WRITE_SECREG(iom, SOCFPGA_CCU_IOM_ADDRESS)
+BUILD_SOC64_WRITE_SECREG(l4_per, SOCFPGA_FIREWALL_L4_PER_ADDRESS)
+BUILD_SOC64_WRITE_SECREG(l4_sys, SOCFPGA_FIREWALL_L4_SYS_ADDRESS)
+BUILD_SOC64_WRITE_SECREG(tcu, SOCFPGA_TCU_ADDRESS)
+
+void agilex5_security_interleaving_off(void)
+{
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 3, 0x1f);
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81300006, 0xc1f03e1f);
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81700006, 0xc1f03e1f);
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81b00006, 0xc1f03e1f);
+
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 3, 0x1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81300006, 0xc1f03e1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81700006, 0xc1f03e1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81b00006, 0xc1f03e1f);
+
+ soc64_write_gic_m(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 3, 0x1f);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81300006, 0xc1f03e1f);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81700006, 0xc1f03e1f);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81b00006, 0xc1f03e1f);
+
+ soc64_write_tcu(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 3, 0x1f);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81300006, 0xc1f03e1f);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81700006, 0xc1f03e1f);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81b00006, 0xc1f03e1f);
+
+ soc64_write_iom(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 3, 0x1f);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81300006, 0xc1f03e1f);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81700006, 0xc1f03e1f);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81b00006, 0xc1f03e1f);
+
+ soc64_write_dce0(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 3, 0x1f);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81300006, 0xc1f03e1f);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81700006, 0xc1f03e1f);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81b00006, 0xc1f03e1f);
+
+ soc64_write_dce1(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 3, 0x1f);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81300006, 0xc1f03e1f);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81700006, 0xc1f03e1f);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81b00006, 0xc1f03e1f);
+}
+
+void agilex5_security_interleaving_on(void)
+{
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 1, 0x1f);
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81200006, 0xc1f03e1f);
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81600006, 0xc1f03e1f);
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81a00006, 0xc1f03e1f);
+
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 1, 0x1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81200006, 0xc1f03e1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81600006, 0xc1f03e1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81a00006, 0xc1f03e1f);
+
+ soc64_write_gic_m(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 1, 0x1f);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81200006, 0xc1f03e1f);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81600006, 0xc1f03e1f);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81a00006, 0xc1f03e1f);
+
+ soc64_write_tcu(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 1, 0x1f);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81200006, 0xc1f03e1f);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81600006, 0xc1f03e1f);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81a00006, 0xc1f03e1f);
+
+ soc64_write_iom(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 1, 0x1f);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81200006, 0xc1f03e1f);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81600006, 0xc1f03e1f);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81a00006, 0xc1f03e1f);
+
+ soc64_write_dce0(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 1, 0x1f);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81200006, 0xc1f03e1f);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81600006, 0xc1f03e1f);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81a00006, 0xc1f03e1f);
+
+ soc64_write_dce1(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 1, 0x1f);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG, 0x81200006, 0xc1f03e1f);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG, 0x81600006, 0xc1f03e1f);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG, 0x81a00006, 0xc1f03e1f);
+}
+
+void agilex5_initialize_security_policies(void)
+{
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU1AMIGR_REG, 0, 0x07070777);
+ soc64_write_ccu(SOCFPGA_SECREG_DII1_MPFE_LR_REG, 0x18000, 0xffffffff);
+ soc64_write_ccu(SOCFPGA_SECREG_DII1_MPFE_HR_REG, 0, 0xff);
+ soc64_write_ccu(SOCFPGA_SECREG_DII1_MPFE_BAR_REG, 0xc0e00200, 0xc1f03e1f);
+ soc64_write_ccu(SOCFPGA_CCU_DII2_GIC_LR_REG, 0x1d000, 0xffffffff);
+ soc64_write_ccu(SOCFPGA_CCU_DII2_GIC_HR_REG, 0, 0xff);
+ soc64_write_ccu(SOCFPGA_CCU_DII2_GIC_BAR_REG, 0xc0800400, 0xc1f03e1f);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_LWSOC2FPGA_LR_REG, 0x20000, 0xffffffff);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_LWSOC2FPGA_HR_REG, 0, 0xff);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_LWSOC2FPGA_BAR_REG, 0xc1100006, 0xc1f03e1f);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_1G_LR_REG, 0x40000, 0xffffffff);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_1G_HR_REG, 0, 0xff);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_1G_BAR_REG, 0xc1200006, 0xc1f03e1f);
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_2G_LR_REG, 0x80000, 0xffffffff);
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_2G_HR_REG, 0, 0xff);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_16G_LR_REG, 0x400000, 0xffffffff);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_16G_HR_REG, 0, 0xff);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_16G_BAR_REG, 0xc1600006, 0xc1f03e1f);
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_30G_LR_REG, 0x800000, 0xffffffff);
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_30G_HR_REG, 0, 0xff);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_256G_LR_REG, 0x4000000, 0xffffff);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_256G_HR_REG, 0, 0xff);
+ soc64_write_ccu(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_256G_BAR_REG, 0x6, 0xf); //
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_480G_LR_REG, 0x8000000, 0xffffffff);
+ soc64_write_ccu(SOCFPGA_SECREG_DMI_SDRAM_480G_HR_REG, 0, 0xff);
+
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU1MIFSR_REG, 0, 0x7070777);
+ soc64_write_fpga2soc(SOCFPGA_FPGA2SOC_PSS_LR_REG, 0x10000, 0xffffffff);
+ soc64_write_fpga2soc(SOCFPGA_FPGA2SOC_PSS_HR_REG, 0, 0xff);
+ soc64_write_fpga2soc(SOCFPGA_FPGA2SOC_PSS_BAR_REG, 0xc0f00000, 0xc1f03e1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DII1_MPFE_LR_REG, 0x18000, 0xffffffff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DII1_MPFE_HR_REG, 0, 0xff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DII1_MPFE_BAR_REG, 0xc0e00200, 0xc1f03e1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_LWSOC2FPGA_BAR_REG, 0x20000, 0xffffffff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_LWSOC2FPGA_LR_REG, 0, 0xff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_LWSOC2FPGA_HR_REG, 0xc1100006, 0xc1f03e1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_1G_LR_REG, 0x40000, 0xffffffff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_1G_HR_REG, 0, 0xff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_1G_BAR_REG, 0xc1200006, 0xc1f03e1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_2G_LR_REG, 0x80000, 0xffffffff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_2G_HR_REG, 0, 0xff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_16G_LR_REG, 0x400000, 0xffffffff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_16G_HR_REG, 0, 0xff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_16G_BAR_REG, 0xc1600006, 0xc1f03e1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_30G_LR_REG, 0x800000, 0xffffffff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_30G_HR_REG, 0, 0xff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_256G_LR_REG, 0x4000000, 0xffffffff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_256G_HR_REG, 0, 0xff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_NCAIU0_SOC2FPGA_256G_BAR_REG, 0xc1a00006, 0xc1f03e1f);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_480G_LR_REG, 0x8000000, 0xffffffff);
+ soc64_write_fpga2soc(SOCFPGA_SECREG_DMI_SDRAM_480G_HR_REG, 0, 0xff);
+
+ soc64_write_gic_m(SOCFPGA_SECREG_NCAIU1MIFSR_REG, 0, 0x7070777);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_2G_LR_REG, 0x80000, 0xffffffff);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_2G_HR_REG, 0, 0xff);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_30G_LR_REG, 0x800000, 0xffffffff);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_30G_HR_REG, 0, 0xff);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_480G_LR_REG, 0x8000000, 0xffffffff);
+ soc64_write_gic_m(SOCFPGA_SECREG_DMI_SDRAM_480G_HR_REG, 0, 0xff);
+
+ soc64_write_tcu(SOCFPGA_SECREG_NCAIU1MIFSR_REG, 0, 0x7070777);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_2G_LR_REG, 0x80000, 0xffffffff);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_2G_HR_REG, 0, 0xff);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_30G_LR_REG, 0x800000, 0xffffffff);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_30G_HR_REG, 0, 0xff);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_480G_LR_REG, 0x8000000, 0xffffffff);
+ soc64_write_tcu(SOCFPGA_SECREG_DMI_SDRAM_480G_HR_REG, 0, 0xff);
+
+ soc64_write_iom(SOCFPGA_SECREG_NCAIU1MIFSR_REG, 0, 0x7070777);
+ soc64_write_iom(SOCFPGA_SECREG_DII1_MPFE_LR_REG, 0x18000, 0xffffffff);
+ soc64_write_iom(SOCFPGA_SECREG_DII1_MPFE_HR_REG, 0, 0xff);
+ soc64_write_iom(SOCFPGA_SECREG_DII1_MPFE_BAR_REG, 0xc0e00200, 0xc1f03e1f);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_2G_LR_REG, 0x80000, 0xffffffff);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_2G_HR_REG, 0, 0xff);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_30G_LR_REG, 0x800000, 0xffffffff);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_30G_HR_REG, 0, 0xff);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_480G_LR_REG, 0x8000000, 0xffffffff);
+ soc64_write_iom(SOCFPGA_SECREG_DMI_SDRAM_480G_HR_REG, 0, 0xff);
+
+ soc64_write_dce0(SOCFPGA_SECREG_NCAIU1MIFSR_REG, 0, 0x7070777);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_2G_LR_REG, 0x80000, 0xffffffff);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_2G_HR_REG, 0, 0xff);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_30G_LR_REG, 0x800000, 0xffffffff);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_30G_HR_REG, 0, 0xff);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_480G_LR_REG, 0x8000000, 0xffffffff);
+ soc64_write_dce0(SOCFPGA_SECREG_DMI_SDRAM_480G_HR_REG, 0, 0xff);
+ soc64_write_dce1(SOCFPGA_SECREG_NCAIU1MIFSR_REG, 0, 0x7070777);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_2G_LR_REG, 0x80000, 0xffffffff);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_2G_HR_REG, 0, 0xff);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_30G_LR_REG, 0x800000, 0xffffffff);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_30G_HR_REG, 0, 0xff);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_480G_LR_REG, 0x8000000, 0xffffffff);
+ soc64_write_dce1(SOCFPGA_SECREG_DMI_SDRAM_480G_HR_REG, 0, 0xff);
+ soc64_write_dmi0(SOCFPGA_DMI0_DMIUSMCTCR_REG, 1, 0x3);
+ soc64_write_dmi0(SOCFPGA_DMI0_DMIUSMCTCR_REG, 3, 0x3);
+ soc64_write_dmi1(SOCFPGA_DMI1_DMIUSMCTCR_REG, 1, 0x3);
+ soc64_write_dmi1(SOCFPGA_DMI1_DMIUSMCTCR_REG, 3, 0x3);
+
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_NAND_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_USB0_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_USB1_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_SPI_MAIN0_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_SPI_MAIN1_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_SPI_SEC0_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_SPI_SEC1_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_EMAC0_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_EMAC1_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_EMAC2_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_SDMMC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_GPIO0_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_GPIO1_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_I2C0_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_I2C1_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_I2C2_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_I2C3_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_I2C4_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_SP_TIMER0_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_SP_TIMER1_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_UART0_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_UART1_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_I3C0_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_I3C1_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_DMA0_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_DMA1_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_COMBO_PHY_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_per(SOCFPGA_FIREWALL_L4_PER_NAND_SDMA_REG, 0x1010301, 0x1010301);
+
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_DMA_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_EMAC0RX_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_EMAC0TX_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_EMAC1RX_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_EMAC1TX_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_EMAC2RX_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_EMAC2TX_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_NAND_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_NAND_READ_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_NAND_WRITE_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_OCRAM_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_SDMMC_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_USB0_ECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_USB1_CACHEECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_CLOCK_MANAGER_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_IO_MANAGER_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_RESET_MANAGER_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_SYSTEM_MANAGER_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_OSC0_TIMER_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_OSC1_TIMER0_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_WATCHDOG0_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_WATCHDOG1_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_WATCHDOG2_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_WATCHDOG3_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_DAP_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_WATCHDOG4_REG, 0x1010301, 0x1010301);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_POWER_MANAGER_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_USB1_RXECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_USB1_TXECC_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_L4_NOC_PROBES_REG, 0x1010001, 0x1010001);
+ soc64_write_l4_sys(SOCFPGA_FIREWALL_L4_SYS_L4_NOC_QOS_REG, 0x1010001, 0x1010001);
+
+ soc64_set(IOMEM(SOCFPGA_FIREWALL_SOC2FPGA_ADDRESS), 0, 0xffe0301, 0xffe0301);
+ soc64_set(IOMEM(SOCFPGA_FIREWALL_LWSOC2FPGA_ADDRESS), 0, 0xffe0301, 0xffe0301);
+ soc64_set(IOMEM(SOCFPGA_FIREWALL_TCU_ADDRESS), 0, 0xffe0301, 0xffe0301);
+
+ /* Enable non-secure access to ocram */
+ clrbits_le32(SOCFPGA_OCRAM_FIREWALL_ADDRESS + 0x18, BIT(0));
+}
diff --git a/arch/arm/mach-socfpga/atf.c b/arch/arm/mach-socfpga/atf.c
new file mode 100644
index 0000000000000000000000000000000000000000..23e2fffdce59c6da4c4e1b632e5ddb9ba22889b1
--- /dev/null
+++ b/arch/arm/mach-socfpga/atf.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <asm/sections.h>
+#include <common.h>
+#include <firmware.h>
+#include <asm-generic/memory_layout.h>
+#include <asm/atf_common.h>
+#include <asm/barebox-arm.h>
+#include <mach/socfpga/atf.h>
+#include <mach/socfpga/generic.h>
+#include <mach/socfpga/soc64-regs.h>
+
+void __noreturn agilex5_load_and_start_image_via_tfa(unsigned long memsize)
+{
+ unsigned long atf_dest = AGILEX5_ATF_BL31_BASE_ADDR;
+ void __noreturn (*bl31)(void) = (void *)atf_dest;
+ const void *tfa;
+ size_t tfa_size;
+
+ pr_debug("Load TFA\n");
+
+ memcpy((void *)AGILEX5_ATF_BL33_BASE_ADDR, __image_start, barebox_image_size);
+
+ get_builtin_firmware(agilex5_bl31_bin, &tfa, &tfa_size);
+
+ memcpy(bl31, tfa, tfa_size);
+
+ asm volatile("msr sp_el2, %0" : :
+ "r" (AGILEX5_ATF_BL33_BASE_ADDR - 16) :
+ "cc");
+
+ pr_debug("Jumping to @0x%08lx\n", atf_dest);
+ bl31_entry((uintptr_t)bl31, 0, AGILEX5_ATF_BL33_BASE_ADDR, 0);
+ __builtin_unreachable();
+}
diff --git a/arch/arm/mach-socfpga/cpu_init.c b/arch/arm/mach-socfpga/cpu_init.c
index 73b69c34c56f86c045abc4916e68a6d8af0885cd..048bd0f867065cfa26dedb112a2667453d534af8 100644
--- a/arch/arm/mach-socfpga/cpu_init.c
+++ b/arch/arm/mach-socfpga/cpu_init.c
@@ -1,12 +1,55 @@
// SPDX-License-Identifier: GPL-2.0
#include <common.h>
+#include <io.h>
+#include <debug_ll.h>
#include <asm/barebox-arm-head.h>
#include <asm/errata.h>
#include <mach/socfpga/init.h>
+#include <mach/socfpga/agilex5-clk.h>
+#include <mach/socfpga/mailbox_s10.h>
+#include <mach/socfpga/soc64-regs.h>
+#include <mach/socfpga/soc64-reset-manager.h>
+#include <mach/socfpga/soc64-system-manager.h>
+#ifdef CONFIG_CPU_32
void arria10_cpu_lowlevel_init(void)
{
enable_arm_errata_794072_war();
enable_arm_errata_845369_war();
}
+#else
+void socfpga_agilex5_cpu_lowlevel_init(void)
+{
+ int enable = 0x3;
+ int loadval = ~0;
+ int val;
+
+ arm_cpu_lowlevel_init();
+
+ agilex5_sysmgr_pinmux_init();
+
+ /* Disable all watchdogs */
+ writel(SYSMGR_WDDBG_PAUSE_ALL_CPU, SOCFPGA_SYSMGR_ADDRESS +
+ SYSMGR_SOC64_WDDBG);
+ /* Let everything out of reset but the watchdogs */
+ val = 0xf;
+ writel(val, SOCFPGA_RSTMGR_ADDRESS + RSTMGR_SOC64_PER1MODRST);
+
+ /* de-assert resets */
+ writel(0, SOCFPGA_RSTMGR_ADDRESS + RSTMGR_SOC64_BRGMODRST);
+
+ /* configure DFI_SEL for SDMMC */
+ writel(SYSMGR_SOC64_COMBOPHY_DFISEL_SDMMC,
+ SOCFPGA_SYSMGR_ADDRESS+ SYSMGR_SOC64_COMBOPHY_DFISEL);
+
+ writel(enable, SOCFPGA_GTIMER_SEC_ADDRESS);
+ asm volatile("msr cntp_ctl_el0, %0" : : "r" (enable));
+ asm volatile("msr cntp_tval_el0, %0" : : "r" (loadval));
+
+ /* configure default base clkmgr clock - 200MHz */
+ val = readl(SOCFPGA_CLKMGR_ADDRESS + CLKMGR_MAINPLL_NOCDIV);
+ val &= 0xfffcffff | (CLKMGR_NOCDIV_SOFTPHY_DIV_ONE << CLKMGR_NOCDIV_SOFTPHY_OFFSET);
+ writel(val, SOCFPGA_CLKMGR_ADDRESS + CLKMGR_MAINPLL_NOCDIV);
+}
+#endif
diff --git a/arch/arm/mach-socfpga/iossm_mailbox.c b/arch/arm/mach-socfpga/iossm_mailbox.c
new file mode 100644
index 0000000000000000000000000000000000000000..de79b8370d8524553b31feb6e8845f7100408d1f
--- /dev/null
+++ b/arch/arm/mach-socfpga/iossm_mailbox.c
@@ -0,0 +1,551 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022-2024 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <io.h>
+#include <linux/bitfield.h>
+#include "iossm_mailbox.h"
+#include <mach/socfpga/generic.h>
+#include <mach/socfpga/soc64-regs.h>
+#include <mach/socfpga/soc64-system-manager.h>
+
+#define ECC_INTSTATUS_SERR SOCFPGA_SYSMGR_ADDRESS + 0x9C
+#define ECC_INISTATUS_DERR SOCFPGA_SYSMGR_ADDRESS + 0xA0
+#define DDR_CSR_CLKGEN_LOCKED_IO96B0_MASK BIT(16)
+#define DDR_CSR_CLKGEN_LOCKED_IO96B1_MASK BIT(17)
+
+#define DDR_CSR_CLKGEN_LOCKED_IO96B_MASK(x) (i == 0 ? DDR_CSR_CLKGEN_LOCKED_IO96B0_MASK : \
+ DDR_CSR_CLKGEN_LOCKED_IO96B1_MASK)
+#define MAX_RETRY_COUNT 3
+#define NUM_CMD_RESPONSE_DATA 3
+
+#define INTF_IP_TYPE_MASK GENMASK(31, 29)
+#define INTF_INSTANCE_ID_MASK GENMASK(28, 24)
+
+/* supported DDR type list */
+static const char *ddr_type_list[7] = {
+ "DDR4", "DDR5", "DDR5_RDIMM", "LPDDR4", "LPDDR5", "QDRIV", "UNKNOWN"
+};
+
+static int wait_for_timeout(const void __iomem *reg, u32 mask, bool set)
+{
+ int timeout = 1000000;
+ int val;
+
+ while (timeout > 0) {
+ val = readl(IOMEM(reg));
+ if (!set)
+ val = ~val;
+
+ if ((val & mask) == mask)
+ return 0;
+ __udelay(10);
+ timeout--;
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int is_ddr_csr_clkgen_locked(u32 clkgen_mask, u8 num_port)
+{
+ int ret;
+
+ ret = wait_for_timeout(IOMEM(ECC_INTSTATUS_SERR), clkgen_mask, true);
+ if (ret) {
+ pr_debug("%s: ddr csr clkgena locked is timeout\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Mailbox request function
+ * This function will send the request to IOSSM mailbox and wait for response return
+ *
+ * @io96b_csr_addr: CSR address for the target IO96B
+ * @ip_type: IP type for the specified memory interface
+ * @instance_id: IP instance ID for the specified memory interface
+ * @usr_cmd_type: User desire IOSSM mailbox command type
+ * @usr_cmd_opcode: User desire IOSSM mailbox command opcode
+ * @cmd_param_*: Parameters (if applicable) for the requested IOSSM mailbox command
+ * @resp_data_len: User desire extra response data fields other than
+ * CMD_RESPONSE_DATA_SHORT field on CMD_RESPONSE_STATUS
+ * @resp: Structure contain responses returned from the requested IOSSM
+ * mailbox command
+ */
+int io96b_mb_req(phys_addr_t io96b_csr_addr, u32 ip_type, u32 instance_id
+ , u32 usr_cmd_type, u32 usr_cmd_opcode, u32 cmd_param_0
+ , u32 cmd_param_1, u32 cmd_param_2, u32 cmd_param_3
+ , u32 cmd_param_4, u32 cmd_param_5, u32 cmd_param_6
+ , u32 resp_data_len, struct io96b_mb_resp *resp)
+{
+ int i;
+ int ret;
+ u32 cmd_req, cmd_resp;
+
+ /* Initialized zeros for responses*/
+ resp->cmd_resp_status = 0;
+ for (i = 0; i < NUM_CMD_RESPONSE_DATA; i++)
+ resp->cmd_resp_data[i] = 0;
+
+ /* Ensure CMD_REQ is cleared before write any command request */
+ ret = wait_for_timeout((IOMEM(io96b_csr_addr) + IOSSM_CMD_REQ_OFFSET), GENMASK(31, 0), false);
+ if (ret) {
+ printf("%s: CMD_REQ not ready\n", __func__);
+ return -1;
+ }
+
+ /* Write CMD_PARAM_* */
+ for (i = 0; i < 6 ; i++) {
+ switch (i) {
+ case 0:
+ if (cmd_param_0)
+ writel(cmd_param_0, io96b_csr_addr + IOSSM_CMD_PARAM_0_OFFSET);
+ break;
+ case 1:
+ if (cmd_param_1)
+ writel(cmd_param_1, io96b_csr_addr + IOSSM_CMD_PARAM_1_OFFSET);
+ break;
+ case 2:
+ if (cmd_param_2)
+ writel(cmd_param_2, io96b_csr_addr + IOSSM_CMD_PARAM_2_OFFSET);
+ break;
+ case 3:
+ if (cmd_param_3)
+ writel(cmd_param_3, io96b_csr_addr + IOSSM_CMD_PARAM_3_OFFSET);
+ break;
+ case 4:
+ if (cmd_param_4)
+ writel(cmd_param_4, io96b_csr_addr + IOSSM_CMD_PARAM_4_OFFSET);
+ break;
+ case 5:
+ if (cmd_param_5)
+ writel(cmd_param_5, io96b_csr_addr + IOSSM_CMD_PARAM_5_OFFSET);
+ break;
+ case 6:
+ if (cmd_param_6)
+ writel(cmd_param_6, io96b_csr_addr + IOSSM_CMD_PARAM_6_OFFSET);
+ break;
+ default:
+ printf("%s: Invalid command parameter\n", __func__);
+ }
+ }
+
+ /* Write CMD_REQ (IP_TYPE, IP_INSTANCE_ID, CMD_TYPE and CMD_OPCODE) */
+ cmd_req = (usr_cmd_opcode << 0) | (usr_cmd_type << 16) | (instance_id << 24) |
+ (ip_type << 29);
+ writel(cmd_req, io96b_csr_addr + IOSSM_CMD_REQ_OFFSET);
+ pr_debug("%s: Write 0x%x to IOSSM_CMD_REQ_OFFSET 0x%llx\n", __func__, cmd_req
+ , io96b_csr_addr + IOSSM_CMD_REQ_OFFSET);
+
+ /* Read CMD_RESPONSE_READY in CMD_RESPONSE_STATUS*/
+ ret = wait_for_timeout((IOMEM(io96b_csr_addr) + IOSSM_CMD_RESPONSE_STATUS_OFFSET),
+ IOSSM_STATUS_COMMAND_RESPONSE_READY, true);
+ if (ret) {
+ printf("%s: CMD_RESPONSE ERROR:\n", __func__);
+ cmd_resp = readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+ printf("%s: STATUS_GENERAL_ERROR: 0x%x\n", __func__, (cmd_resp >> 1) & 0xF);
+ printf("%s: STATUS_CMD_RESPONSE_ERROR: 0x%x\n", __func__, (cmd_resp >> 5) & 0x7);
+ }
+
+ /* read CMD_RESPONSE_STATUS*/
+ resp->cmd_resp_status = readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+ pr_debug("%s: CMD_RESPONSE_STATUS 0x%llx: 0x%x\n", __func__, io96b_csr_addr +
+ IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
+
+ /* read CMD_RESPONSE_DATA_* */
+ for (i = 0; i < resp_data_len; i++) {
+ switch (i) {
+ case 0:
+ resp->cmd_resp_data[i] =
+ readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_0_OFFSET);
+ pr_debug("%s: IOSSM_CMD_RESPONSE_DATA_0_OFFSET 0x%llx: 0x%x\n", __func__
+ , io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_0_OFFSET,
+ resp->cmd_resp_data[i]);
+ break;
+ case 1:
+ resp->cmd_resp_data[i] =
+ readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_1_OFFSET);
+ pr_debug("%s: IOSSM_CMD_RESPONSE_DATA_1_OFFSET 0x%llx: 0x%x\n", __func__
+ , io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_1_OFFSET,
+ resp->cmd_resp_data[i]);
+ break;
+ case 2:
+ resp->cmd_resp_data[i] =
+ readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_2_OFFSET);
+ pr_debug("%s: IOSSM_CMD_RESPONSE_DATA_2_OFFSET 0x%llx: 0x%x\n", __func__
+ , io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_2_OFFSET,
+ resp->cmd_resp_data[i]);
+ break;
+ default:
+ printf("%s: Invalid response data\n", __func__);
+ }
+ }
+
+ resp->cmd_resp_status = readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+ pr_debug("%s: CMD_RESPONSE_STATUS 0x%llx: 0x%x\n", __func__, io96b_csr_addr +
+ IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
+
+ /* write CMD_RESPONSE_READY = 0 */
+ clrbits_le32((u32 *)(uintptr_t)(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET)
+ , IOSSM_STATUS_COMMAND_RESPONSE_READY);
+
+ resp->cmd_resp_status = readl(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+ pr_debug("%s: CMD_RESPONSE_READY 0x%llx: 0x%x\n", __func__, io96b_csr_addr +
+ IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
+
+ return 0;
+}
+
+/*
+ * Initial function to be called to set memory interface IP type and instance ID
+ * IP type and instance ID need to be determined before sending mailbox command
+ */
+void io96b_mb_init(struct io96b_info *io96b_ctrl)
+{
+ struct io96b_mb_resp usr_resp;
+ u8 ip_type_ret, instance_id_ret;
+ int i, j, k;
+
+ pr_debug("%s: num_instance %d\n", __func__, io96b_ctrl->num_instance);
+ for (i = 0; i < io96b_ctrl->num_instance; i++) {
+ pr_debug("%s: get memory interface IO96B %d\n", __func__, i);
+ /* Get memory interface IP type and instance ID (IP identifier) */
+ io96b_mb_req(io96b_ctrl->io96b[i].io96b_csr_addr, 0, 0, CMD_GET_SYS_INFO
+ , GET_MEM_INTF_INFO, 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
+ pr_debug("%s: get response from memory interface IO96B %d\n", __func__, i);
+ /* Retrieve number of memory interface(s) */
+ io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface =
+ IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status) & 0x3;
+ pr_debug("%s: IO96B %d: num_mem_interface: 0x%x\n", __func__, i
+ , io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface);
+
+ /* Retrieve memory interface IP type and instance ID (IP identifier) */
+ j = 0;
+ for (k = 0; k < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; k++) {
+ ip_type_ret = FIELD_GET(INTF_IP_TYPE_MASK, usr_resp.cmd_resp_data[k]);
+ instance_id_ret = FIELD_GET(INTF_INSTANCE_ID_MASK
+ , usr_resp.cmd_resp_data[k]);
+
+ if (ip_type_ret) {
+ io96b_ctrl->io96b[i].mb_ctrl.ip_type[j] = ip_type_ret;
+ io96b_ctrl->io96b[i].mb_ctrl.ip_instance_id[j] = instance_id_ret;
+ pr_debug("%s: IO96B %d mem_interface %d: ip_type_ret: 0x%x\n"
+ , __func__, i, j, ip_type_ret);
+ pr_debug("%s: IO96B %d mem_interface %d: instance_id_ret: 0x%x\n"
+ , __func__, i, j, instance_id_ret);
+ j++;
+ }
+ }
+ }
+}
+
+int io96b_cal_status(phys_addr_t addr)
+{
+ int ret;
+ u32 cal_success, cal_fail;
+ phys_addr_t status_addr = addr + IOSSM_STATUS_OFFSET;
+ /* Ensure calibration completed */
+ ret = wait_for_timeout(IOMEM(status_addr), IOSSM_STATUS_CAL_BUSY, false);
+ if (ret) {
+ printf("%s: SDRAM calibration IO96b instance 0x%llx timeout\n", __func__
+ , status_addr);
+ hang();
+ }
+
+ /* Calibration status */
+ cal_success = readl(status_addr) & IOSSM_STATUS_CAL_SUCCESS;
+ cal_fail = readl(status_addr) & IOSSM_STATUS_CAL_FAIL;
+
+ if (cal_success && !cal_fail)
+ return 0;
+ else
+ return -EPERM;
+}
+
+void init_mem_cal(struct io96b_info *io96b_ctrl)
+{
+ int count, i, ret;
+
+ /* Initialize overall calibration status */
+ io96b_ctrl->overall_cal_status = false;
+
+ /* Check initial calibration status for the assigned IO96B*/
+ count = 0;
+ for (i = 0; i < io96b_ctrl->num_instance; i++) {
+ if (io96b_ctrl->ckgen_lock) {
+ ret = is_ddr_csr_clkgen_locked(DDR_CSR_CLKGEN_LOCKED_IO96B_MASK(i),
+ io96b_ctrl->num_port);
+ if (ret) {
+ printf("%s: ckgena_lock iossm IO96B_%d is not locked\n",
+ __func__, i);
+ hang();
+ }
+ }
+ ret = io96b_cal_status(io96b_ctrl->io96b[i].io96b_csr_addr);
+ if (ret) {
+ io96b_ctrl->io96b[i].cal_status = false;
+ printf("%s: Initial DDR calibration IO96B_%d failed %d\n", __func__, i
+ , ret);
+ hang();
+ }
+ io96b_ctrl->io96b[i].cal_status = true;
+ printf("%s: Initial DDR calibration IO96B_%d succeed\n", __func__, i);
+ count++;
+ }
+
+ if (count == io96b_ctrl->num_instance)
+ io96b_ctrl->overall_cal_status = true;
+}
+
+/*
+ * Trying 3 times re-calibration if initial calibration failed
+ */
+int trig_mem_cal(struct io96b_info *io96b_ctrl)
+{
+ struct io96b_mb_resp usr_resp;
+ bool recal_success;
+ int i, j, k;
+ u32 cal_stat_offset;
+ u8 cal_stat;
+ u8 trig_cal_stat;
+ int count = 0;
+
+ for (i = 0; i < io96b_ctrl->num_instance; i++) {
+ if (!(io96b_ctrl->io96b[i].cal_status)) {
+ for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
+ /* Get the memory calibration status for memory interface */
+ io96b_mb_req(io96b_ctrl->io96b[i].io96b_csr_addr, 0, 0
+ , CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0, 0, 0
+ , 0, 0, 0, 0, 2, &usr_resp);
+
+ recal_success = false;
+
+ /* Re-calibration first memory interface with failed calibration */
+ for (k = 0; k < MAX_RETRY_COUNT; k++) {
+ cal_stat_offset = usr_resp.cmd_resp_data[j];
+ cal_stat = readl(io96b_ctrl->io96b[i].io96b_csr_addr +
+ cal_stat_offset);
+ if (cal_stat == INTF_MEM_CAL_STATUS_SUCCESS) {
+ recal_success = true;
+ break;
+ }
+ io96b_mb_req(io96b_ctrl->io96b[i].io96b_csr_addr
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_type[j]
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_instance_id[j]
+ , CMD_TRIG_MEM_CAL_OP, TRIG_MEM_CAL, 0, 0, 0, 0, 0
+ , 0, 0, 2, &usr_resp);
+
+ trig_cal_stat =
+ IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status) &
+ BIT(0);
+ pr_debug("%s: Memory calibration triggered status = %d\n",
+ __func__, trig_cal_stat);
+
+ udelay(1);
+
+ io96b_mb_req(io96b_ctrl->io96b[i].io96b_csr_addr, 0, 0
+ , CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS
+ , 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
+ }
+
+ if (!recal_success) {
+ printf("%s: Error as SDRAM calibration failed\n", __func__);
+ hang();
+ }
+ }
+
+ io96b_ctrl->io96b[i].cal_status = true;
+ io96b_ctrl->overall_cal_status = io96b_ctrl->io96b[i].cal_status;
+ printf("%s: Initial DDR calibration IO96B_%d succeed\n", __func__, i);
+ count++;
+ }
+ }
+
+ if (io96b_ctrl->overall_cal_status)
+ pr_debug("%s: Overall SDRAM calibration success\n", __func__);
+
+ return 0;
+}
+
+int get_mem_technology(struct io96b_info *io96b_ctrl)
+{
+ struct io96b_mb_resp usr_resp;
+ int i, j;
+ u8 ddr_type_ret;
+
+ /* Initialize ddr type */
+ io96b_ctrl->ddr_type = ddr_type_list[6];
+
+ /* Get and ensure all memory interface(s) same DDR type */
+ for (i = 0; i < io96b_ctrl->num_instance; i++) {
+ for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
+ io96b_mb_req(io96b_ctrl->io96b[i].io96b_csr_addr
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_type[j]
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_instance_id[j]
+ , CMD_GET_MEM_INFO, GET_MEM_TECHNOLOGY, 0, 0, 0, 0
+ , 0, 0, 0, 0, &usr_resp);
+
+ ddr_type_ret =
+ IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+ & GENMASK(2, 0);
+
+ if (!strcmp(io96b_ctrl->ddr_type, "UNKNOWN"))
+ io96b_ctrl->ddr_type = ddr_type_list[ddr_type_ret];
+
+ if (ddr_type_list[ddr_type_ret] != io96b_ctrl->ddr_type) {
+ printf("%s: Mismatch DDR type on IO96B_%d\n", __func__, i);
+ return -ENOEXEC;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int get_mem_width_info(struct io96b_info *io96b_ctrl)
+{
+ struct io96b_mb_resp usr_resp;
+ int i, j;
+ u16 memory_size;
+ u16 total_memory_size = 0;
+
+ /* Get all memory interface(s) total memory size on all instance(s) */
+ for (i = 0; i < io96b_ctrl->num_instance; i++) {
+ memory_size = 0;
+ for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
+ io96b_mb_req(io96b_ctrl->io96b[i].io96b_csr_addr
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_type[j]
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_instance_id[j]
+ , CMD_GET_MEM_INFO, GET_MEM_WIDTH_INFO, 0, 0, 0, 0
+ , 0, 0, 0, 2, &usr_resp);
+
+ memory_size = memory_size +
+ (usr_resp.cmd_resp_data[1] & GENMASK(7, 0));
+ }
+
+ if (!memory_size) {
+ printf("%s: Failed to get valid memory size\n", __func__);
+ return -ENOEXEC;
+ }
+
+ io96b_ctrl->io96b[i].size = memory_size;
+
+ total_memory_size = total_memory_size + memory_size;
+ }
+
+ if (!total_memory_size) {
+ printf("%s: Failed to get valid memory size\n", __func__);
+ return -ENOEXEC;
+ }
+
+ io96b_ctrl->overall_size = total_memory_size;
+
+ return 0;
+}
+
+int ecc_enable_status(struct io96b_info *io96b_ctrl)
+{
+ struct io96b_mb_resp usr_resp;
+ int i, j;
+ bool ecc_stat_set = false;
+ bool ecc_stat;
+
+ /* Initialize ECC status */
+ io96b_ctrl->ecc_status = false;
+
+ /* Get and ensure all memory interface(s) same ECC status */
+ for (i = 0; i < io96b_ctrl->num_instance; i++) {
+ for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
+ io96b_mb_req(io96b_ctrl->io96b[i].io96b_csr_addr
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_type[j]
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_instance_id[j]
+ , CMD_TRIG_CONTROLLER_OP, ECC_ENABLE_STATUS, 0, 0, 0
+ , 0, 0, 0, 0, 0, &usr_resp);
+
+ ecc_stat = ((IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+ & GENMASK(1, 0)) == 0 ? false : true);
+
+ if (!ecc_stat_set) {
+ io96b_ctrl->ecc_status = ecc_stat;
+ ecc_stat_set = true;
+ }
+
+ if (ecc_stat != io96b_ctrl->ecc_status) {
+ printf("%s: Mismatch DDR ECC status on IO96B_%d\n"
+ , __func__, i);
+ return -ENOEXEC;
+ }
+ }
+ }
+
+ pr_debug("%s: ECC enable status: %d\n", __func__, io96b_ctrl->ecc_status);
+
+ return 0;
+}
+
+int bist_mem_init_start(struct io96b_info *io96b_ctrl)
+{
+ struct io96b_mb_resp usr_resp;
+ int i, j;
+ bool bist_start, bist_success;
+ int timeout = 1000000;
+
+ /* Full memory initialization BIST performed on all memory interface(s) */
+ for (i = 0; i < io96b_ctrl->num_instance; i++) {
+ for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) {
+ bist_start = false;
+ bist_success = false;
+
+ /* Start memory initialization BIST on full memory address */
+ io96b_mb_req(io96b_ctrl->io96b[i].io96b_csr_addr
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_type[j]
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_instance_id[j]
+ , CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_START, 0x40
+ , 0, 0, 0, 0, 0, 0, 0, &usr_resp);
+
+ bist_start =
+ (IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+ & BIT(0));
+
+ if (!bist_start) {
+ printf("%s: Failed to initialized memory on IO96B_%d\n"
+ , __func__, i);
+ printf("%s: BIST_MEM_INIT_START Error code 0x%x\n", __func__
+ , (IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+ & GENMASK(2, 1)) > 0x1);
+ return -ENOEXEC;
+ }
+
+ /* Polling for the initiated memory initialization BIST status */
+ while (!bist_success) {
+ io96b_mb_req(io96b_ctrl->io96b[i].io96b_csr_addr
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_type[j]
+ , io96b_ctrl->io96b[i].mb_ctrl.ip_instance_id[j]
+ , CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_STATUS, 0
+ , 0, 0, 0, 0, 0, 0, 0, &usr_resp);
+
+ bist_success = (IOSSM_CMD_RESPONSE_DATA_SHORT
+ (usr_resp.cmd_resp_status) & BIT(0));
+
+ if (!bist_success && (timeout-- < 0)) {
+ printf("%s: Timeout initialize memory on IO96B_%d\n"
+ , __func__, i);
+ printf("%s: BIST_MEM_INIT_STATUS Error code 0x%x\n"
+ , __func__, (IOSSM_CMD_RESPONSE_DATA_SHORT
+ (usr_resp.cmd_resp_status)
+ & GENMASK(2, 1)) > 0x1);
+ return -ETIMEDOUT;
+ }
+
+ __udelay(1);
+ }
+ }
+
+ pr_debug("%s: Memory initialized successfully on IO96B_%d\n", __func__, i);
+ }
+ return 0;
+}
diff --git a/arch/arm/mach-socfpga/iossm_mailbox.h b/arch/arm/mach-socfpga/iossm_mailbox.h
new file mode 100644
index 0000000000000000000000000000000000000000..86c93a38d5845d34ad82b510ac09b8048f42c64e
--- /dev/null
+++ b/arch/arm/mach-socfpga/iossm_mailbox.h
@@ -0,0 +1,152 @@
+#ifndef IOSSM_MAILBOX_H_
+#define IOSSM_MAILBOX_H_
+
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022-2023 Intel Corporation <www.intel.com>
+ */
+
+#define TIMEOUT 120000
+#define IOSSM_STATUS_CAL_SUCCESS BIT(0)
+#define IOSSM_STATUS_CAL_FAIL BIT(1)
+#define IOSSM_STATUS_CAL_BUSY BIT(2)
+#define IOSSM_STATUS_COMMAND_RESPONSE_READY BIT(0)
+#define IOSSM_CMD_RESPONSE_STATUS_OFFSET 0x45C
+#define IOSSM_CMD_RESPONSE_DATA_0_OFFSET 0x458
+#define IOSSM_CMD_RESPONSE_DATA_1_OFFSET 0x454
+#define IOSSM_CMD_RESPONSE_DATA_2_OFFSET 0x450
+#define IOSSM_CMD_REQ_OFFSET 0x43C
+#define IOSSM_CMD_PARAM_0_OFFSET 0x438
+#define IOSSM_CMD_PARAM_1_OFFSET 0x434
+#define IOSSM_CMD_PARAM_2_OFFSET 0x430
+#define IOSSM_CMD_PARAM_3_OFFSET 0x42C
+#define IOSSM_CMD_PARAM_4_OFFSET 0x428
+#define IOSSM_CMD_PARAM_5_OFFSET 0x424
+#define IOSSM_CMD_PARAM_6_OFFSET 0x420
+#define IOSSM_STATUS_OFFSET 0x400
+#define IOSSM_CMD_RESPONSE_DATA_SHORT_MASK GENMASK(31, 16)
+#define IOSSM_CMD_RESPONSE_DATA_SHORT(data) (((data) & IOSSM_CMD_RESPONSE_DATA_SHORT_MASK) >> 16)
+#define MAX_IO96B_SUPPORTED 2
+
+/* supported mailbox command type */
+enum iossm_mailbox_cmd_type {
+ CMD_NOP,
+ CMD_GET_SYS_INFO,
+ CMD_GET_MEM_INFO,
+ CMD_GET_MEM_CAL_INFO,
+ CMD_TRIG_CONTROLLER_OP,
+ CMD_TRIG_MEM_CAL_OP
+};
+
+/* supported mailbox command opcode */
+enum iossm_mailbox_cmd_opcode {
+ GET_MEM_INTF_INFO = 0x0001,
+ GET_MEM_TECHNOLOGY,
+ GET_MEMCLK_FREQ_KHZ,
+ GET_MEM_WIDTH_INFO,
+ ECC_ENABLE_SET = 0x0101,
+ ECC_ENABLE_STATUS,
+ ECC_INTERRUPT_STATUS,
+ ECC_INTERRUPT_ACK,
+ ECC_INTERRUPT_MASK,
+ ECC_WRITEBACK_ENABLE,
+ ECC_SCRUB_IN_PROGRESS_STATUS = 0x0201,
+ ECC_SCRUB_MODE_0_START,
+ ECC_SCRUB_MODE_1_START,
+ BIST_STANDARD_MODE_START = 0x0301,
+ BIST_RESULTS_STATUS,
+ BIST_MEM_INIT_START,
+ BIST_MEM_INIT_STATUS,
+ BIST_SET_DATA_PATTERN_UPPER,
+ BIST_SET_DATA_PATTERN_LOWER,
+ TRIG_MEM_CAL = 0x000a,
+ GET_MEM_CAL_STATUS
+};
+
+/* response data of cmd opcode GET_MEM_CAL_STATUS */
+#define INTF_UNUSED 0x0
+#define INTF_MEM_CAL_STATUS_SUCCESS 0x1
+#define INTF_MEM_CAL_STATUS_FAIL 0x2
+#define INTF_MEM_CAL_STATUS_ONGOING 0x4
+
+/*
+ * IOSSM mailbox required information
+ *
+ * @num_mem_interface: Number of memory interfaces instantiated
+ * @ip_type: IP type implemented on the IO96B
+ * @ip_instance_id: IP identifier for every IP instance implemented on the IO96B
+ */
+struct io96b_mb_ctrl {
+ u32 num_mem_interface;
+ u32 ip_type[2];
+ u32 ip_instance_id[2];
+};
+
+/*
+ * IOSSM mailbox response outputs
+ *
+ * @cmd_resp_status: Command Interface status
+ * @cmd_resp_data_*: More spaces for command response
+ */
+struct io96b_mb_resp {
+ u32 cmd_resp_status;
+ u32 cmd_resp_data[3];
+};
+
+/*
+ * IO96B instance specific information
+ *
+ * @size: Memory size
+ * @io96b_csr_addr: IO96B instance CSR address
+ * @cal_status: IO96B instance calibration status
+ * @mb_ctrl: IOSSM mailbox required information
+ */
+struct io96b_instance {
+ u16 size;
+ phys_addr_t io96b_csr_addr;
+ bool cal_status;
+ struct io96b_mb_ctrl mb_ctrl;
+};
+
+/*
+ * Overall IO96B instance(s) information
+ *
+ * @num_instance: Number of instance(s) assigned to HPS
+ * @overall_cal_status: Overall calibration status for all IO96B instance(s)
+ * @ddr_type: DDR memory type
+ * @ecc_status: ECC enable status (false = disabled, true = enabled)
+ * @overall_size: Total DDR memory size
+ * @io96b[]: IO96B instance specific information
+ * @ckgen_lock: IO96B GEN PLL lock (false = not locked, true = locked)
+ * @num_port: Number of IO96B port.
+ */
+struct io96b_info {
+ u8 num_instance;
+ bool overall_cal_status;
+ const char *ddr_type;
+ bool ecc_status;
+ u16 overall_size;
+ struct io96b_instance io96b[MAX_IO96B_SUPPORTED];
+ bool ckgen_lock;
+ u8 num_port;
+};
+
+int io96b_mb_req(phys_addr_t io96b_csr_addr, u32 ip_type, u32 instance_id
+ , u32 usr_cmd_type, u32 usr_cmd_opcode, u32 cmd_param_0
+ , u32 cmd_param_1, u32 cmd_param_2, u32 cmd_param_3, u32 cmd_param_4
+ , u32 cmd_param_5, u32 cmd_param_6, u32 resp_data_len
+ , struct io96b_mb_resp *resp);
+
+/* Supported IOSSM mailbox function */
+void io96b_mb_init(struct io96b_info *io96b_ctrl);
+int io96b_cal_status(phys_addr_t addr);
+void init_mem_cal(struct io96b_info *io96b_ctrl);
+int trig_mem_cal(struct io96b_info *io96b_ctrl);
+int get_mem_technology(struct io96b_info *io96b_ctrl);
+int get_mem_width_info(struct io96b_info *io96b_ctrl);
+int ecc_enable_status(struct io96b_info *io96b_ctrl);
+int bist_mem_init_start(struct io96b_info *io96b_ctrl);
+
+
+
+#endif // IOSSM_MAILBOX_H_
diff --git a/arch/arm/mach-socfpga/mailbox_s10.c b/arch/arm/mach-socfpga/mailbox_s10.c
new file mode 100644
index 0000000000000000000000000000000000000000..26b240138e7c8be56a74052ca91d08cdf696c3a4
--- /dev/null
+++ b/arch/arm/mach-socfpga/mailbox_s10.c
@@ -0,0 +1,407 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017-2023 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <io.h>
+#include <mach/socfpga/mailbox_s10.h>
+#include <mach/socfpga/soc64-regs.h>
+#include <mach/socfpga/soc64-system-manager.h>
+
+#define MBOX_READL(reg) \
+ readl(SOCFPGA_MAILBOX_ADDRESS + (reg))
+
+#define MBOX_WRITEL(data, reg) \
+ writel(data, SOCFPGA_MAILBOX_ADDRESS + (reg))
+
+#define MBOX_READ_RESP_BUF(rout) \
+ MBOX_READL(MBOX_RESP_BUF + ((rout) * sizeof(u32)))
+
+#define MBOX_WRITE_CMD_BUF(data, cin) \
+ MBOX_WRITEL(data, MBOX_CMD_BUF + ((cin) * sizeof(u32)))
+
+static __always_inline int mbox_polling_resp(u32 rout)
+{
+ u32 rin;
+ unsigned long i = 2000;
+
+ while (i) {
+ rin = MBOX_READL(MBOX_RIN);
+ if (rout != rin)
+ return 0;
+
+ udelay(1000);
+ i--;
+ }
+
+ return -ETIMEDOUT;
+}
+
+static __always_inline int mbox_is_cmdbuf_full(u32 cin)
+{
+ return (((cin + 1) % MBOX_CMD_BUFFER_SIZE) == MBOX_READL(MBOX_COUT));
+}
+
+static __always_inline int mbox_is_cmdbuf_empty(u32 cin)
+{
+ return (((MBOX_READL(MBOX_COUT) + 1) % MBOX_CMD_BUFFER_SIZE) == cin);
+}
+
+static __always_inline int mbox_wait_for_cmdbuf_empty(u32 cin)
+{
+ int timeout = 2000;
+
+ while (timeout) {
+ if (mbox_is_cmdbuf_empty(cin))
+ return 0;
+
+ udelay(1000);
+ timeout--;
+ }
+
+ return -ETIMEDOUT;
+}
+
+static __always_inline int mbox_write_cmd_buffer(u32 *cin, u32 data,
+ int *is_cmdbuf_overflow)
+{
+ int timeout = 1000;
+
+ while (timeout) {
+ if (mbox_is_cmdbuf_full(*cin)) {
+ if (is_cmdbuf_overflow &&
+ *is_cmdbuf_overflow == 0) {
+ /* Trigger SDM doorbell */
+ MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM);
+ *is_cmdbuf_overflow = 1;
+ }
+ udelay(1000);
+ } else {
+ /* write header to circular buffer */
+ MBOX_WRITE_CMD_BUF(data, (*cin)++);
+ *cin %= MBOX_CMD_BUFFER_SIZE;
+ MBOX_WRITEL(*cin, MBOX_CIN);
+ if (is_cmdbuf_overflow)
+ *is_cmdbuf_overflow = 0;
+ break;
+ }
+ timeout--;
+ }
+
+ if (!timeout)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+/* Check for available slot and write to circular buffer.
+ * It also update command valid offset (cin) register.
+ */
+static __always_inline int mbox_fill_cmd_circular_buff(u32 header, u32 len,
+ u32 *arg)
+{
+ int i, ret;
+ int is_cmdbuf_overflow = 0;
+ u32 cin = MBOX_READL(MBOX_CIN) % MBOX_CMD_BUFFER_SIZE;
+
+ ret = mbox_write_cmd_buffer(&cin, header, &is_cmdbuf_overflow);
+ if (ret)
+ return ret;
+
+ /* write arguments */
+ for (i = 0; i < len; i++) {
+ is_cmdbuf_overflow = 0;
+ ret = mbox_write_cmd_buffer(&cin, arg[i], &is_cmdbuf_overflow);
+ if (ret)
+ return ret;
+ }
+
+ /* Always trigger the SDM doorbell at the end to ensure SDM able to read
+ * the remaining data.
+ */
+ MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM);
+
+ return 0;
+}
+
+/* Check the command and fill it into circular buffer */
+static __always_inline int mbox_prepare_cmd_only(u8 id, u32 cmd,
+ u8 is_indirect, u32 len,
+ u32 *arg)
+{
+ u32 header;
+ int ret;
+
+ if (cmd > MBOX_MAX_CMD_INDEX)
+ return -EINVAL;
+
+ header = MBOX_CMD_HEADER(MBOX_CLIENT_ID_BAREBOX, id, len,
+ (is_indirect) ? 1 : 0, cmd);
+
+ ret = mbox_fill_cmd_circular_buff(header, len, arg);
+
+ return ret;
+}
+
+/* Send command only without waiting for responses from SDM */
+static __always_inline int mbox_send_cmd_only_common(u8 id, u32 cmd,
+ u8 is_indirect, u32 len,
+ u32 *arg)
+{
+ return mbox_prepare_cmd_only(id, cmd, is_indirect, len, arg);
+}
+
+/* Return number of responses received in buffer */
+static __always_inline int __mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len)
+{
+ u32 rin;
+ u32 rout;
+ u32 resp_len = 0;
+
+ /* clear doorbell from SDM if it was SET */
+ if (MBOX_READL(MBOX_DOORBELL_FROM_SDM) & 1)
+ MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM);
+
+ /* read current response offset */
+ rout = MBOX_READL(MBOX_ROUT);
+ /* read response valid offset */
+ rin = MBOX_READL(MBOX_RIN);
+
+ while (rin != rout && (resp_len < resp_buf_max_len)) {
+ /* Response received */
+ if (resp_buf)
+ resp_buf[resp_len++] = MBOX_READ_RESP_BUF(rout);
+
+ rout++;
+ /* wrapping around when it reach the buffer size */
+ rout %= MBOX_RESP_BUFFER_SIZE;
+ /* update next ROUT */
+ MBOX_WRITEL(rout, MBOX_ROUT);
+ }
+
+ return resp_len;
+}
+
+/* Support one command and up to 31 words argument length only */
+static __always_inline int mbox_send_cmd_common(u8 id, u32 cmd, u8 is_indirect,
+ u32 len, u32 *arg, u8 urgent,
+ u32 *resp_buf_len,
+ u32 *resp_buf)
+{
+ u32 rin;
+ u32 resp;
+ u32 rout;
+ u32 status;
+ u32 resp_len;
+ u32 buf_len;
+ int ret;
+
+ if (urgent) {
+ /* Read status because it is toggled */
+ status = MBOX_READL(MBOX_STATUS) & MBOX_STATUS_UA_MSK;
+ /* Write urgent command to urgent register */
+ MBOX_WRITEL(cmd, MBOX_URG);
+ /* write doorbell */
+ MBOX_WRITEL(1, MBOX_DOORBELL_TO_SDM);
+ } else {
+ ret = mbox_prepare_cmd_only(id, cmd, is_indirect, len, arg);
+ if (ret)
+ return ret;
+ }
+
+ while (1) {
+ ret = 1000;
+
+ /* Wait for doorbell from SDM */
+ do {
+ if (MBOX_READL(MBOX_DOORBELL_FROM_SDM))
+ break;
+ udelay(1000);
+ } while (--ret);
+
+ if (!ret)
+ return -ETIMEDOUT;
+
+ /* clear interrupt */
+ MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM);
+
+ if (urgent) {
+ u32 new_status = MBOX_READL(MBOX_STATUS);
+
+ /* Urgent ACK is toggled */
+ if ((new_status & MBOX_STATUS_UA_MSK) ^ status)
+ return 0;
+
+ return -ECOMM;
+ }
+
+ /* read current response offset */
+ rout = MBOX_READL(MBOX_ROUT);
+
+ /* read response valid offset */
+ rin = MBOX_READL(MBOX_RIN);
+
+ if (rout != rin) {
+ /* Response received */
+ resp = MBOX_READ_RESP_BUF(rout);
+ rout++;
+ /* wrapping around when it reach the buffer size */
+ rout %= MBOX_RESP_BUFFER_SIZE;
+ /* update next ROUT */
+ MBOX_WRITEL(rout, MBOX_ROUT);
+
+ /* check client ID and ID */
+ if ((MBOX_RESP_CLIENT_GET(resp) ==
+ MBOX_CLIENT_ID_BAREBOX) &&
+ (MBOX_RESP_ID_GET(resp) == id)) {
+ int resp_err = MBOX_RESP_ERR_GET(resp);
+
+ if (resp_buf_len) {
+ buf_len = *resp_buf_len;
+ *resp_buf_len = 0;
+ } else {
+ buf_len = 0;
+ }
+
+ resp_len = MBOX_RESP_LEN_GET(resp);
+ while (resp_len) {
+ ret = mbox_polling_resp(rout);
+ if (ret)
+ return ret;
+ /* we need to process response buffer
+ * even caller doesn't need it
+ */
+ resp = MBOX_READ_RESP_BUF(rout);
+ rout++;
+ resp_len--;
+ rout %= MBOX_RESP_BUFFER_SIZE;
+ MBOX_WRITEL(rout, MBOX_ROUT);
+ if (buf_len) {
+ /* copy response to buffer */
+ resp_buf[*resp_buf_len] = resp;
+ (*resp_buf_len)++;
+ buf_len--;
+ }
+ }
+ return resp_err;
+ }
+ }
+ }
+
+ return -EIO;
+}
+
+static __always_inline int mbox_send_cmd_common_retry(u8 id, u32 cmd,
+ u8 is_indirect,
+ u32 len, u32 *arg,
+ u8 urgent,
+ u32 *resp_buf_len,
+ u32 *resp_buf)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ ret = mbox_send_cmd_common(id, cmd, is_indirect, len, arg,
+ urgent, resp_buf_len, resp_buf);
+ if (ret == MBOX_RESP_TIMEOUT || ret == MBOX_RESP_DEVICE_BUSY)
+ udelay(2000); /* wait for 2ms before resend */
+ else
+ break;
+ }
+
+ return ret;
+}
+
+int mbox_init(void)
+{
+ int ret;
+
+ /* enable mailbox interrupts */
+ MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS);
+
+ /* Ensure urgent request is cleared */
+ MBOX_WRITEL(0, MBOX_URG);
+
+ /* Ensure the Doorbell Interrupt is cleared */
+ MBOX_WRITEL(0, MBOX_DOORBELL_FROM_SDM);
+
+ ret = mbox_send_cmd(MBOX_ID_BAREBOX, MBOX_RESTART, MBOX_CMD_DIRECT, 0,
+ NULL, 1, 0, NULL);
+ if (ret)
+ return ret;
+
+ pr_debug("%s: success...\n", __func__);
+
+ /* Renable mailbox interrupts after MBOX_RESTART */
+ MBOX_WRITEL(MBOX_ALL_INTRS, MBOX_FLAGS);
+
+ return 0;
+}
+
+int mbox_qspi_close(void)
+{
+ return mbox_send_cmd(MBOX_ID_BAREBOX, MBOX_QSPI_CLOSE, MBOX_CMD_DIRECT,
+ 0, NULL, 0, 0, NULL);
+}
+
+int mbox_qspi_open(void)
+{
+ int ret;
+ u32 resp_buf[1];
+ u32 resp_buf_len;
+ u32 reg;
+ u32 clk_khz;
+
+ ret = mbox_send_cmd(MBOX_ID_BAREBOX, MBOX_QSPI_OPEN, MBOX_CMD_DIRECT,
+ 0, NULL, 0, 0, NULL);
+ if (ret) {
+ /* retry again by closing and reopen the QSPI again */
+ ret = mbox_qspi_close();
+ if (ret)
+ return ret;
+
+ ret = mbox_send_cmd(MBOX_ID_BAREBOX, MBOX_QSPI_OPEN,
+ MBOX_CMD_DIRECT, 0, NULL, 0, 0, NULL);
+ if (ret)
+ return ret;
+ }
+
+ /* HPS will directly control the QSPI controller, no longer mailbox */
+ resp_buf_len = 1;
+ ret = mbox_send_cmd(MBOX_ID_BAREBOX, MBOX_QSPI_DIRECT, MBOX_CMD_DIRECT,
+ 0, NULL, 0, (u32 *)&resp_buf_len,
+ (u32 *)&resp_buf);
+ if (ret)
+ goto error;
+
+ /* Get the QSPI clock from SDM response and save for later use */
+ clk_khz = resp_buf[0];
+ if (clk_khz < 1000)
+ return -EINVAL;
+
+ clk_khz /= 1000;
+ pr_info("QSPI: reference clock at %d kHZ\n", clk_khz);
+
+ reg = (readl(SOCFPGA_SYSMGR_ADDRESS + SYSMGR_SOC64_BOOT_SCRATCH_COLD0)) &
+ ~(SYSMGR_SCRATCH_REG_0_QSPI_REFCLK_MASK);
+
+ writel((clk_khz & SYSMGR_SCRATCH_REG_0_QSPI_REFCLK_MASK) | reg,
+ SOCFPGA_SYSMGR_ADDRESS + SYSMGR_SOC64_BOOT_SCRATCH_COLD0);
+
+ return 0;
+
+error:
+ mbox_qspi_close();
+
+ return ret;
+}
+
+int mbox_send_cmd(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg,
+ u8 urgent, u32 *resp_buf_len, u32 *resp_buf)
+{
+ return mbox_send_cmd_common_retry(id, cmd, is_indirect, len, arg,
+ urgent, resp_buf_len, resp_buf);
+}
diff --git a/arch/arm/mach-socfpga/secure_reg_helper.c b/arch/arm/mach-socfpga/secure_reg_helper.c
new file mode 100644
index 0000000000000000000000000000000000000000..fe855aec8dd79cb2ab2d82a8dd4a41134150d452
--- /dev/null
+++ b/arch/arm/mach-socfpga/secure_reg_helper.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2022 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <io.h>
+#include <mach/socfpga/secure_reg_helper.h>
+#include <mach/socfpga/smc_api.h>
+#include <mach/socfpga/soc64-regs.h>
+#include <mach/socfpga/soc64-system-manager.h>
+#include <linux/errno.h>
+#include <linux/intel-smc.h>
+
+static int socfpga_secure_convert_reg_id_to_addr(u32 id, phys_addr_t *reg_addr)
+{
+ switch (id) {
+ case SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC0:
+ *reg_addr = SOCFPGA_SYSMGR_ADDRESS + SYSMGR_SOC64_EMAC0;
+ break;
+ case SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC1:
+ *reg_addr = SOCFPGA_SYSMGR_ADDRESS + SYSMGR_SOC64_EMAC1;
+ break;
+ case SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC2:
+ *reg_addr = SOCFPGA_SYSMGR_ADDRESS + SYSMGR_SOC64_EMAC2;
+ break;
+ default:
+ return -EADDRNOTAVAIL;
+ }
+ return 0;
+}
+
+int socfpga_secure_reg_read32(u32 id, u32 *val)
+{
+ int ret;
+ u32 ret_arg[4];
+ phys_addr_t reg_addr;
+
+ ret = socfpga_secure_convert_reg_id_to_addr(id, ®_addr);
+ if (ret)
+ return ret;
+
+ ret = invoke_smc(INTEL_SIP_SMC_REG_READ, reg_addr, 0, 0, ret_arg);
+ if (ret)
+ return ret;
+
+ *val = ret_arg[0];
+
+ return 0;
+}
+
+int socfpga_secure_reg_write32(u32 id, u32 val)
+{
+ int ret;
+ phys_addr_t reg_addr;
+
+ ret = socfpga_secure_convert_reg_id_to_addr(id, ®_addr);
+ if (ret)
+ return ret;
+
+ return invoke_smc(INTEL_SIP_SMC_REG_WRITE, reg_addr, (u64) val, 0, 0);
+}
+
+int socfpga_secure_reg_update32(u32 id, u32 mask, u32 val)
+{
+ int ret;
+ phys_addr_t reg_addr;
+
+ ret = socfpga_secure_convert_reg_id_to_addr(id, ®_addr);
+ if (ret)
+ return ret;
+
+ return invoke_smc(INTEL_SIP_SMC_REG_UPDATE, reg_addr, (u64) mask, (u64) val, 0);
+}
diff --git a/arch/arm/mach-socfpga/smc_api.c b/arch/arm/mach-socfpga/smc_api.c
new file mode 100644
index 0000000000000000000000000000000000000000..2540c3301cc978ab06bafd92554efff77757579b
--- /dev/null
+++ b/arch/arm/mach-socfpga/smc_api.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020-2024 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <mach/socfpga/smc_api.h>
+#include <linux/arm-smccc.h>
+#include <linux/intel-smc.h>
+#include <linux/kernel.h>
+
+int invoke_smc(u32 func_id, u64 arg0, u64 arg1, u64 arg2, u32 *ret_payload)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(func_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+
+ if (ret_payload) {
+ ret_payload[0] = lower_32_bits(res.a0);
+ ret_payload[1] = upper_32_bits(res.a0);
+ ret_payload[2] = lower_32_bits(res.a1);
+ ret_payload[3] = upper_32_bits(res.a1);
+ }
+
+ return res.a0;
+}
+
+int smc_get_usercode(u32 *usercode)
+{
+ u32 res;
+ int ret;
+
+ if (!usercode)
+ return -EINVAL;
+
+ ret = invoke_smc(INTEL_SIP_SMC_GET_USERCODE, 0, 0, 0, &res);
+
+ if (ret == INTEL_SIP_SMC_STATUS_OK)
+ *usercode = res;
+
+ return ret;
+}
diff --git a/arch/arm/mach-socfpga/soc64-system-manager.c b/arch/arm/mach-socfpga/soc64-system-manager.c
new file mode 100644
index 0000000000000000000000000000000000000000..b66a7556975558fe460523322a00a366c9fc68a9
--- /dev/null
+++ b/arch/arm/mach-socfpga/soc64-system-manager.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016-2021 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <io.h>
+#include <mach/socfpga/soc64-handoff.h>
+#include <mach/socfpga/soc64-regs.h>
+#include <mach/socfpga/soc64-system-manager.h>
+
+/*
+ * Populate the value for SYSMGR.FPGAINTF.MODULE based on pinmux setting.
+ * The value is not wrote to SYSMGR.FPGAINTF.MODULE but
+ * CONFIG_SYSMGR_ISWGRP_HANDOFF.
+ */
+static void populate_sysmgr_fpgaintf_module(void)
+{
+ void __iomem *sysmgr = IOMEM(SOCFPGA_SYSMGR_ADDRESS);
+ u32 handoff_val = 0;
+
+ /* Enable the signal for those HPS peripherals that use FPGA. */
+ if (readl(sysmgr + SYSMGR_SOC64_NAND_USEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ handoff_val |= SYSMGR_FPGAINTF_NAND;
+ if (readl(sysmgr + SYSMGR_SOC64_SDMMC_USEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ handoff_val |= SYSMGR_FPGAINTF_SDMMC;
+ if (readl(sysmgr + SYSMGR_SOC64_SPIM0_USEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ handoff_val |= SYSMGR_FPGAINTF_SPIM0;
+ if (readl(sysmgr + SYSMGR_SOC64_SPIM1_USEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ handoff_val |= SYSMGR_FPGAINTF_SPIM1;
+ writel(handoff_val, sysmgr + SYSMGR_SOC64_FPGAINTF_EN2);
+
+ handoff_val = 0;
+ if (readl(sysmgr + SYSMGR_SOC64_EMAC0_USEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ handoff_val |= SYSMGR_FPGAINTF_EMAC0;
+ if (readl(sysmgr + SYSMGR_SOC64_EMAC1_USEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ handoff_val |= SYSMGR_FPGAINTF_EMAC1;
+ if (readl(sysmgr + SYSMGR_SOC64_EMAC2_USEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ handoff_val |= SYSMGR_FPGAINTF_EMAC2;
+ writel(handoff_val, sysmgr + SYSMGR_SOC64_FPGAINTF_EN3);
+}
+
+/*
+ * Configure all the pin muxes
+ */
+static void populate_sysmgr_pinmux(void)
+{
+ u32 len, i;
+ void __iomem *sysmgr = IOMEM(SOCFPGA_SYSMGR_ADDRESS);
+ u32 len_mux = socfpga_get_handoff_size((void __iomem *)SOC64_HANDOFF_MUX);
+ u32 len_ioctl = socfpga_get_handoff_size((void __iomem *)SOC64_HANDOFF_IOCTL);
+ u32 len_fpga = socfpga_get_handoff_size((void __iomem *)SOC64_HANDOFF_FPGA);
+ u32 len_delay = socfpga_get_handoff_size((void __iomem *)SOC64_HANDOFF_DELAY);
+
+ len = (len_mux > len_ioctl) ? len_mux : len_ioctl;
+ len = (len > len_fpga) ? len : len_fpga;
+ len = (len > len_delay) ? len : len_delay;
+
+ u32 handoff_table[len];
+
+ /* setup the pin sel */
+ len = (len_mux < SOC64_HANDOFF_MUX_LEN) ? len_mux : SOC64_HANDOFF_MUX_LEN;
+ socfpga_handoff_read(IOMEM(SOC64_HANDOFF_MUX), handoff_table, len);
+ for (i = 0; i < len; i = i + 2) {
+ writel(handoff_table[i + 1], handoff_table[i] + sysmgr +
+ SYSMGR_SOC64_PINSEL0);
+ }
+
+ /* setup the pin ctrl */
+ len = (len_ioctl < SOC64_HANDOFF_IOCTL_LEN) ? len_ioctl : SOC64_HANDOFF_IOCTL_LEN;
+ socfpga_handoff_read(IOMEM(SOC64_HANDOFF_IOCTL), handoff_table, len);
+ for (i = 0; i < len; i = i + 2) {
+ writel(handoff_table[i + 1], handoff_table[i] + sysmgr +
+ SYSMGR_SOC64_IOCTRL0);
+ }
+
+ /* setup the fpga use */
+ len = (len_fpga < SOC64_HANDOFF_FPGA_LEN) ? len_fpga : SOC64_HANDOFF_FPGA_LEN;
+ socfpga_handoff_read(IOMEM(SOC64_HANDOFF_FPGA), handoff_table, len);
+ for (i = 0; i < len; i = i + 2) {
+ writel(handoff_table[i + 1], handoff_table[i] + sysmgr +
+ SYSMGR_SOC64_EMAC0_USEFPGA);
+ }
+
+ /* setup the IO delay */
+ len = (len_delay < SOC64_HANDOFF_DELAY_LEN) ? len_delay : SOC64_HANDOFF_DELAY_LEN;
+ socfpga_handoff_read(IOMEM(SOC64_HANDOFF_DELAY), handoff_table, len);
+ for (i = 0; i < len; i = i + 2) {
+ writel(handoff_table[i + 1], handoff_table[i] + sysmgr +
+ SYSMGR_SOC64_IODELAY0);
+ }
+}
+
+/*
+ * Configure all the pin muxes
+ */
+void agilex5_sysmgr_pinmux_init(void)
+{
+ populate_sysmgr_pinmux();
+ populate_sysmgr_fpgaintf_module();
+}
diff --git a/arch/arm/mach-socfpga/soc64-wrap-handoff.c b/arch/arm/mach-socfpga/soc64-wrap-handoff.c
new file mode 100644
index 0000000000000000000000000000000000000000..c506e21001f677dd23fb5eb6cc11d06952acf20d
--- /dev/null
+++ b/arch/arm/mach-socfpga/soc64-wrap-handoff.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2022 Intel Corporation <www.intel.com>
+ *
+ */
+
+#include <common.h>
+#include <io.h>
+#include <errno.h>
+#include <mach/socfpga/agilex5-clk.h>
+#include <mach/socfpga/soc64-handoff.h>
+
+enum endianness {
+ LITTLE_ENDIAN = 0,
+ BIG_ENDIAN,
+ UNKNOWN_ENDIANNESS
+};
+
+static enum endianness check_endianness(u32 handoff)
+{
+ switch (handoff) {
+ case SOC64_HANDOFF_MAGIC_BOOT:
+ case SOC64_HANDOFF_MAGIC_MUX:
+ case SOC64_HANDOFF_MAGIC_IOCTL:
+ case SOC64_HANDOFF_MAGIC_FPGA:
+ case SOC64_HANDOFF_MAGIC_DELAY:
+ case SOC64_HANDOFF_MAGIC_PERI:
+ case SOC64_HANDOFF_MAGIC_SDRAM:
+ case SOC64_HANDOFF_MAGIC_CLOCK:
+ return BIG_ENDIAN;
+ default:
+ return UNKNOWN_ENDIANNESS;
+ }
+}
+
+static int getting_endianness(void __iomem *handoff_address, enum endianness *endian_t)
+{
+ /* Checking handoff data is little endian ? */
+ *endian_t = check_endianness(readl(handoff_address));
+
+ if (*endian_t == UNKNOWN_ENDIANNESS) {
+ /* Trying to check handoff data is big endian? */
+ *endian_t = check_endianness(swab32(readl(handoff_address)));
+ if (*endian_t == UNKNOWN_ENDIANNESS)
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+const struct cm_config * const cm_get_default_config(void)
+{
+ struct cm_config *cm_handoff_cfg = (struct cm_config *)
+ (SOC64_HANDOFF_CLOCK + SOC64_HANDOFF_OFFSET_DATA);
+ u32 *conversion = (u32 *)cm_handoff_cfg;
+ u32 handoff_clk = readl(SOC64_HANDOFF_CLOCK);
+ u32 i;
+
+ if (swab32(handoff_clk) == SOC64_HANDOFF_MAGIC_CLOCK) {
+ writel(swab32(handoff_clk), SOC64_HANDOFF_CLOCK);
+ for (i = 0; i < (sizeof(*cm_handoff_cfg) / sizeof(u32)); i++)
+ conversion[i] = swab32(conversion[i]);
+ return cm_handoff_cfg;
+ } else if (handoff_clk == SOC64_HANDOFF_MAGIC_CLOCK) {
+ return cm_handoff_cfg;
+ }
+
+ return NULL;
+}
+
+int socfpga_get_handoff_size(void __iomem *handoff_address)
+{
+ u32 size;
+ int ret;
+ enum endianness endian_t;
+
+ ret = getting_endianness(handoff_address, &endian_t);
+ if (ret)
+ return ret;
+
+ size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
+ if (endian_t == BIG_ENDIAN)
+ size = swab32(size);
+
+ size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
+
+ return size;
+}
+
+int socfpga_handoff_read(void __iomem *handoff_address, void *table, u32 table_len)
+{
+ u32 temp;
+ u32 *table_x32 = table;
+ u32 i = 0;
+ int ret;
+ enum endianness endian_t;
+
+ ret = getting_endianness(handoff_address, &endian_t);
+ if (ret)
+ return ret;
+
+ temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
+ (i * sizeof(u32)));
+
+ if (endian_t == BIG_ENDIAN)
+ *table_x32 = swab32(temp);
+ else if (endian_t == LITTLE_ENDIAN)
+ *table_x32 = temp;
+
+ for (i = 1; i < table_len; i++) {
+ table_x32++;
+
+ temp = readl(handoff_address +
+ SOC64_HANDOFF_OFFSET_DATA +
+ (i * sizeof(u32)));
+
+ if (endian_t == BIG_ENDIAN)
+ *table_x32 = swab32(temp);
+ else if (endian_t == LITTLE_ENDIAN)
+ *table_x32 = temp;
+ }
+
+ return 0;
+}
diff --git a/common/Kconfig.debug_ll b/common/Kconfig.debug_ll
index 1f9255b1a45bce4f432ca8a3462352ded7dc5504..28c0ed496d915a25a3fbdee07a71eb80a45bde7d 100644
--- a/common/Kconfig.debug_ll
+++ b/common/Kconfig.debug_ll
@@ -239,6 +239,20 @@ config DEBUG_SOCFPGA_UART1
Say Y here if you want kernel low-level debugging support
on SOCFPGA(Arria 10) based platforms.
+config DEBUG_SOCFPGA_AGILEX5_UART0
+ bool "Use Agilex5 UART0 for low-level debug"
+ depends on ARCH_SOCFPGA_AGILEX5
+ help
+ Say Y here if you want kernel low-level debugging support
+ on Agilex5 based platforms.
+
+config DEBUG_SOCFPGA_AGILEX5_UART1
+ bool "Use Agilex5 UART1 for low-level debug"
+ depends on ARCH_SOCFPGA_AGILEX5
+ help
+ Say Y here if you want kernel low-level debugging support
+ on Agilex5 based platforms.
+
config DEBUG_STM32MP_UART
bool "Use STM32MP UART4 for low-level debug"
depends on ARCH_STM32
@@ -420,12 +434,15 @@ config DEBUG_SOCFPGA_UART_PHYS_ADDR
hex "Physical base address of debug UART" if DEBUG_LL
default 0xffc02000 if DEBUG_SOCFPGA_UART0
default 0xffc02100 if DEBUG_SOCFPGA_UART1
+ default 0x10c02000 if DEBUG_SOCFPGA_AGILEX5_UART0
+ default 0x10c02100 if DEBUG_SOCFPGA_AGILEX5_UART1
depends on ARCH_SOCFPGA
config DEBUG_SOCFPGA_UART_CLOCK
int "SoCFPGA UART debug clock" if DEBUG_LL
default 100000000 if ARCH_SOCFPGA_CYCLONE5
default 50000000 if ARCH_SOCFPGA_ARRIA10
+ default 100000000 if ARCH_SOCFPGA_AGILEX5
depends on ARCH_SOCFPGA
help
Choose UART root clock.
diff --git a/firmware/Kconfig b/firmware/Kconfig
index ae7bbdc71e3a37ae485d52c7719c4da150ebac40..76c47a9fe8715038ced200557ee56b359358f725 100644
--- a/firmware/Kconfig
+++ b/firmware/Kconfig
@@ -41,6 +41,9 @@ config FIRMWARE_IMX8MQ_ATF
config FIRMWARE_IMX93_ATF
bool
+config FIRMWARE_AGILEX5_ATF
+ bool
+
config FIRMWARE_IMX8MM_OPTEE
bool "install OP-TEE on i.MX8MM boards"
depends on FIRMWARE_IMX8MM_ATF && PBL_OPTEE
diff --git a/firmware/Makefile b/firmware/Makefile
index 7265c55c4253e91b9d3f8fa1cf4fb416ed459826..e01b6d4ee02d0eb9b04e765dc60d9dfea5a938a9 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -17,6 +17,7 @@ pbl-firmware-$(CONFIG_FIRMWARE_IMX8MN_ATF) += imx8mn-bl31.bin$(if $(CONFIG_FIRMW
pbl-firmware-$(CONFIG_FIRMWARE_IMX8MP_ATF) += imx8mp-bl31.bin$(if $(CONFIG_FIRMWARE_IMX8MP_OPTEE),-optee,)
pbl-firmware-$(CONFIG_FIRMWARE_IMX8MQ_ATF) += imx8mq-bl31.bin
pbl-firmware-$(CONFIG_FIRMWARE_IMX93_ATF) += imx93-bl31.bin$(if $(CONFIG_FIRMWARE_IMX93_OPTEE),-optee,)
+pbl-firmware-$(CONFIG_FIRMWARE_AGILEX5_ATF) += agilex5-bl31.bin
fw-external-$(CONFIG_FIRMWARE_IMX8MM_OPTEE) += imx8mm-bl32.bin
fw-external-$(CONFIG_FIRMWARE_IMX8MN_OPTEE) += imx8mn-bl32.bin
fw-external-$(CONFIG_FIRMWARE_IMX8MP_OPTEE) += imx8mp-bl32.bin
diff --git a/images/Makefile.socfpga b/images/Makefile.socfpga
index 7f95bed03297e616532ffb38cb36742b155146f5..807ca78e4ac8636382107f844eeb83ba9007a583 100644
--- a/images/Makefile.socfpga
+++ b/images/Makefile.socfpga
@@ -14,6 +14,14 @@ quiet_cmd_socfpga_image = SOCFPGA-IMG $@
$(obj)/%.socfpgaimg: $(obj)/% FORCE
$(call if_changed,socfpga_image)
+# %.hex - convert into Intel hex format
+# ----------------------------------------------------------------
+quiet_cmd_socfpga_objcopy = SOCFPGA-OBJCOPY $@
+ cmd_socfpga_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) -I binary -O ihex --change-address=0x0 $< $@
+
+$(obj)/%.hex: $(obj)/% FORCE
+ $(call if_changed,socfpga_objcopy)
+
# ----------------------- Cyclone5 based boards ---------------------------
pblb-$(CONFIG_MACH_SOCFPGA_ALTERA_SOCDK) += start_socfpga_socdk_xload
FILE_barebox-socfpga-socdk-xload.img = start_socfpga_socdk_xload.pblb.socfpgaimg
diff --git a/include/dt-bindings/clock/agilex5-clock.h b/include/dt-bindings/clock/agilex5-clock.h
new file mode 100644
index 0000000000000000000000000000000000000000..269108465387c0becb165d5fdc5d5eb4460ed9c8
--- /dev/null
+++ b/include/dt-bindings/clock/agilex5-clock.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019-2022, Intel Corporation
+ */
+
+#ifndef __AGILEX5_CLOCK_H
+#define __AGILEX5_CLOCK_H
+
+/* fixed rate clocks */
+#define AGILEX5_OSC1 0
+#define AGILEX5_CB_INTOSC_HS_DIV2_CLK 1
+#define AGILEX5_CB_INTOSC_LS_CLK 2
+#define AGILEX5_L4_SYS_FREE_CLK 3
+#define AGILEX5_F2S_FREE_CLK 4
+
+/* PLL clocks */
+#define AGILEX5_MAIN_PLL_CLK 5
+#define AGILEX5_MAIN_PLL_C0_CLK 6
+#define AGILEX5_MAIN_PLL_C1_CLK 7
+#define AGILEX5_MAIN_PLL_C2_CLK 8
+#define AGILEX5_MAIN_PLL_C3_CLK 9
+#define AGILEX5_PERIPH_PLL_CLK 10
+#define AGILEX5_PERIPH_PLL_C0_CLK 11
+#define AGILEX5_PERIPH_PLL_C1_CLK 12
+#define AGILEX5_PERIPH_PLL_C2_CLK 13
+#define AGILEX5_PERIPH_PLL_C3_CLK 14
+#define AGILEX5_MPU_FREE_CLK 15
+#define AGILEX5_MPU_CCU_CLK 16
+#define AGILEX5_BOOT_CLK 17
+
+/* fixed factor clocks */
+#define AGILEX5_L3_MAIN_FREE_CLK 18
+#define AGILEX5_NOC_FREE_CLK 19
+#define AGILEX5_S2F_USR0_CLK 20
+#define AGILEX5_NOC_CLK 21
+#define AGILEX5_EMAC_A_FREE_CLK 22
+#define AGILEX5_EMAC_B_FREE_CLK 23
+#define AGILEX5_EMAC_PTP_FREE_CLK 24
+#define AGILEX5_GPIO_DB_FREE_CLK 25
+#define AGILEX5_SDMMC_FREE_CLK 26
+#define AGILEX5_S2F_USER0_FREE_CLK 27
+#define AGILEX5_S2F_USER1_FREE_CLK 28
+#define AGILEX5_PSI_REF_FREE_CLK 29
+
+/* Gate clocks */
+#define AGILEX5_MPU_CLK 30
+#define AGILEX5_MPU_PERIPH_CLK 31
+#define AGILEX5_L4_MAIN_CLK 32
+#define AGILEX5_L4_MP_CLK 33
+#define AGILEX5_L4_SP_CLK 34
+#define AGILEX5_CS_AT_CLK 35
+#define AGILEX5_CS_TRACE_CLK 36
+#define AGILEX5_CS_PDBG_CLK 37
+#define AGILEX5_CS_TIMER_CLK 38
+#define AGILEX5_S2F_USER0_CLK 39
+#define AGILEX5_EMAC0_CLK 40
+#define AGILEX5_EMAC1_CLK 41
+#define AGILEX5_EMAC2_CLK 42
+#define AGILEX5_EMAC_PTP_CLK 43
+#define AGILEX5_GPIO_DB_CLK 44
+#define AGILEX5_NAND_CLK 45
+#define AGILEX5_PSI_REF_CLK 46
+#define AGILEX5_S2F_USER1_CLK 47
+#define AGILEX5_SDMMC_CLK 48
+#define AGILEX5_SPI_M_CLK 49
+#define AGILEX5_USB_CLK 50
+#define AGILEX5_NAND_X_CLK 51
+#define AGILEX5_NAND_ECC_CLK 52
+#define AGILEX5_NUM_CLKS 53
+
+#endif /* __AGILEX5_CLOCK_H */
diff --git a/include/linux/intel-smc.h b/include/linux/intel-smc.h
new file mode 100644
index 0000000000000000000000000000000000000000..e15fa3d4da21a4da61c759bf26d66a9f4d769210
--- /dev/null
+++ b/include/linux/intel-smc.h
@@ -0,0 +1,545 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017-2018, Intel Corporation
+ */
+
+#ifndef __INTEL_SMC_H
+#define __INTEL_SMC_H
+
+#include <linux/arm-smccc.h>
+#include <linux/bitops.h>
+
+/*
+ * This file defines the Secure Monitor Call (SMC) message protocol used for
+ * service layer driver in normal world (EL1) to communicate with secure
+ * monitor software in Secure Monitor Exception Level 3 (EL3).
+ *
+ * This file is shared with secure firmware (FW) which is out of u-boot tree.
+ *
+ * An ARM SMC instruction takes a function identifier and up to 6 64-bit
+ * register values as arguments, and can return up to 4 64-bit register
+ * values. The operation of the secure monitor is determined by the parameter
+ * values passed in through registers.
+
+ * EL1 and EL3 communicates pointer as physical address rather than the
+ * virtual address.
+ */
+
+/*
+ * Functions specified by ARM SMC Calling convention:
+ *
+ * FAST call executes atomic operations, returns when the requested operation
+ * has completed.
+ * STD call starts a operation which can be preempted by a non-secure
+ * interrupt. The call can return before the requested operation has
+ * completed.
+ *
+ * a0..a7 is used as register names in the descriptions below, on arm32
+ * that translates to r0..r7 and on arm64 to w0..w7.
+ */
+
+#define INTEL_SIP_SMC_STD_CALL_VAL(func_num) \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_SIP, (func_num))
+
+#define INTEL_SIP_SMC_FAST_CALL_VAL(func_num) \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_SIP, (func_num))
+
+/*
+ * Return values in INTEL_SIP_SMC_* call
+ *
+ * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION:
+ * Secure monitor software doesn't recognize the request.
+ *
+ * INTEL_SIP_SMC_STATUS_OK:
+ * SMC call completed successfully,
+ * In case of FPGA configuration write operation, it means secure monitor
+ * software can accept the next chunk of FPGA configuration data.
+ *
+ * INTEL_SIP_SMC_STATUS_BUSY:
+ * In case of FPGA configuration write operation, it means secure monitor
+ * software is still processing previous data & can't accept the next chunk
+ * of data. Service driver needs to issue
+ * INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE call to query the
+ * completed block(s).
+ *
+ * INTEL_SIP_SMC_STATUS_ERROR:
+ * There is error during the SMC call process.
+ *
+ * INTEL_SIP_SMC_REG_ERROR:
+ * There is error during a read or write operation of the protected
+ * registers.
+ */
+#define INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF
+#define INTEL_SIP_SMC_STATUS_OK 0x0
+#define INTEL_SIP_SMC_STATUS_BUSY 0x1
+#define INTEL_SIP_SMC_STATUS_REJECTED 0x2
+#define INTEL_SIP_SMC_STATUS_ERROR 0x4
+#define INTEL_SIP_SMC_REG_ERROR 0x5
+#define INTEL_SIP_SMC_RSU_ERROR 0x7
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_START
+ *
+ * Sync call used by service driver at EL1 to request the FPGA in EL3 to
+ * be prepare to receive a new configuration.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_START.
+ * a1: flag for full or partial configuration
+ * 0 full reconfiguration.
+ * 1 partial reconfiguration.
+ * a2-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, or INTEL_SIP_SMC_STATUS_ERROR.
+ * a1-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_START 1
+#define INTEL_SIP_SMC_FPGA_CONFIG_START \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_START)
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_WRITE
+ *
+ * Async call used by service driver at EL1 to provide FPGA configuration data
+ * to secure world.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_WRITE.
+ * a1: 64bit physical address of the configuration data memory block
+ * a2: Size of configuration data block.
+ * a3-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_BUSY,
+ * INTEL_SIP_SMC_STATUS_REJECTED or INTEL_SIP_SMC_STATUS_ERROR.
+ * a1: 64bit physical address of 1st completed memory block if any completed
+ * block, otherwise zero value.
+ * a2: 64bit physical address of 2nd completed memory block if any completed
+ * block, otherwise zero value.
+ * a3: 64bit physical address of 3rd completed memory block if any completed
+ * block, otherwise zero value.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_WRITE 2
+#define INTEL_SIP_SMC_FPGA_CONFIG_WRITE \
+ INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_WRITE)
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE
+ *
+ * Sync call used by service driver at EL1 to track the completed write
+ * transactions. This request is called after INTEL_SIP_SMC_FPGA_CONFIG_WRITE
+ * call returns INTEL_SIP_SMC_STATUS_BUSY.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_BUSY or
+ * INTEL_SIP_SMC_STATUS_ERROR.
+ * a1: 64bit physical address of 1st completed memory block.
+ * a2: 64bit physical address of 2nd completed memory block if
+ * any completed block, otherwise zero value.
+ * a3: 64bit physical address of 3rd completed memory block if
+ * any completed block, otherwise zero value.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE 3
+#define INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE \
+INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE)
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_ISDONE
+ *
+ * Sync call used by service driver at EL1 to inform secure world that all
+ * data are sent, to check whether or not the secure world had completed
+ * the FPGA configuration process.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_ISDONE.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_STATUS_BUSY or
+ * INTEL_SIP_SMC_STATUS_ERROR.
+ * a1-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_ISDONE 4
+#define INTEL_SIP_SMC_FPGA_CONFIG_ISDONE \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_ISDONE)
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM
+ *
+ * Sync call used by service driver at EL1 to query the physical address of
+ * memory block reserved by secure monitor software.
+ *
+ * Call register usage:
+ * a0:INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR.
+ * a1: start of physical address of reserved memory block.
+ * a2: size of reserved memory block.
+ * a3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_GET_MEM 5
+#define INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_GET_MEM)
+
+/*
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK
+ *
+ * For SMC loop-back mode only, used for internal integration, debugging
+ * or troubleshooting.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR.
+ * a1-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_LOOPBACK 6
+#define INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_LOOPBACK)
+
+/*
+ * Request INTEL_SIP_SMC_REG_READ
+ *
+ * Read a protected register using SMCCC
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_REG_READ.
+ * a1: register address.
+ * a2-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR.
+ * a1: Value in the register
+ * a2-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_REG_READ 7
+#define INTEL_SIP_SMC_REG_READ \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_READ)
+
+/*
+ * Request INTEL_SIP_SMC_REG_WRITE
+ *
+ * Write a protected register using SMCCC
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_REG_WRITE.
+ * a1: register address
+ * a2: value to program into register.
+ * a3-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR.
+ * a1-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_REG_WRITE 8
+#define INTEL_SIP_SMC_REG_WRITE \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_WRITE)
+
+/*
+ * Request INTEL_SIP_SMC_FUNCID_REG_UPDATE
+ *
+ * Update one or more bits in a protected register using a
+ * read-modify-write operation.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_REG_UPDATE.
+ * a1: register address
+ * a2: Write Mask.
+ * a3: Value to write.
+ * a4-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR.
+ * a1-3: Not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_REG_UPDATE 9
+#define INTEL_SIP_SMC_REG_UPDATE \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_UPDATE)
+
+/*
+* Request INTEL_SIP_SMC_RSU_STATUS
+*
+* Sync call used by service driver at EL1 to query the RSU status
+*
+* Call register usage:
+* a0 INTEL_SIP_SMC_RSU_STATUS
+* a1-7 not used
+*
+* Return status
+* a0: Current Image
+* a1: Last Failing Image
+* a2: Version [width 32 bit] | State [width 32 bit]
+* a3: Error details [width 32 bit] | Error location [width 32 bit]
+*
+* Or
+*
+* a0: INTEL_SIP_SMC_RSU_ERROR
+*/
+#define INTEL_SIP_SMC_FUNCID_RSU_STATUS 11
+#define INTEL_SIP_SMC_RSU_STATUS \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_STATUS)
+
+/*
+* Request INTEL_SIP_SMC_RSU_UPDATE
+*
+* Sync call used by service driver at EL1 to tell you next reboot is RSU_UPDATE
+*
+* Call register usage:
+* a0 INTEL_SIP_SMC_RSU_UPDATE
+* a1 64bit physical address of the configuration data memory in flash
+* a2-7 not used
+*
+* Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+*/
+#define INTEL_SIP_SMC_FUNCID_RSU_UPDATE 12
+#define INTEL_SIP_SMC_RSU_UPDATE \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_UPDATE)
+
+/*
+ * Request INTEL_SIP_SMC_ECC_DBE
+ *
+ * Sync call used by service driver at EL1 alert EL3 that a Double Bit
+ * ECC error has occurred.
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_ECC_DBE
+ * a1 SysManager Double Bit Error value
+ * a2-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ */
+#define INTEL_SIP_SMC_FUNCID_ECC_DBE 13
+#define INTEL_SIP_SMC_ECC_DBE \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_ECC_DBE)
+
+/*
+* Request INTEL_SIP_SMC_RSU_NOTIFY
+*
+* Sync call used by service driver at EL1 to report HPS software execution stage
+*
+* Call register usage:
+* a0 INTEL_SIP_SMC_RSU_NOTIFY
+* a1 32bit HPS software execution stage
+* a2-7 not used
+*
+* Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_REG_ERROR.
+*/
+#define INTEL_SIP_SMC_FUNCID_RSU_NOTIFY 14
+#define INTEL_SIP_SMC_RSU_NOTIFY \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_NOTIFY)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_RETRY_COUNTER
+ *
+ * Sync call used by service driver at EL1 to query the RSU retry counter
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_RETRY_COUNTER
+ * a1-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_RSU_ERROR.
+ * a1 retry counter
+*/
+#define INTEL_SIP_SMC_FUNCID_RSU_RETRY_COUNTER 15
+#define INTEL_SIP_SMC_RSU_RETRY_COUNTER \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_RETRY_COUNTER)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_DCMF_VERSION
+ *
+ * Sync call used by service driver at EL1 to query DCMF version
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_DCMF_VERSION
+ * a1-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ * a1 dcmf1 version | dcmf0 version
+ * a2 dcmf3 version | dcmf2 version
+ *
+ * Or
+ *
+ * a0 INTEL_SIP_SMC_RSU_ERROR
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_DCMF_VERSION 16
+#define INTEL_SIP_SMC_RSU_DCMF_VERSION \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_DCMF_VERSION)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION
+ *
+ * Sync call used by SSBL (EL2) to copy DCMF version to ATF memory
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION
+ * a1 dcmf1 version | dcmf0 version
+ * a2 dcmf3 version | dcmf2 version
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_VERSION 17
+#define INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_VERSION)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_MAX_RETRY
+ *
+ * Sync call used by service driver at EL1 to query max_retry parameter
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_MAX_RETRY
+ * a1-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ * a1 max_retry
+ *
+ * Or
+ *
+ * a0 INTEL_SIP_SMC_RSU_ERROR
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_MAX_RETRY 18
+#define INTEL_SIP_SMC_RSU_MAX_RETRY \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_MAX_RETRY)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_COPY_MAX_RETRY
+ *
+ * Sync call used by SSBL (EL2) to copy RSU 'max retry' to ATF memory
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_COPY_MAX_RETRY
+ * a1 max retry
+ * a2-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_COPY_MAX_RETRY 19
+#define INTEL_SIP_SMC_RSU_COPY_MAX_RETRY \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_COPY_MAX_RETRY)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_DCMF_STATUS
+ *
+ * Sync call used by service driver at EL1 to query DCMF status
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_DCMF_STATUS
+ * a1-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ * a1 dcmf3 status | dcmf2 status | dcmf1 status | dcmf0 status
+ *
+ * Or
+ *
+ * a0 INTEL_SIP_SMC_RSU_ERROR
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_DCMF_STATUS 20
+#define INTEL_SIP_SMC_RSU_DCMF_STATUS \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_DCMF_STATUS)
+
+/*
+ * Request INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS
+ *
+ * Sync call used by SSBL (EL2) to copy RSU 'dcmf status' to ATF memory
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS
+ * a1 dcmf status
+ * a2-7 not used
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ */
+#define INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_STATUS 21
+#define INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_RSU_COPY_DCMF_STATUS)
+
+/*
+ * Request INTEL_SIP_SMC_HPS_SET_BRIDGES
+ *
+ * Enable/disable the SoC FPGA bridges
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_HPS_SET_BRIDGES
+ * a1 Set bridges status:
+ * Bit 0: 0 - Disable, 1 - Enable
+ * Bit 1: 1 - Has mask value in a2
+ * a2 Mask value
+ * Bit 0: soc2fpga
+ * Bit 1: lwhps2fpga
+ * Bit 2: fpga2soc
+ * Bit 3: f2sdram0 (For Stratix 10 only)
+ * Bit 4: f2sdram1 (For Stratix 10 only)
+ * Bit 5: f2sdram2 (For Stratix 10 only)
+ * a3-7 not used
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK
+ */
+#define INTEL_SIP_SMC_FUNCID_HPS_SET_BRIDGES 50
+#define INTEL_SIP_SMC_HPS_SET_BRIDGES \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_HPS_SET_BRIDGES)
+
+/*
+ * Request INTEL_SIP_SMC_MBOX_SEND_CMD
+ *
+ * Send mailbox command to SDM
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_MBOX_SEND_CMD
+ * a1 Mailbox command
+ * a2 64bit physical address pointer to command's arguments
+ * a3 Length of the argument
+ * a4 Urgent command:
+ * 0 - Disable
+ * 1 - Enable
+ * a5 64bit physical address pointer to a buffer for receiving responses
+ * a6 Length of the buffer
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR
+ * a1 Status of mailbox response
+ * a2 Received length in the buffer
+ */
+#define INTEL_SIP_SMC_FUNCID_MBOX_SEND_CMD 60
+#define INTEL_SIP_SMC_MBOX_SEND_CMD \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_MBOX_SEND_CMD)
+
+/*
+ * Request INTEL_SIP_SMC_GET_USERCODE
+ *
+ * Send mailbox command to get usercode from SDM
+ *
+ * Call register usage:
+ * a0 INTEL_SIP_SMC_GET_USERCODE
+ * a1-7 not used.
+ *
+ * Return status
+ * a0 INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_STATUS_ERROR
+ * a1 User code
+ * a2-3 not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_GET_USERCODE 61
+#define INTEL_SIP_SMC_GET_USERCODE \
+ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_GET_USERCODE)
+
+#endif
diff --git a/include/mach/socfpga/agilex5-clk.h b/include/mach/socfpga/agilex5-clk.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f689db4f0481c0ec353843b15387d94066337d5
--- /dev/null
+++ b/include/mach/socfpga/agilex5-clk.h
@@ -0,0 +1,266 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019-2022 Intel Corporation <www.intel.com>
+ */
+
+#ifndef _CLK_AGILEX5_
+#define _CLK_AGILEX5_
+
+#ifndef __ASSEMBLY__
+#include <linux/bitops.h>
+#endif
+
+#define CLKMGR_INTOSC_HZ 400000000
+
+#define CM_REG_READL(plat, reg) \
+ readl((plat)->regs + (reg))
+
+#define CM_REG_WRITEL(plat, data, reg) \
+ writel(data, (plat)->regs + (reg))
+
+#define CM_REG_CLRBITS(plat, reg, clear) \
+ clrbits_le32((plat)->regs + (reg), (clear))
+
+#define CM_REG_SETBITS(plat, reg, set) \
+ setbits_le32((plat)->regs + (reg), (set))
+
+struct cm_config {
+ /* main group */
+ u32 main_pll_nocclk;
+ u32 main_pll_nocdiv;
+ u32 main_pll_pllglob;
+ u32 main_pll_fdbck;
+ u32 main_pll_pllc0;
+ u32 main_pll_pllc1;
+ u32 main_pll_pllc2;
+ u32 main_pll_pllc3;
+ u32 main_pll_pllm;
+
+ /* peripheral group */
+ u32 per_pll_emacctl;
+ u32 per_pll_gpiodiv;
+ u32 per_pll_pllglob;
+ u32 per_pll_fdbck;
+ u32 per_pll_pllc0;
+ u32 per_pll_pllc1;
+ u32 per_pll_pllc2;
+ u32 per_pll_pllc3;
+ u32 per_pll_pllm;
+
+ /* control group */
+ u32 ctl_emacactr;
+ u32 ctl_emacbctr;
+ u32 ctl_emacptpctr;
+ u32 ctl_gpiodbctr;
+ u32 ctl_s2fuser0ctr;
+ u32 ctl_s2fuser1ctr;
+ u32 ctl_psirefctr;
+ u32 ctl_usb31ctr;
+ u32 ctl_dsuctr;
+ u32 ctl_core01ctr;
+ u32 ctl_core23ctr;
+ u32 ctl_core2ctr;
+ u32 ctl_core3ctr;
+
+
+ /* incoming clock */
+ u32 hps_osc_clk_hz;
+ u32 fpga_clk_hz;
+ u32 spare[3];
+};
+
+/* Clock Manager registers */
+#define CLKMGR_CTRL 0
+#define CLKMGR_STAT 4
+#define CLKMGR_TESTIOCTRL 8
+#define CLKMGR_INTRGEN 0x0c
+#define CLKMGR_INTRMSK 0x10
+#define CLKMGR_INTRCLR 0x14
+#define CLKMGR_INTRSTS 0x18
+#define CLKMGR_INTRSTK 0x1c
+#define CLKMGR_INTRRAW 0x20
+
+/* Clock Manager Main PPL group registers */
+#define CLKMGR_MAINPLL_EN 0x24
+#define CLKMGR_MAINPLL_ENS 0x28
+#define CLKMGR_MAINPLL_ENR 0x2c
+#define CLKMGR_MAINPLL_BYPASS 0x30
+#define CLKMGR_MAINPLL_BYPASSS 0x34
+#define CLKMGR_MAINPLL_BYPASSR 0x38
+#define CLKMGR_MAINPLL_NOCCLK 0x40
+#define CLKMGR_MAINPLL_NOCDIV 0x44
+#define CLKMGR_MAINPLL_PLLGLOB 0x48
+#define CLKMGR_MAINPLL_FDBCK 0x4c
+#define CLKMGR_MAINPLL_MEM 0x50
+#define CLKMGR_MAINPLL_MEMSTAT 0x54
+#define CLKMGR_MAINPLL_VCOCALIB 0x58
+#define CLKMGR_MAINPLL_PLLC0 0x5c
+#define CLKMGR_MAINPLL_PLLC1 0x60
+#define CLKMGR_MAINPLL_PLLC2 0x64
+#define CLKMGR_MAINPLL_PLLC3 0x68
+#define CLKMGR_MAINPLL_PLLM 0x6c
+#define CLKMGR_MAINPLL_FHOP 0x70
+#define CLKMGR_MAINPLL_SSC 0x74
+#define CLKMGR_MAINPLL_LOSTLOCK 0x78
+
+/* Clock Manager Peripheral PPL group registers */
+#define CLKMGR_PERPLL_EN 0x7c
+#define CLKMGR_PERPLL_ENS 0x80
+#define CLKMGR_PERPLL_ENR 0x84
+#define CLKMGR_PERPLL_BYPASS 0x88
+#define CLKMGR_PERPLL_BYPASSS 0x8c
+#define CLKMGR_PERPLL_BYPASSR 0x90
+#define CLKMGR_PERPLL_EMACCTL 0x94
+#define CLKMGR_PERPLL_GPIODIV 0x98
+#define CLKMGR_PERPLL_PLLGLOB 0x9c
+#define CLKMGR_PERPLL_FDBCK 0xa0
+#define CLKMGR_PERPLL_MEM 0xa4
+#define CLKMGR_PERPLL_MEMSTAT 0xa8
+#define CLKMGR_PERPLL_VCOCALIB 0xac
+#define CLKMGR_PERPLL_PLLC0 0xb0
+#define CLKMGR_PERPLL_PLLC1 0xb4
+#define CLKMGR_PERPLL_PLLC2 0xb8
+#define CLKMGR_PERPLL_PLLC3 0xbc
+#define CLKMGR_PERPLL_PLLM 0xc0
+#define CLKMGR_PERPLL_FHOP 0xc4
+#define CLKMGR_PERPLL_SSC 0xc8
+#define CLKMGR_PERPLL_LOSTLOCK 0xcc
+
+/* Clock Manager Control group registers */
+#define CLKMGR_CTL_JTAG 0xd0
+#define CLKMGR_CTL_EMACACTR 0xd4
+#define CLKMGR_CTL_EMACBCTR 0xd8
+#define CLKMGR_CTL_EMACPTPCTR 0xdc
+#define CLKMGR_CTL_GPIODBCTR 0xe0
+#define CLKMGR_CTL_S2FUSER0CTR 0xe8
+#define CLKMGR_CTL_S2FUSER1CTR 0xec
+#define CLKMGR_CTL_PSIREFCTR 0xf0
+#define CLKMGR_CTL_EXTCNTRST 0xf4
+#define CLKMGR_CTL_USB31CTR 0xf8
+#define CLKMGR_CTL_DSUCTR 0xfc
+#define CLKMGR_CTL_CORE01CTR 0x100
+#define CLKMGR_CTL_CORE23CTR 0x104
+#define CLKMGR_CTL_CORE2CTR 0x108
+#define CLKMGR_CTL_CORE3CTR 0x10C
+
+#define CLKMGR_CTRL_BOOTMODE BIT(0)
+
+#define CLKMGR_STAT_BUSY BIT(0)
+#define CLKMGR_STAT_MAINPLL_LOCKED BIT(8)
+#define CLKMGR_STAT_MAIN_TRANS BIT(9)
+#define CLKMGR_STAT_PERPLL_LOCKED BIT(16)
+#define CLKMGR_STAT_PERF_TRANS BIT(17)
+#define CLKMGR_STAT_BOOTMODE BIT(24)
+#define CLKMGR_STAT_BOOTCLKSRC BIT(25)
+
+#define CLKMGR_STAT_ALLPLL_LOCKED_MASK \
+ (CLKMGR_STAT_MAINPLL_LOCKED | CLKMGR_STAT_PERPLL_LOCKED)
+
+#define CLKMGR_INTER_MAINPLLLOCKED_MASK 0x00000001
+#define CLKMGR_INTER_PERPLLLOCKED_MASK 0x00000002
+#define CLKMGR_INTER_MAINPLLLOST_MASK 0x00000004
+#define CLKMGR_INTER_PERPLLLOST_MASK 0x00000008
+
+#define CLKMGR_CLKSRC_MASK GENMASK(18, 16)
+#define CLKMGR_CLKSRC_OFFSET 16
+#define CLKMGR_CLKSRC_MAIN 0
+#define CLKMGR_CLKSRC_PER 1
+#define CLKMGR_CLKSRC_OSC1 2
+#define CLKMGR_CLKSRC_INTOSC 3
+#define CLKMGR_CLKSRC_FPGA 4
+#define CLKMGR_CLKCNT_MSK GENMASK(10, 0)
+
+#define CLKMGR_BYPASS_MAINPLL_ALL 0xf6
+#define CLKMGR_BYPASS_PERPLL_ALL 0xef
+
+#define CLKMGR_NOCDIV_SOFTPHY_DIV_ONE 0
+#define CLKMGR_NOCDIV_SOFTPHY_DIV_TWO 1
+#define CLKMGR_NOCDIV_SOFTPHY_DIV_FOUR 2
+#define CLKMGR_NOCDIV_L4SYSFREECLK_OFFSET 0
+#define CLKMGR_NOCDIV_L4MPCLK_OFFSET 4
+#define CLKMGR_NOCDIV_L4SPCLK_OFFSET 6
+#define CLKMGR_NOCDIV_SOFTPHY_OFFSET 16
+#define CLKMGR_NOCDIV_CCU_OFFSET 18
+#define CLKMGR_NOCDIV_MPUPERIPH_OFFSET 20
+#define CLKMGR_NOCDIV_CSATCLK_OFFSET 24
+#define CLKMGR_NOCDIV_CSTRACECLK_OFFSET 26
+#define CLKMGR_NOCDIV_CSPDBGCLK_OFFSET 28
+#define CLKMGR_NOCDIV_DIVIDER_MASK 0x3
+
+#define CLKMGR_PLLGLOB_PD_MASK BIT(0)
+#define CLKMGR_PLLGLOB_RST_MASK BIT(1)
+#define CLKMGR_PLLGLOB_AREFCLKDIV_MASK GENMASK(11, 8)
+#define CLKMGR_PLLGLOB_DREFCLKDIV_MASK GENMASK(13, 12)
+#define CLKMGR_PLLGLOB_REFCLKDIV_MASK GENMASK(13, 8)
+#define CLKMGR_PLLGLOB_MODCLKDIV_MASK GENMASK(24, 27)
+#define CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET 8
+#define CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET 12
+#define CLKMGR_PLLGLOB_REFCLKDIV_OFFSET 8
+#define CLKMGR_PLLGLOB_MODCLKDIV_OFFSET 24
+#define CLKMGR_PLLGLOB_VCO_PSRC_MASK GENMASK(17, 16)
+#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET 16
+#define CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK BIT(29)
+
+#define CLKMGR_VCO_PSRC_EOSC1 0
+#define CLKMGR_VCO_PSRC_INTOSC 1
+#define CLKMGR_VCO_PSRC_F2S 2
+
+#define CLKMGR_MEM_REQ_SET_MSK BIT(24)
+#define CLKMGR_MEM_WR_SET_MSK BIT(25)
+#define CLKMGR_MEM_ERR_MSK BIT(26)
+#define CLKMGR_MEM_WDAT_LSB_OFFSET 16
+#define CLKMGR_MEM_ADDR_MASK GENMASK(15, 0)
+#define CLKMGR_MEM_ADDR_START 0x00004000
+
+#define CLKMGR_PLLCX_EN_SET_MSK BIT(27)
+#define CLKMGR_PLLCX_MUTE_SET_MSK BIT(28)
+
+#define CLKMGR_VCOCALIB_MSCNT_MASK GENMASK(23, 16)
+#define CLKMGR_VCOCALIB_MSCNT_OFFSET 16
+#define CLKMGR_VCOCALIB_HSCNT_MASK GENMASK(9, 0)
+#define CLKMGR_VCOCALIB_MSCNT_CONST 100
+#define CLKMGR_VCOCALIB_HSCNT_CONST 4
+
+#define CLKMGR_PLLM_MDIV_MASK GENMASK(9, 0)
+
+#define CLKMGR_LOSTLOCK_SET_MASK BIT(0)
+
+#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK BIT(5)
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET 26
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK BIT(26)
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET 27
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK BIT(27)
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET 28
+#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK BIT(28)
+
+#define CLKMGR_CTL_EMACCTR_SRC_OFFSET 16
+#define CLKMGR_CTL_EMACCTR_SRC_MASK GENMASK(18, 16)
+#define CLKMGR_CTL_EMACCTR_CNT_OFFSET 0
+#define CLKMGR_CTL_EMACCTR_CNT_MASK GENMASK(10, 0)
+
+#define CLKMGR_CTL_EXTCNTRST_EMACACNTRST BIT(0)
+#define CLKMGR_CTL_EXTCNTRST_EMACBCNTRST BIT(1)
+#define CLKMGR_CTL_EXTCNTRST_EMACPTPCNTRST BIT(2)
+#define CLKMGR_CTL_EXTCNTRST_GPIODBCNTRST BIT(3)
+#define CLKMGR_CTL_EXTCNTRST_S2FUSER0CNTRST BIT(5)
+#define CLKMGR_CTL_EXTCNTRST_S2FUSER1CNTRST BIT(6)
+#define CLKMGR_CTL_EXTCNTRST_PSIREFCNTRST BIT(7)
+#define CLKMGR_CTL_EXTCNTRST_USB31REFCNTRST BIT(8)
+#define CLKMGR_CTL_EXTCNTRST_DSUCNTRST BIT(10)
+#define CLKMGR_CTL_EXTCNTRST_CORE01CNTRST BIT(11)
+#define CLKMGR_CTL_EXTCNTRST_CORE2CNTRST BIT(12)
+#define CLKMGR_CTL_EXTCNTRST_CORE3CNTRST BIT(13)
+#define CLKMGR_CTL_EXTCNTRST_ALLCNTRST \
+ (CLKMGR_CTL_EXTCNTRST_EMACACNTRST | \
+ CLKMGR_CTL_EXTCNTRST_EMACBCNTRST | \
+ CLKMGR_CTL_EXTCNTRST_EMACPTPCNTRST | \
+ CLKMGR_CTL_EXTCNTRST_GPIODBCNTRST | \
+ CLKMGR_CTL_EXTCNTRST_S2FUSER0CNTRST | \
+ CLKMGR_CTL_EXTCNTRST_S2FUSER1CNTRST | \
+ CLKMGR_CTL_EXTCNTRST_PSIREFCNTRST | \
+ CLKMGR_CTL_EXTCNTRST_USB31REFCNTRST | \
+ CLKMGR_CTL_EXTCNTRST_DSUCNTRST | \
+ CLKMGR_CTL_EXTCNTRST_CORE01CNTRST | \
+ CLKMGR_CTL_EXTCNTRST_CORE2CNTRST | \
+ CLKMGR_CTL_EXTCNTRST_CORE3CNTRST)
+#endif /* _CLK_AGILEX5_ */
diff --git a/include/mach/socfpga/atf.h b/include/mach/socfpga/atf.h
new file mode 100644
index 0000000000000000000000000000000000000000..a1ae878015bc48613cbdca73ac971f3f3dd844fe
--- /dev/null
+++ b/include/mach/socfpga/atf.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef ATF_H_
+#define ATF_H_
+
+#include <linux/sizes.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <asm/system.h>
+
+#define AGILEX5_ATF_BL31_BASE_ADDR 0x80000000
+#define AGILEX5_ATF_BL33_BASE_ADDR 0x80200000
+
+#endif
diff --git a/include/mach/socfpga/generic.h b/include/mach/socfpga/generic.h
index 40224897c1d2e05b934cd49963ac4ddeaeb28a25..673ccf90a19cda93b0856b7e494c5e519a00b83c 100644
--- a/include/mach/socfpga/generic.h
+++ b/include/mach/socfpga/generic.h
@@ -99,6 +99,9 @@ static inline void arria10_kick_l4wd0(void) {}
static inline void arria10_watchdog_disable(void) {}
#endif
+int agilex5_clk_init(void);
+void __noreturn agilex5_load_and_start_image_via_tfa(unsigned long memsize);
+
static inline void __udelay(unsigned us)
{
volatile unsigned int i;
diff --git a/include/mach/socfpga/init.h b/include/mach/socfpga/init.h
index c0e073ee1347cb4d76d74aeb3f513b1764996a59..06c480fe42f131d4f785643cd30e58780b3a0e52 100644
--- a/include/mach/socfpga/init.h
+++ b/include/mach/socfpga/init.h
@@ -5,4 +5,6 @@
void arria10_cpu_lowlevel_init(void);
+void socfpga_agilex5_cpu_lowlevel_init(void);
+
#endif
diff --git a/include/mach/socfpga/mailbox_s10.h b/include/mach/socfpga/mailbox_s10.h
new file mode 100644
index 0000000000000000000000000000000000000000..195e913d9228b51e4c91eb88932a9a3017c5deb1
--- /dev/null
+++ b/include/mach/socfpga/mailbox_s10.h
@@ -0,0 +1,199 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2017-2023 Intel Corporation <www.intel.com>
+ *
+ */
+
+#ifndef _MAILBOX_S10_H_
+#define _MAILBOX_S10_H_
+
+/* user define barebox ID */
+#include <linux/bitops.h>
+#define MBOX_CLIENT_ID_BAREBOX 0x2
+#define MBOX_ID_BAREBOX 0x2
+
+#define MBOX_CMD_DIRECT 0
+#define MBOX_CMD_INDIRECT 1
+
+#define MBOX_MAX_CMD_INDEX 2047
+#define MBOX_CMD_BUFFER_SIZE 32
+#define MBOX_RESP_BUFFER_SIZE 16
+
+#define MBOX_HDR_CMD_LSB 0
+#define MBOX_HDR_CMD_MSK (BIT(11) - 1)
+#define MBOX_HDR_I_LSB 11
+#define MBOX_HDR_I_MSK BIT(11)
+#define MBOX_HDR_LEN_LSB 12
+#define MBOX_HDR_LEN_MSK 0x007FF000
+#define MBOX_HDR_ID_LSB 24
+#define MBOX_HDR_ID_MSK 0x0F000000
+#define MBOX_HDR_CLIENT_LSB 28
+#define MBOX_HDR_CLIENT_MSK 0xF0000000
+
+/* Interrupt flags */
+#define MBOX_FLAGS_INT_COE BIT(0) /* COUT update interrupt enable */
+#define MBOX_FLAGS_INT_RIE BIT(1) /* RIN update interrupt enable */
+#define MBOX_FLAGS_INT_UAE BIT(8) /* Urgent ACK interrupt enable */
+#define MBOX_ALL_INTRS (MBOX_FLAGS_INT_COE | \
+ MBOX_FLAGS_INT_RIE | \
+ MBOX_FLAGS_INT_UAE)
+
+/* Status */
+#define MBOX_STATUS_UA_MSK BIT(8)
+
+#define MBOX_CMD_HEADER(client, id, len, indirect, cmd) \
+ ((((cmd) << MBOX_HDR_CMD_LSB) & MBOX_HDR_CMD_MSK) | \
+ (((indirect) << MBOX_HDR_I_LSB) & MBOX_HDR_I_MSK) | \
+ (((len) << MBOX_HDR_LEN_LSB) & MBOX_HDR_LEN_MSK) | \
+ (((id) << MBOX_HDR_ID_LSB) & MBOX_HDR_ID_MSK) | \
+ (((client) << MBOX_HDR_CLIENT_LSB) & MBOX_HDR_CLIENT_MSK))
+
+#define MBOX_RESP_ERR_GET(resp) \
+ (((resp) & MBOX_HDR_CMD_MSK) >> MBOX_HDR_CMD_LSB)
+#define MBOX_RESP_LEN_GET(resp) \
+ (((resp) & MBOX_HDR_LEN_MSK) >> MBOX_HDR_LEN_LSB)
+#define MBOX_RESP_ID_GET(resp) \
+ (((resp) & MBOX_HDR_ID_MSK) >> MBOX_HDR_ID_LSB)
+#define MBOX_RESP_CLIENT_GET(resp) \
+ (((resp) & MBOX_HDR_CLIENT_MSK) >> MBOX_HDR_CLIENT_LSB)
+
+/* Response error list */
+enum ALT_SDM_MBOX_RESP_CODE {
+ /* CMD completed successfully, but check resp ARGS for any errors */
+ MBOX_RESP_STATOK = 0,
+ /* CMD is incorrectly formatted in some way */
+ MBOX_RESP_INVALID_COMMAND = 1,
+ /* BootROM Command code not undesrtood */
+ MBOX_RESP_UNKNOWN_BR = 2,
+ /* CMD code not recognized by firmware */
+ MBOX_RESP_UNKNOWN = 3,
+ /* Length setting is not a valid length for this CMD type */
+ MBOX_RESP_INVALID_LEN = 4,
+ /* Indirect setting is not valid for this CMD type */
+ MBOX_RESP_INVALID_INDIRECT_SETTING = 5,
+ /* HW source which is not allowed to send CMD type */
+ MBOX_RESP_CMD_INVALID_ON_SRC = 6,
+ /* Client with ID not associated with any running PR CMD tries to run
+ * RECONFIG_DATA RECONFIG_STATUS and accessing QSPI / SDMMC using ID
+ * without exclusive access
+ */
+ MBOX_RESP_CLIENT_ID_NO_MATCH = 8,
+ /* Address provided to the system is invalid (alignment, range
+ * permission)
+ */
+ MBOX_RESP_INVALID_ADDR = 0x9,
+ /* Signature authentication failed */
+ MBOX_RESP_AUTH_FAIL = 0xA,
+ /* CMD timed out */
+ MBOX_RESP_TIMEOUT = 0xB,
+ /* HW (i.e. QSPI) is not ready (initialized or configured) */
+ MBOX_RESP_HW_NOT_RDY = 0xC,
+ /* Function is not supported in this firmware */
+ MBOX_FUNC_NOT_SUPPORTED = 0xF,
+ /* Invalid license for IID registration */
+ MBOX_RESP_PUF_ACCCES_FAILED = 0x80,
+ MBOX_PUF_ENROLL_DISABLE = 0x81,
+ MBOX_RESP_PUF_ENROLL_FAIL = 0x82,
+ MBOX_RESP_PUF_RAM_TEST_FAIL = 0x83,
+ MBOX_RESP_ATTEST_CERT_GEN_FAIL = 0x84,
+ /* Operation not allowed under current security settings */
+ MBOX_RESP_NOT_ALLOWED_UNDER_SECURITY_SETTINGS = 0x85,
+ MBOX_RESP_PUF_TRNG_FAIL = 0x86,
+ MBOX_RESP_FUSE_ALREADY_BLOWN = 0x87,
+ MBOX_RESP_INVALID_SIGNATURE = 0x88,
+ MBOX_RESP_INVALID_HASH = 0x8b,
+ MBOX_RESP_INVALID_CERTIFICATE = 0x91,
+ /* Indicates that the device (FPGA or HPS) is not configured */
+ MBOX_RESP_NOT_CONFIGURED = 0x100,
+ /* Indicates that the device is busy */
+ MBOX_RESP_DEVICE_BUSY = 0x1FF,
+ /* Indicates that there is no valid response available */
+ MBOX_RESP_NO_VALID_RESP_AVAILABLE = 0x2FF,
+ /* General Error */
+ MBOX_RESP_ERROR = 0x3FF,
+};
+
+/* Mailbox command list */
+#define MBOX_RESTART 2
+#define MBOX_CONFIG_STATUS 4
+#define MBOX_RECONFIG 6
+#define MBOX_RECONFIG_MSEL 7
+#define MBOX_RECONFIG_DATA 8
+#define MBOX_RECONFIG_STATUS 9
+#define MBOX_VAB_SRC_CERT 11
+#define MBOX_GET_USERCODE 19
+#define MBOX_QSPI_OPEN 50
+#define MBOX_QSPI_CLOSE 51
+#define MBOX_QSPI_DIRECT 59
+#define MBOX_REBOOT_HPS 71
+#define MBOX_GET_SUBPARTITION_TABLE 90
+#define MBOX_RSU_STATUS 91
+#define MBOX_RSU_UPDATE 92
+#define MBOX_HPS_STAGE_NOTIFY 93
+#define MBOX_QSPI_GET_DEVICE_INFO 116 /* get QSPI size and erasesize */
+
+/* Mailbox response len */
+#define QSPI_GET_DEVICE_INFO_RESP_LEN 8
+
+/* Mailbox registers */
+#define MBOX_CIN 0 /* command valid offset */
+#define MBOX_ROUT 4 /* response output offset */
+#define MBOX_URG 8 /* urgent command */
+#define MBOX_FLAGS 0x0c /* interrupt enables */
+#define MBOX_COUT 0x20 /* command free offset */
+#define MBOX_RIN 0x24 /* respond valid offset */
+#define MBOX_STATUS 0x2c /* mailbox status */
+#define MBOX_CMD_BUF 0x40 /* circular command buffer */
+#define MBOX_RESP_BUF 0xc0 /* circular response buffer */
+#define MBOX_DOORBELL_TO_SDM 0x400 /* Doorbell to SDM */
+#define MBOX_DOORBELL_FROM_SDM 0x480 /* Doorbell from SDM */
+
+/* Status and bit information returned by RECONFIG_STATUS */
+#define RECONFIG_STATUS_RESPONSE_LEN 6
+#define RECONFIG_STATUS_STATE 0
+#define RECONFIG_STATUS_PIN_STATUS 2
+#define RECONFIG_STATUS_SOFTFUNC_STATUS 3
+
+/* Macros for specifying number of arguments in mailbox command */
+#define MBOX_NUM_ARGS(n, b) (((n) & 0xFF) << (b))
+#define MBOX_DIRECT_COUNT(n) MBOX_NUM_ARGS((n), 0)
+#define MBOX_ARG_DESC_COUNT(n) MBOX_NUM_ARGS((n), 8)
+#define MBOX_RESP_DESC_COUNT(n) MBOX_NUM_ARGS((n), 16)
+
+#define MBOX_CFGSTAT_STATE_IDLE 0x00000000
+#define MBOX_CFGSTAT_STATE_CONFIG 0x10000000
+#define MBOX_CFGSTAT_STATE_FAILACK 0x08000000
+#define MBOX_CFGSTAT_STATE_ERROR_INVALID 0xf0000001
+#define MBOX_CFGSTAT_STATE_ERROR_CORRUPT 0xf0000002
+#define MBOX_CFGSTAT_STATE_ERROR_AUTH 0xf0000003
+#define MBOX_CFGSTAT_STATE_ERROR_CORE_IO 0xf0000004
+#define MBOX_CFGSTAT_STATE_ERROR_HARDWARE 0xf0000005
+#define MBOX_CFGSTAT_STATE_ERROR_FAKE 0xf0000006
+#define MBOX_CFGSTAT_STATE_ERROR_BOOT_INFO 0xf0000007
+#define MBOX_CFGSTAT_STATE_ERROR_QSPI_ERROR 0xf0000008
+
+#define RCF_SOFTFUNC_STATUS_CONF_DONE BIT(0)
+#define RCF_SOFTFUNC_STATUS_INIT_DONE BIT(1)
+#define RCF_SOFTFUNC_STATUS_SEU_ERROR BIT(3)
+#define RCF_PIN_STATUS_NSTATUS BIT(31)
+
+/* Defines for HPS_STAGE_NOTIFY */
+#define HPS_EXECUTION_STATE_FSBL 0
+#define HPS_EXECUTION_STATE_SSBL 1
+#define HPS_EXECUTION_STATE_OS 2
+
+int mbox_send_cmd(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg, u8 urgent,
+ u32 *resp_buf_len, u32 *resp_buf);
+int mbox_send_cmd_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg,
+ u8 urgent, u32 *resp_buf_len, u32 *resp_buf);
+int mbox_send_cmd_only(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg);
+int mbox_send_cmd_only_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg);
+int mbox_rcv_resp(u32 *resp_buf, u32 resp_buf_max_len);
+int mbox_rcv_resp_psci(u32 *resp_buf, u32 resp_buf_max_len);
+int mbox_init(void);
+
+int mbox_qspi_close(void);
+int mbox_qspi_open(void);
+int mbox_qspi_get_device_info(u32 *resp_buf, u32 resp_buf_len);
+
+#endif /* _MAILBOX_S10_H_ */
diff --git a/include/mach/socfpga/secure_reg_helper.h b/include/mach/socfpga/secure_reg_helper.h
new file mode 100644
index 0000000000000000000000000000000000000000..d5a11122c723b22b6d1b93833e494909f758f3b5
--- /dev/null
+++ b/include/mach/socfpga/secure_reg_helper.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2020 Intel Corporation <www.intel.com>
+ *
+ */
+
+#ifndef _SECURE_REG_HELPER_H_
+#define _SECURE_REG_HELPER_H_
+
+#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_SDMMC 1
+#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC0 2
+#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC1 3
+#define SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC2 4
+
+int socfpga_secure_reg_read32(u32 id, u32 *val);
+int socfpga_secure_reg_write32(u32 id, u32 val);
+int socfpga_secure_reg_update32(u32 id, u32 mask, u32 val);
+
+#endif /* _SECURE_REG_HELPER_H_ */
diff --git a/include/mach/socfpga/smc_api.h b/include/mach/socfpga/smc_api.h
new file mode 100644
index 0000000000000000000000000000000000000000..491bcaeb019aac986013bb98c59b6109dda719f0
--- /dev/null
+++ b/include/mach/socfpga/smc_api.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Intel Corporation
+ */
+
+#ifndef _SMC_API_H_
+#define _SMC_API_H_
+
+int invoke_smc(u32 func_id, u64 arg0, u64 arg1, u64 arg2, u32 *ret_payload);
+int smc_get_usercode(u32 *usercode);
+
+#endif /* _SMC_API_H_ */
diff --git a/include/mach/socfpga/soc64-firewall.h b/include/mach/socfpga/soc64-firewall.h
new file mode 100644
index 0000000000000000000000000000000000000000..659b84ca1f3f20ede52ed9b0bc0b03d9611e4d26
--- /dev/null
+++ b/include/mach/socfpga/soc64-firewall.h
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2017-2023 Intel Corporation <www.intel.com>
+ *
+ */
+
+#ifndef _FIREWALL_H_
+#define _FIREWALL_H_
+
+#include <linux/bitops.h>
+
+struct socfpga_firwall_l4_per {
+ u32 nand; /* 0x00 */
+ u32 nand_data;
+ u32 _pad_0x8;
+ u32 usb0;
+ u32 usb1; /* 0x10 */
+ u32 _pad_0x14;
+ u32 _pad_0x18;
+ u32 spim0;
+ u32 spim1; /* 0x20 */
+ u32 spis0;
+ u32 spis1;
+ u32 emac0;
+ u32 emac1; /* 0x30 */
+ u32 emac2;
+ u32 _pad_0x38;
+ u32 _pad_0x3c;
+ u32 sdmmc; /* 0x40 */
+ u32 gpio0;
+ u32 gpio1;
+ u32 _pad_0x4c;
+ u32 i2c0; /* 0x50 */
+ u32 i2c1;
+ u32 i2c2;
+ u32 i2c3;
+ u32 i2c4; /* 0x60 */
+ u32 timer0;
+ u32 timer1;
+ u32 uart0;
+ u32 uart1; /* 0x70 */
+};
+
+struct socfpga_firwall_l4_sys {
+ u32 _pad_0x00; /* 0x00 */
+ u32 _pad_0x04;
+ u32 dma_ecc;
+ u32 emac0rx_ecc;
+ u32 emac0tx_ecc; /* 0x10 */
+ u32 emac1rx_ecc;
+ u32 emac1tx_ecc;
+ u32 emac2rx_ecc;
+ u32 emac2tx_ecc; /* 0x20 */
+ u32 _pad_0x24;
+ u32 _pad_0x28;
+ u32 nand_ecc;
+ u32 nand_read_ecc; /* 0x30 */
+ u32 nand_write_ecc;
+ u32 ocram_ecc;
+ u32 _pad_0x3c;
+ u32 sdmmc_ecc; /* 0x40 */
+ u32 usb0_ecc;
+ u32 usb1_ecc;
+ u32 clock_manager;
+ u32 _pad_0x50; /* 0x50 */
+ u32 io_manager;
+ u32 reset_manager;
+ u32 system_manager;
+ u32 osc0_timer; /* 0x60 */
+ u32 osc1_timer;
+ u32 watchdog0;
+ u32 watchdog1;
+ u32 watchdog2; /* 0x70 */
+ u32 watchdog3;
+};
+
+#define FIREWALL_L4_DISABLE_ALL (BIT(0) | BIT(24) | BIT(16))
+#define FIREWALL_MPFE_SCR_DISABLE_ALL (BIT(0) | BIT(8) | BIT(16))
+#define FIREWALL_MPFE_SCR_DISABLE_MPU BIT(0)
+#define FIREWALL_BRIDGE_DISABLE_ALL (~0)
+
+/* Cache coherency unit (CCU) registers */
+#define CCU_CPU0_MPRT_ADBASE_DDRREG 0x4400
+#define CCU_CPU0_MPRT_ADBASE_MEMSPACE0 0x45c0
+#define CCU_CPU0_MPRT_ADBASE_MEMSPACE1A 0x45e0
+#define CCU_CPU0_MPRT_ADBASE_MEMSPACE1B 0x4600
+#define CCU_CPU0_MPRT_ADBASE_MEMSPACE1C 0x4620
+#define CCU_CPU0_MPRT_ADBASE_MEMSPACE1D 0x4640
+#define CCU_CPU0_MPRT_ADBASE_MEMSPACE1E 0x4660
+
+#define CCU_CPU0_MPRT_ADMASK_MEM_RAM0 0x4688
+
+#define CCU_IOM_MPRT_ADBASE_MEMSPACE0 0x18560
+#define CCU_IOM_MPRT_ADBASE_MEMSPACE1A 0x18580
+#define CCU_IOM_MPRT_ADBASE_MEMSPACE1B 0x185a0
+#define CCU_IOM_MPRT_ADBASE_MEMSPACE1C 0x185c0
+#define CCU_IOM_MPRT_ADBASE_MEMSPACE1D 0x185e0
+#define CCU_IOM_MPRT_ADBASE_MEMSPACE1E 0x18600
+
+#define CCU_IOM_MPRT_ADMASK_MEM_RAM0 0x18628
+
+#define CCU_TCU_MPRT_ADBASE_MEMSPACE0 0x2c520
+#define CCU_TCU_MPRT_ADBASE_MEMSPACE1A 0x2c540
+#define CCU_TCU_MPRT_ADBASE_MEMSPACE1B 0x2c560
+#define CCU_TCU_MPRT_ADBASE_MEMSPACE1C 0x2c580
+#define CCU_TCU_MPRT_ADBASE_MEMSPACE1D 0x2c5a0
+#define CCU_TCU_MPRT_ADBASE_MEMSPACE1E 0x2c5c0
+
+#define CCU_FPGA_MPRT_ADBASE_MEMSPACE0 0x105a0
+#define CCU_FPGA_MPRT_ADBASE_MEMSPACE1A 0x105c0
+#define CCU_FPGA_MPRT_ADBASE_MEMSPACE1B 0x105e0
+#define CCU_FPGA_MPRT_ADBASE_MEMSPACE1C 0x10600
+#define CCU_FPGA_MPRT_ADBASE_MEMSPACE1D 0x10620
+#define CCU_FPGA_MPRT_ADBASE_MEMSPACE1E 0x10640
+
+
+#define CCU_ADMASK_P_MASK BIT(0)
+#define CCU_ADMASK_NS_MASK BIT(1)
+
+#define CCU_ADBASE_DI_MASK BIT(4)
+
+#define CCU_REG_ADDR(reg) \
+ (SOCFPGA_CCU_ADDRESS + (reg))
+
+/* Firewall MPU DDR SCR registers */
+#define FW_MPU_DDR_SCR_EN 0x00
+#define FW_MPU_DDR_SCR_EN_SET 0x04
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_BASE 0x10
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_BASEEXT 0x14
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT 0x18
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT 0x1c
+
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASE 0x90
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT 0x94
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT 0x98
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT 0x9c
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT_FIELD 0xff
+
+/* Firewall F2SDRAM DDR SCR registers */
+#define FW_F2SDRAM_DDR_SCR_EN 0x00
+#define FW_F2SDRAM_DDR_SCR_EN_SET 0x04
+#define FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASE 0x10
+#define FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASEEXT 0x14
+#define FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMIT 0x18
+#define FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMITEXT 0x1c
+
+/* Firewall MPFE SCR Registers */
+#define FW_MPFE_SCR_HMC 0x00
+#define FW_MPFE_SCR_HMC_ADAPTOR 0x04
+
+#define MPUREGION0_ENABLE BIT(0)
+#define NONMPUREGION0_ENABLE BIT(8)
+
+#define FW_MPU_DDR_SCR_WRITEL(data, reg) \
+ writel(data, SOCFPGA_FW_DDR_CCU_DMI0_ADDRESS + (reg)); \
+ writel(data, SOCFPGA_FW_DDR_CCU_DMI1_ADDRESS + (reg))
+#define FW_F2SDRAM_DDR_SCR_WRITEL(data, reg) \
+ writel(data, SOCFPGA_FW_TBU2NOC_ADDRESS + (reg))
+
+#define FW_MPU_DDR_DMI0_SCR_READL(reg) readl(SOCFPGA_FW_DDR_CCU_DMI0_ADDRESS + (reg));
+#define FW_MPU_DDR_DMI1_SCR_READL(reg) readl(SOCFPGA_FW_DDR_CCU_DMI1_ADDRESS + (reg));
+#define FW_F2SDRAM_DDR_SCR_READL(reg) readl(SOCFPGA_FW_TBU2NOC_ADDRESS + (reg))
+
+/* Secure Transaction Register */
+#define SECURE_TRANS_OFFS 0x190
+#define SECURE_TRANS_REG SOCFPGA_SYSMGR_ADDRESS +\
+ SECURE_TRANS_OFFS
+#define SECURE_TRANS_RESET 0x0
+#define SECURE_TRANS_SET 0x33
+#define OCRAM_SECURE_REGION1_OFFS 0x18
+#define OCRAM_SECURE_REGION1_REG SOCFPGA_OCRAM_FIREWALL_ADDRESS +\
+ OCRAM_SECURE_REGION1_OFFS
+#define NON_SECURE_ACCESS 0x0
+
+void firewall_setup(void);
+
+#endif /* _FIREWALL_H_ */
diff --git a/include/mach/socfpga/soc64-handoff.h b/include/mach/socfpga/soc64-handoff.h
new file mode 100644
index 0000000000000000000000000000000000000000..5e079b34b84fd874f70cdb664de3c90f7464d111
--- /dev/null
+++ b/include/mach/socfpga/soc64-handoff.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2016-2024 Intel Corporation <www.intel.com>
+ *
+ */
+
+#ifndef _HANDOFF_SOC64_H_
+#define _HANDOFF_SOC64_H_
+
+/*
+ * Offset for HW handoff from Quartus tools
+ */
+/* HPS handoff */
+#define SOC64_HANDOFF_MAGIC_BOOT 0x424F4F54
+#define SOC64_HANDOFF_MAGIC_MUX 0x504D5558
+#define SOC64_HANDOFF_MAGIC_IOCTL 0x494F4354
+#define SOC64_HANDOFF_MAGIC_FPGA 0x46504741
+#define SOC64_HANDOFF_MAGIC_DELAY 0x444C4159
+#define SOC64_HANDOFF_MAGIC_CLOCK 0x434C4B53
+#define SOC64_HANDOFF_MAGIC_PERI 0x50455249
+#define SOC64_HANDOFF_MAGIC_SDRAM 0x5344524d
+
+#define SOC64_HANDOFF_OFFSET_LENGTH 0x4
+#define SOC64_HANDOFF_OFFSET_DATA 0x10
+#define SOC64_HANDOFF_SIZE 4096
+
+#define SOC64_HANDOFF_BASE 0x0007F000
+
+#define SOC64_HANDOFF_MUX (SOC64_HANDOFF_BASE + 0x10)
+#define SOC64_HANDOFF_IOCTL (SOC64_HANDOFF_BASE + 0x1A0)
+#define SOC64_HANDOFF_FPGA (SOC64_HANDOFF_BASE + 0x330)
+#define SOC64_HANDOFF_DELAY (SOC64_HANDOFF_BASE + 0x3F0)
+#define SOC64_HANDOFF_CLOCK (SOC64_HANDOFF_BASE + 0x580)
+#define SOC64_HANDOFF_PERI (SOC64_HANDOFF_BASE + 0x620)
+#define SOC64_HANDOFF_SDRAM (SOC64_HANDOFF_BASE + 0x634)
+#define SOC64_HANDOFF_SDRAM_LEN 5
+
+#define SOC64_HANDOFF_CLOCK_OSC (SOC64_HANDOFF_BASE + 0x60c)
+#define SOC64_HANDOFF_CLOCK_FPGA (SOC64_HANDOFF_BASE + 0x610)
+
+#define SOC64_HANDOFF_MUX_LEN 96
+#define SOC64_HANDOFF_IOCTL_LEN 96
+#define SOC64_HANDOFF_FPGA_LEN 40
+#define SOC64_HANDOFF_DELAY_LEN 96
+
+int socfpga_get_handoff_size(void *handoff_address);
+int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len);
+const struct cm_config * const cm_get_default_config(void);
+
+#endif /* _HANDOFF_SOC64_H_ */
diff --git a/include/mach/socfpga/soc64-init.h b/include/mach/socfpga/soc64-init.h
new file mode 100644
index 0000000000000000000000000000000000000000..15113f70701c6452affad3725c3e8375133300f3
--- /dev/null
+++ b/include/mach/socfpga/soc64-init.h
@@ -0,0 +1,4 @@
+#ifndef SOC64-INIT_H_
+#define SOC64-INIT_H_
+
+#endif // SOC64-INIT_H_
diff --git a/include/mach/socfpga/soc64-regs.h b/include/mach/socfpga/soc64-regs.h
new file mode 100644
index 0000000000000000000000000000000000000000..fd8cfa17ba1bf0c62a02c9db39dc09347131dd61
--- /dev/null
+++ b/include/mach/socfpga/soc64-regs.h
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016-2023 Intel Corporation <www.intel.com>
+ */
+
+#ifndef _SOCFPGA_SOC64_BASE_HARDWARE_H_
+#define _SOCFPGA_SOC64_BASE_HARDWARE_H_
+
+#if IS_ENABLED(CONFIG_ARCH_SOCFPGA_AGILEX5)
+#define SOCFPGA_CCU_ADDRESS 0x1c000000
+#define SOCFPGA_CCU_DII2_GIC_BAR_REG 0x420
+#define SOCFPGA_CCU_DII2_GIC_LR_REG 0x424
+#define SOCFPGA_CCU_DII2_GIC_HR_REG 0x428
+
+#define SOCFPGA_FPGA2SOC_ADDRESS 0x1c001000
+#define SOCFPGA_FPGA2SOC_PSS_BAR_REG 0x400
+#define SOCFPGA_FPGA2SOC_PSS_LR_REG 0x404
+#define SOCFPGA_FPGA2SOC_PSS_HR_REG 0x408
+
+#define SOCFPGA_GIC_M_ADDRESS 0x1c002000
+#define SOCFPGA_TCU_ADDRESS 0x1c003000
+#define SOCFPGA_CCU_IOM_ADDRESS 0x1c004000
+#define SOCFPGA_DCE0_ADDRESS 0x1c005000
+#define SOCFPGA_DCE1_ADDRESS 0x1c006000
+
+#define SOCFPGA_SECREG_NCAIU1AMIGR_REG 0x3c0
+#define SOCFPGA_SECREG_NCAIU1MIFSR_REG 0x3c4
+#define SOCFPGA_SECREG_DII1_MPFE_BAR_REG 0x410
+#define SOCFPGA_SECREG_DII1_MPFE_LR_REG 0x414
+#define SOCFPGA_SECREG_DII1_MPFE_HR_REG 0x418
+#define SOCFPGA_SECREG_NCAIU0_LWSOC2FPGA_BAR_REG 0x440
+#define SOCFPGA_SECREG_NCAIU0_LWSOC2FPGA_LR_REG 0x444
+#define SOCFPGA_SECREG_NCAIU0_LWSOC2FPGA_HR_REG 0x448
+#define SOCFPGA_SECREG_NCAIU0_SOC2FPGA_1G_BAR_REG 0x450
+#define SOCFPGA_SECREG_NCAIU0_SOC2FPGA_1G_LR_REG 0x454
+#define SOCFPGA_SECREG_NCAIU0_SOC2FPGA_1G_HR_REG 0x458
+#define SOCFPGA_SECREG_DMI_SDRAM_2G_BAR_REG 0x460
+#define SOCFPGA_SECREG_DMI_SDRAM_2G_LR_REG 0x464
+#define SOCFPGA_SECREG_DMI_SDRAM_2G_HR_REG 0x468
+#define SOCFPGA_SECREG_NCAIU0_SOC2FPGA_16G_BAR_REG 0x470
+#define SOCFPGA_SECREG_NCAIU0_SOC2FPGA_16G_LR_REG 0x474
+#define SOCFPGA_SECREG_NCAIU0_SOC2FPGA_16G_HR_REG 0x478
+#define SOCFPGA_SECREG_DMI_SDRAM_30G_BAR_REG 0x480
+#define SOCFPGA_SECREG_DMI_SDRAM_30G_LR_REG 0x484
+#define SOCFPGA_SECREG_DMI_SDRAM_30G_HR_REG 0x488
+#define SOCFPGA_SECREG_NCAIU0_SOC2FPGA_256G_BAR_REG 0x490
+#define SOCFPGA_SECREG_NCAIU0_SOC2FPGA_256G_LR_REG 0x494
+#define SOCFPGA_SECREG_NCAIU0_SOC2FPGA_256G_HR_REG 0x498
+#define SOCFPGA_SECREG_DMI_SDRAM_480G_BAR_REG 0x4a0
+#define SOCFPGA_SECREG_DMI_SDRAM_480G_LR_REG 0x4a4
+#define SOCFPGA_SECREG_DMI_SDRAM_480G_HR_REG 0x4a8
+
+#define SOCFPGA_DMI0_ADDRESS 0x1c007000
+#define SOCFPGA_DMI0_DMIUSMCTCR_REG 0x300
+
+#define SOCFPGA_DMI1_ADDRESS 0x1c008000
+#define SOCFPGA_DMI1_DMIUSMCTCR_REG 0x300
+
+#define SOCFPGA_F2SDRAM_MGR_ADDRESS 0x18001000
+#define SOCFPGA_SMMU_ADDRESS 0x16000000
+#define SOCFPGA_OCRAM_FIREWALL_ADDRESS 0x108cc400
+#define SOCFPGA_MAILBOX_ADDRESS 0x10a30000
+#define SOCFPGA_UART0_ADDRESS 0x10c02000
+#define SOCFPGA_UART1_ADDRESS 0x10c02100
+#define SOCFPGA_SPTIMER0_ADDRESS 0x10c03000
+#define SOCFPGA_SPTIMER1_ADDRESS 0x10c03100
+#define SOCFPGA_SYSTIMER0_ADDRESS 0x10d00000
+#define SOCFPGA_SYSTIMER1_ADDRESS 0x10d00100
+#define SOCFPGA_L4WD0_ADDRESS 0x10d00200
+#define SOCFPGA_L4WD1_ADDRESS 0x10d00300
+#define SOCFPGA_L4WD2_ADDRESS 0x10d00400
+#define SOCFPGA_L4WD3_ADDRESS 0x10d00500
+#define SOCFPGA_L4WD4_ADDRESS 0x10d00600
+#define SOCFPGA_GTIMER_SEC_ADDRESS 0x10d01000
+#define SOCFPGA_GTIMER_NSEC_ADDRESS 0x10d02000
+#define SOCFPGA_CLKMGR_ADDRESS 0x10d10000
+#define SOCFPGA_RSTMGR_ADDRESS 0x10d11000
+#define SOCFPGA_SYSMGR_ADDRESS 0x10d12000
+#define SOCFPGA_PINMUX_ADDRESS 0x10d13000
+#define SOCFPGA_OCRAM_ADDRESS 0x00000000
+#define SOCFPGA_MPFE_CSR_ADDRESS 0x18000000
+#define SOCFPGA_FW_DDR_CCU_DMI0_ADDRESS 0x18000800
+#define SOCFPGA_FW_DDR_CCU_DMI1_ADDRESS 0x18000A00
+#define SOCFPGA_FW_TBU2NOC_ADDRESS 0x18000C00
+#define SOCFPGA_FIREWALL_L4_PER_ADDRESS 0x10d21000
+#define SOCFPGA_FIREWALL_L4_PER_NAND_REG 0x0
+#define SOCFPGA_FIREWALL_L4_PER_USB0_REG 0xc
+#define SOCFPGA_FIREWALL_L4_PER_USB1_REG 0x10
+#define SOCFPGA_FIREWALL_L4_PER_SPI_MAIN0_REG 0x1c
+#define SOCFPGA_FIREWALL_L4_PER_SPI_MAIN1_REG 0x20
+#define SOCFPGA_FIREWALL_L4_PER_SPI_SEC0_REG 0x24
+#define SOCFPGA_FIREWALL_L4_PER_SPI_SEC1_REG 0x28
+#define SOCFPGA_FIREWALL_L4_PER_EMAC0_REG 0x2c
+#define SOCFPGA_FIREWALL_L4_PER_EMAC1_REG 0x30
+#define SOCFPGA_FIREWALL_L4_PER_EMAC2_REG 0x34
+#define SOCFPGA_FIREWALL_L4_PER_SDMMC_REG 0x40
+#define SOCFPGA_FIREWALL_L4_PER_GPIO0_REG 0x44
+#define SOCFPGA_FIREWALL_L4_PER_GPIO1_REG 0x48
+#define SOCFPGA_FIREWALL_L4_PER_I2C0_REG 0x50
+#define SOCFPGA_FIREWALL_L4_PER_I2C1_REG 0x54
+#define SOCFPGA_FIREWALL_L4_PER_I2C2_REG 0x58
+#define SOCFPGA_FIREWALL_L4_PER_I2C3_REG 0x5c
+#define SOCFPGA_FIREWALL_L4_PER_I2C4_REG 0x60
+#define SOCFPGA_FIREWALL_L4_PER_SP_TIMER0_REG 0x64
+#define SOCFPGA_FIREWALL_L4_PER_SP_TIMER1_REG 0x68
+#define SOCFPGA_FIREWALL_L4_PER_UART0_REG 0x6c
+#define SOCFPGA_FIREWALL_L4_PER_UART1_REG 0x70
+#define SOCFPGA_FIREWALL_L4_PER_I3C0_REG 0x74
+#define SOCFPGA_FIREWALL_L4_PER_I3C1_REG 0x78
+#define SOCFPGA_FIREWALL_L4_PER_DMA0_REG 0x7c
+#define SOCFPGA_FIREWALL_L4_PER_DMA1_REG 0x80
+#define SOCFPGA_FIREWALL_L4_PER_COMBO_PHY_REG 0x84
+#define SOCFPGA_FIREWALL_L4_PER_NAND_SDMA_REG 0x88
+
+#define SOCFPGA_FIREWALL_L4_SYS_ADDRESS 0x10d21100
+#define SOCFPGA_FIREWALL_L4_SYS_DMA_ECC_REG 0x08
+#define SOCFPGA_FIREWALL_L4_SYS_EMAC0RX_ECC_REG 0x0c
+#define SOCFPGA_FIREWALL_L4_SYS_EMAC0TX_ECC_REG 0x10
+#define SOCFPGA_FIREWALL_L4_SYS_EMAC1RX_ECC_REG 0x14
+#define SOCFPGA_FIREWALL_L4_SYS_EMAC1TX_ECC_REG 0x18
+#define SOCFPGA_FIREWALL_L4_SYS_EMAC2RX_ECC_REG 0x1c
+#define SOCFPGA_FIREWALL_L4_SYS_EMAC2TX_ECC_REG 0x20
+#define SOCFPGA_FIREWALL_L4_SYS_NAND_ECC_REG 0x2c
+#define SOCFPGA_FIREWALL_L4_SYS_NAND_READ_ECC_REG 0x30
+#define SOCFPGA_FIREWALL_L4_SYS_NAND_WRITE_ECC_REG 0x34
+#define SOCFPGA_FIREWALL_L4_SYS_OCRAM_ECC_REG 0x38
+#define SOCFPGA_FIREWALL_L4_SYS_SDMMC_ECC_REG 0x40
+#define SOCFPGA_FIREWALL_L4_SYS_USB0_ECC_REG 0x44
+#define SOCFPGA_FIREWALL_L4_SYS_USB1_CACHEECC_REG 0x48
+#define SOCFPGA_FIREWALL_L4_SYS_CLOCK_MANAGER_REG 0x4c
+#define SOCFPGA_FIREWALL_L4_SYS_IO_MANAGER_REG 0x54
+#define SOCFPGA_FIREWALL_L4_SYS_RESET_MANAGER_REG 0x58
+#define SOCFPGA_FIREWALL_L4_SYS_SYSTEM_MANAGER_REG 0x5c
+#define SOCFPGA_FIREWALL_L4_SYS_OSC0_TIMER_REG 0x60
+#define SOCFPGA_FIREWALL_L4_SYS_OSC1_TIMER0_REG 0x64
+#define SOCFPGA_FIREWALL_L4_SYS_WATCHDOG0_REG 0x68
+#define SOCFPGA_FIREWALL_L4_SYS_WATCHDOG1_REG 0x6c
+#define SOCFPGA_FIREWALL_L4_SYS_WATCHDOG2_REG 0x70
+#define SOCFPGA_FIREWALL_L4_SYS_WATCHDOG3_REG 0x74
+#define SOCFPGA_FIREWALL_L4_SYS_DAP_REG 0x78
+#define SOCFPGA_FIREWALL_L4_SYS_WATCHDOG4_REG 0x7c
+#define SOCFPGA_FIREWALL_L4_SYS_POWER_MANAGER_REG 0x80
+#define SOCFPGA_FIREWALL_L4_SYS_USB1_RXECC_REG 0x84
+#define SOCFPGA_FIREWALL_L4_SYS_USB1_TXECC_REG 0x88
+#define SOCFPGA_FIREWALL_L4_SYS_L4_NOC_PROBES_REG 0x90
+#define SOCFPGA_FIREWALL_L4_SYS_L4_NOC_QOS_REG 0x94
+
+#define SOCFPGA_FIREWALL_SOC2FPGA_ADDRESS 0x10d21200
+#define SOCFPGA_FIREWALL_LWSOC2FPGA_ADDRESS 0x10d21300
+#define SOCFPGA_FIREWALL_TCU_ADDRESS 0x10d21400
+#define GICD_BASE 0x1d000000
+#define GICR_BASE 0x1d060000
+
+#define SOCFPGA_AGILEX5_DDR_BASE 0x80000000
+
+#else
+#define SOCFPGA_CCU_ADDRESS 0xf7000000
+#define SOCFPGA_SDR_SCHEDULER_ADDRESS 0xf8000400
+#define SOCFPGA_HMC_MMR_IO48_ADDRESS 0xf8010000
+#define SOCFPGA_SDR_ADDRESS 0xf8011000
+#define SOCFPGA_FW_MPFE_SCR_ADDRESS 0xf8020000
+#define SOCFPGA_FW_MPU_DDR_SCR_ADDRESS 0xf8020100
+#define SOCFPGA_F2SDRAM_MGR_ADDRESS 0xf8024000
+#define SOCFPGA_SMMU_ADDRESS 0xfa000000
+#define SOCFPGA_MAILBOX_ADDRESS 0xffa30000
+#define SOCFPGA_UART0_ADDRESS 0xffc02000
+#define SOCFPGA_UART1_ADDRESS 0xffc02100
+#define SOCFPGA_SPTIMER0_ADDRESS 0xffc03000
+#define SOCFPGA_SPTIMER1_ADDRESS 0xffc03100
+#define SOCFPGA_SYSTIMER0_ADDRESS 0xffd00000
+#define SOCFPGA_SYSTIMER1_ADDRESS 0xffd00100
+#define SOCFPGA_L4WD0_ADDRESS 0xffd00200
+#define SOCFPGA_L4WD1_ADDRESS 0xffd00300
+#define SOCFPGA_L4WD2_ADDRESS 0xffd00400
+#define SOCFPGA_L4WD3_ADDRESS 0xffd00500
+#define SOCFPGA_GTIMER_SEC_ADDRESS 0xffd01000
+#define SOCFPGA_GTIMER_NSEC_ADDRESS 0xffd02000
+#define SOCFPGA_CLKMGR_ADDRESS 0xffd10000
+#define SOCFPGA_RSTMGR_ADDRESS 0xffd11000
+#define SOCFPGA_SYSMGR_ADDRESS 0xffd12000
+#define SOCFPGA_PINMUX_DEDICATED_IO_ADDRESS 0xffd13000
+#define SOCFPGA_FIREWALL_L4_PER 0xffd21000
+#define SOCFPGA_FIREWALL_L4_SYS 0xffd21100
+#define SOCFPGA_FIREWALL_SOC2FPGA 0xffd21200
+#define SOCFPGA_FIREWALL_LWSOC2FPGA 0xffd21300
+#define SOCFPGA_FIREWALL_TCU 0xffd21400
+#define SOCFPGA_FIREWALL_PRIV_MEMORYMAP_PRIV 0xffd24800
+#define SOCFPGA_DMANONSECURE_ADDRESS 0xffda0000
+#define SOCFPGA_DMASECURE_ADDRESS 0xffda1000
+#define SOCFPGA_OCRAM_ADDRESS 0xffe00000
+#define GICD_BASE 0xfffc1000
+#define GICC_BASE 0xfffc2000
+#endif
+
+#endif /* _SOCFPGA_SOC64_BASE_HARDWARE_H_ */
diff --git a/include/mach/socfpga/soc64-reset-manager.h b/include/mach/socfpga/soc64-reset-manager.h
new file mode 100644
index 0000000000000000000000000000000000000000..d9822ae9bfd9d02581432dc2aeb2051334c149bb
--- /dev/null
+++ b/include/mach/socfpga/soc64-reset-manager.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016-2022 Intel Corporation <www.intel.com>
+ */
+
+#ifndef _RESET_MANAGER_SOC64_H_
+#define _RESET_MANAGER_SOC64_H_
+
+#define RSTMGR_SOC64_STATUS 0x00
+#define RSTMGR_SOC64_HDSKEN 0x10
+#define RSTMGR_SOC64_HDSKREQ 0x14
+#define RSTMGR_SOC64_HDSKACK 0x18
+#define RSTMGR_SOC64_MPUMODRST 0x20
+#define RSTMGR_SOC64_PER0MODRST 0x24
+#define RSTMGR_SOC64_PER1MODRST 0x28
+#define RSTMGR_SOC64_BRGMODRST 0x2c
+
+#define RSTMGR_MPUMODRST_CORE0 0
+#define RSTMGR_PER0MODRST_OCP_MASK 0x0020bf00
+
+#define RSTMGR_BRGMODRST_SOC2FPGA_MASK BIT(0)
+#define RSTMGR_BRGMODRST_LWSOC2FPGA_MASK BIT(1)
+#define RSTMGR_BRGMODRST_FPGA2SOC_MASK BIT(2)
+#define RSTMGR_BRGMODRST_F2SDRAM0_MASK BIT(3)
+#define RSTMGR_BRGMODRST_F2SDRAM1_MASK BIT(4)
+#define RSTMGR_BRGMODRST_F2SDRAM2_MASK BIT(5)
+#define RSTMGR_BRGMODRST_DDRSCH_MASK BIT(6)
+
+#define RSTMGR_HDSKEN_FPGAHSEN BIT(2)
+#define RSTMGR_HDSKREQ_FPGAHSREQ BIT(2)
+
+/* SDM, Watchdogs and MPU warm reset mask */
+#define RSTMGR_STAT_SDMWARMRST 0x2
+#define RSTMGR_STAT_MPU0RST_BITPOS 8
+#define RSTMGR_STAT_L4WD0RST_BITPOS 16
+#define RSTMGR_STAT_L4WD0RST_BIT 0x1F0000
+#define RSTMGR_L4WD_MPU_WARMRESET_MASK RSTMGR_STAT_SDMWARMRST | \
+ RSTMGR_STAT_L4WD0RST_BIT
+
+#endif /* _RESET_MANAGER_SOC64_H_ */
diff --git a/include/mach/socfpga/soc64-sdram.h b/include/mach/socfpga/soc64-sdram.h
new file mode 100644
index 0000000000000000000000000000000000000000..c84cd7f8253734dfb7066077c3b8401884efb0ed
--- /dev/null
+++ b/include/mach/socfpga/soc64-sdram.h
@@ -0,0 +1,203 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017-2023 Intel Corporation <www.intel.com>
+ */
+
+#ifndef _SDRAM_SOC64_H_
+#define _SDRAM_SOC64_H_
+
+#include <linux/sizes.h>
+
+struct altera_sdram_plat {
+ void __iomem *mpfe_base_addr;
+ bool dualport;
+ bool dualemif;
+};
+
+/* ECC HMC registers */
+#define DDRIOCTRL 0x8
+#define DDRCALSTAT 0xc
+#define DRAMADDRWIDTH 0xe0
+#define ECCCTRL1 0x100
+#define ECCCTRL2 0x104
+#define ERRINTEN 0x110
+#define ERRINTENS 0x114
+#define INTMODE 0x11c
+#define INTSTAT 0x120
+#define AUTOWB_CORRADDR 0x138
+#define ECC_REG2WRECCDATABUS 0x144
+#define ECC_DIAGON 0x150
+#define ECC_DECSTAT 0x154
+#define HPSINTFCSEL 0x210
+#define RSTHANDSHAKECTRL 0x214
+#define RSTHANDSHAKESTAT 0x218
+
+#define DDR_HMC_DDRIOCTRL_IOSIZE_MSK 0x00000003
+#define DDR_HMC_DDRIOCTRL_MPFE_HMCA_DATA_RATE_MSK BIT(2)
+#define DDR_HMC_DDRIOCTRL_MPFE_HMCA_DATA_RATE_SHIFT 2
+#define DDR_HMC_DDRCALSTAT_CAL_MSK BIT(0)
+#define DDR_HMC_ECCCTL_AWB_CNT_RST_SET_MSK BIT(16)
+#define DDR_HMC_ECCCTL_CNT_RST_SET_MSK BIT(8)
+#define DDR_HMC_ECCCTL_ECC_EN_SET_MSK BIT(0)
+#define DDR_HMC_ECCCTL2_RMW_EN_SET_MSK BIT(8)
+#define DDR_HMC_ECCCTL2_AWB_EN_SET_MSK BIT(0)
+#define DDR_HMC_ECC_DIAGON_ECCDIAGON_EN_SET_MSK BIT(16)
+#define DDR_HMC_ECC_DIAGON_WRDIAGON_EN_SET_MSK BIT(0)
+#define DDR_HMC_ERRINTEN_SERRINTEN_EN_SET_MSK BIT(0)
+#define DDR_HMC_ERRINTEN_DERRINTEN_EN_SET_MSK BIT(1)
+#define DDR_HMC_INTSTAT_SERRPENA_SET_MSK BIT(0)
+#define DDR_HMC_INTSTAT_DERRPENA_SET_MSK BIT(1)
+#define DDR_HMC_INTSTAT_ADDRMTCFLG_SET_MSK BIT(16)
+#define DDR_HMC_INTMODE_INTMODE_SET_MSK BIT(0)
+#define DDR_HMC_RSTHANDSHAKE_MASK 0x0000000f
+#define DDR_HMC_CORE2SEQ_INT_REQ 0xF
+#define DDR_HMC_SEQ2CORE_INT_RESP_MASK BIT(3)
+#define DDR_HMC_HPSINTFCSEL_ENABLE_MASK 0x001f1f1f
+
+#define DDR_HMC_ERRINTEN_INTMASK \
+ (DDR_HMC_ERRINTEN_SERRINTEN_EN_SET_MSK | \
+ DDR_HMC_ERRINTEN_DERRINTEN_EN_SET_MSK)
+
+/* HMC MMR IO48 registers */
+#define CTRLCFG0 0x28
+#define CTRLCFG1 0x2c
+#define CTRLCFG3 0x34
+#define CTRLCFG5 0x3c
+#define CTRLCFG6 0x40
+#define DRAMTIMING0 0x50
+#define CALTIMING0 0x7c
+#define CALTIMING1 0x80
+#define CALTIMING2 0x84
+#define CALTIMING3 0x88
+#define CALTIMING4 0x8c
+#define CALTIMING9 0xa0
+#define DRAMADDRW 0xa8
+#define DRAMSTS 0xec
+#define NIOSRESERVED0 0x110
+#define NIOSRESERVED1 0x114
+#define NIOSRESERVED2 0x118
+
+#define CTRLCFG3_CFG_CTRL_CMD_RATE_QUARTER BIT(2)
+#define CTRLCFG5_CFG_CTRL_RC_EN_MASK BIT(8)
+
+#define DRAMADDRW_CFG_COL_ADDR_WIDTH(x) \
+ ((x) & 0x1F)
+#define DRAMADDRW_CFG_ROW_ADDR_WIDTH(x) \
+ (((x) >> 5) & 0x1F)
+#define DRAMADDRW_CFG_BANK_ADDR_WIDTH(x) \
+ (((x) >> 10) & 0xF)
+#define DRAMADDRW_CFG_BANK_GRP_ADDR_WIDTH(x) \
+ (((x) >> 14) & 0x3)
+#define DRAMADDRW_CFG_CS_ADDR_WIDTH(x) \
+ (((x) >> 16) & 0x7)
+
+#define CTRLCFG0_CFG_MEMTYPE(x) \
+ ((x) & 0xF)
+#define CTRLCFG0_CFG_DIMM_TYPE(x) \
+ (((x) >> 4) & 0x7)
+#define CTRLCFG0_CFG_AC_POS(x) \
+ (((x) >> 7) & 0x3)
+#define CTRLCFG0_CFG_CTRL_BURST_LEN(x) \
+ (((x) >> 9) & 0x1F)
+
+#define CTRLCFG1_CFG_DBC3_BURST_LEN(x) \
+ ((x) & 0x1F)
+#define CTRLCFG1_CFG_ADDR_ORDER(x) \
+ (((x) >> 5) & 0x3)
+#define CTRLCFG1_CFG_CTRL_EN_ECC(x) \
+ (((x) >> 7) & 0x1)
+
+#define CTRLCFG6_CFG_CS_CHIP(x) \
+ ((x) & 0xFFFF)
+
+#define DRAMTIMING0_CFG_TCL(x) \
+ ((x) & 0x7F)
+
+#define CALTIMING0_CFG_ACT_TO_RDWR(x) \
+ ((x) & 0x3F)
+#define CALTIMING0_CFG_ACT_TO_PCH(x) \
+ (((x) >> 6) & 0x3F)
+#define CALTIMING0_CFG_ACT_TO_ACT(x) \
+ (((x) >> 12) & 0x3F)
+#define CALTIMING0_CFG_ACT_TO_ACT_DB(x) \
+ (((x) >> 18) & 0x3F)
+
+#define CALTIMING1_CFG_RD_TO_RD(x) \
+ ((x) & 0x3F)
+#define CALTIMING1_CFG_RD_TO_RD_DC(x) \
+ (((x) >> 6) & 0x3F)
+#define CALTIMING1_CFG_RD_TO_RD_DB(x) \
+ (((x) >> 12) & 0x3F)
+#define CALTIMING1_CFG_RD_TO_WR(x) \
+ (((x) >> 18) & 0x3F)
+#define CALTIMING1_CFG_RD_TO_WR_DC(x) \
+ (((x) >> 24) & 0x3F)
+
+#define CALTIMING2_CFG_RD_TO_WR_DB(x) \
+ ((x) & 0x3F)
+#define CALTIMING2_CFG_RD_TO_WR_PCH(x) \
+ (((x) >> 6) & 0x3F)
+#define CALTIMING2_CFG_RD_AP_TO_VALID(x) \
+ (((x) >> 12) & 0x3F)
+#define CALTIMING2_CFG_WR_TO_WR(x) \
+ (((x) >> 18) & 0x3F)
+#define CALTIMING2_CFG_WR_TO_WR_DC(x) \
+ (((x) >> 24) & 0x3F)
+
+#define CALTIMING3_CFG_WR_TO_WR_DB(x) \
+ ((x) & 0x3F)
+#define CALTIMING3_CFG_WR_TO_RD(x) \
+ (((x) >> 6) & 0x3F)
+#define CALTIMING3_CFG_WR_TO_RD_DC(x) \
+ (((x) >> 12) & 0x3F)
+#define CALTIMING3_CFG_WR_TO_RD_DB(x) \
+ (((x) >> 18) & 0x3F)
+#define CALTIMING3_CFG_WR_TO_PCH(x) \
+ (((x) >> 24) & 0x3F)
+
+#define CALTIMING4_CFG_WR_AP_TO_VALID(x) \
+ ((x) & 0x3F)
+#define CALTIMING4_CFG_PCH_TO_VALID(x) \
+ (((x) >> 6) & 0x3F)
+#define CALTIMING4_CFG_PCH_ALL_TO_VALID(x) \
+ (((x) >> 12) & 0x3F)
+#define CALTIMING4_CFG_ARF_TO_VALID(x) \
+ (((x) >> 18) & 0xFF)
+#define CALTIMING4_CFG_PDN_TO_VALID(x) \
+ (((x) >> 26) & 0x3F)
+
+#define CALTIMING9_CFG_4_ACT_TO_ACT(x) \
+ ((x) & 0xFF)
+
+/* Firewall DDR scheduler MPFE */
+#define FW_HMC_ADAPTOR_REG_ADDR 0xf8020004
+#define FW_HMC_ADAPTOR_MPU_MASK BIT(0)
+
+u32 hmc_readl(struct altera_sdram_plat *plat, u32 reg);
+u32 hmc_ecc_readl(struct altera_sdram_plat *plat, u32 reg);
+u32 hmc_ecc_writel(struct altera_sdram_plat *plat,
+ u32 data, u32 reg);
+u32 ddr_sch_writel(struct altera_sdram_plat *plat, u32 data,
+ u32 reg);
+int emif_clear(struct altera_sdram_plat *plat);
+int emif_reset(struct altera_sdram_plat *plat);
+int poll_hmc_clock_status(void);
+void sdram_clear_mem(phys_addr_t addr, phys_size_t size);
+//void sdram_set_firewall(struct bd_info *bd);
+phys_size_t sdram_calculate_size(struct altera_sdram_plat *plat);
+int agilex5_ddr_init_full(void);
+
+static inline resource_size_t agilex5_mpfe_sdram_size(void)
+{
+ u32 lower;
+ resource_size_t mem = 0;
+
+ lower = FW_MPU_DDR_DMI0_SCR_READL(SOCFPGA_FW_DDR_CCU_DMI0_ADDRESS +
+ FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT);
+
+ mem = lower;
+
+ return mem;
+}
+
+#endif /* _SDRAM_SOC64_H_ */
diff --git a/include/mach/socfpga/soc64-system-manager.h b/include/mach/socfpga/soc64-system-manager.h
new file mode 100644
index 0000000000000000000000000000000000000000..862e974b190245862dc7975cbeb281ba6b263dc7
--- /dev/null
+++ b/include/mach/socfpga/soc64-system-manager.h
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+* Copyright (C) 2019-2023 Intel Corporation <www.intel.com>
+ */
+
+#ifndef _SOC64_SYSTEM_MANAGER_H_
+#define _SOC64_SYSTEM_MANAGER_H_
+
+#include <linux/bitops.h>
+
+#define SYSMGR_SOC64_SILICONID_1 0x00
+#define SYSMGR_SOC64_SILICONID_2 0x04
+#define SYSMGR_SOC64_WDDBG 0x08
+#define SYSMGR_SOC64_MPU_STATUS 0x10
+#define SYSMGR_SOC64_SDMMC 0x28
+#define SYSMGR_SOC64_SDMMC_L3MASTER 0x2c
+#define SYSMGR_SOC64_COMBOPHY_DFISEL 0xfc
+#define SYSMGR_SOC64_COMBOPHY_DFISEL_SDMMC 0x1
+#define SYSMGR_SOC64_NANDGRP_L3MASTER 0x34
+#define SYSMGR_SOC64_USB0_L3MASTER 0x38
+#define SYSMGR_SOC64_USB1_L3MASTER 0x3c
+#define SYSMGR_SOC64_TSN_GLOBAL 0x40
+#define SYSMGR_SOC64_TSN_0 0x44
+#define SYSMGR_SOC64_TSN_1 0x48
+#define SYSMGR_SOC64_TSN_2 0x4C
+#define SYSMGR_SOC64_TSN_0_ACE 0x50
+#define SYSMGR_SOC64_TSN_1_ACE 0x54
+#define SYSMGR_SOC64_TSN_2_ACE 0x58
+#define SYSMGR_SOC64_FPGAINTF_EN1 0x68
+#define SYSMGR_SOC64_FPGAINTF_EN2 0x6C
+#define SYSMGR_SOC64_FPGAINTF_EN3 0x70
+#define SYSMGR_SOC64_DMAC0_L3_MASTER 0x74
+#define SYSMGR_SOC64_ETR_L3_MASTER 0x78
+#define SYSMGR_SOC64_DMAC1_L3_MASTER 0x7C
+#define SYSMGR_SOC64_SEC_CTRL_SLT 0x80
+#define SYSMGR_SOC64_OSC_TRIM 0x84
+#define SYSMGR_SOC64_DMAC0_CTRL_STATUS_REG 0x88
+#define SYSMGR_SOC64_DMAC1_CTRL_STATUS_REG 0x8C
+#define SYSMGR_SOC64_ECC_INTMASK_VALUE 0x90
+#define SYSMGR_SOC64_ECC_INTMASK_SET 0x94
+#define SYSMGR_SOC64_ECC_INTMASK_CLR 0x98
+#define SYSMGR_SOC64_ECC_INTMASK_SERR 0x9C
+#define SYSMGR_SOC64_ECC_INTMASK_DERR 0xA0
+#define SYSMGR_SOC64_NOC_TIMEOUT 0xC0
+#define SYSMGR_SOC64_NOC_IDLEREQ_SET 0xc4
+#define SYSMGR_SOC64_NOC_IDLEREQ_CLR 0xc8
+#define SYSMGR_SOC64_NOC_IDLEREQ_VAL 0xcc
+#define SYSMGR_SOC64_NOC_IDLEACK 0xd0
+#define SYSMGR_SOC64_NOC_IDLESTATUS 0xD4
+#define SYSMGR_SOC64_FPGA2SOC_CTRL 0xD8
+#define SYSMGR_SOC64_FPGA_CONFIG 0xDC
+#define SYSMGR_SOC64_BOOT_SCRATCH_COLD0 0x200
+#define SYSMGR_SOC64_BOOT_SCRATCH_COLD1 0x204
+#define SYSMGR_SOC64_BOOT_SCRATCH_COLD2 0x208
+#define SYSMGR_SOC64_BOOT_SCRATCH_COLD3 0x20C
+#define SYSMGR_SOC64_BOOT_SCRATCH_COLD4 0x210
+#define SYSMGR_SOC64_BOOT_SCRATCH_COLD5 0x214
+#define SYSMGR_SOC64_BOOT_SCRATCH_COLD6 0x218
+#define SYSMGR_SOC64_BOOT_SCRATCH_COLD7 0x21C
+#define SYSMGR_SOC64_BOOT_SCRATCH_COLD8 0x220
+#define SYSMGR_SOC64_BOOT_SCRATCH_COLD9 0x224
+#define SYSMGR_SOC64_MPFE_CONFIG 0x228
+#define SYSMGR_SOC64_BOOT_SCRATCH_POR0 0x258
+#define SYSMGR_SOC64_BOOT_SCRATCH_POR1 0x25C
+
+#define SYSMGR_SCRATCH_REG_0_QSPI_REFCLK_MASK GENMASK(31, 0)
+#define ALT_SYSMGR_SCRATCH_REG_3_DDR_RESET_TYPE_MASK GENMASK(31, 29)
+#define ALT_SYSMGR_SCRATCH_REG_3_DDR_RESET_TYPE_SHIFT 29
+#define ALT_SYSMGR_SCRATCH_REG_3_DDR_DBE_MASK BIT(1)
+#define ALT_SYSMGR_SCRATCH_REG_3_OCRAM_DBE_MASK BIT(0)
+#define ALT_SYSMGR_SCRATCH_REG_POR_0_DDR_PROGRESS_MASK BIT(0)
+#define ALT_SYSMGR_SCRATCH_REG_POR_1_REVA_WORKAROUND_USER_MODE_MASK BIT(0)
+#define ALT_SYSMGR_SCRATCH_REG_POR_1_REVA_WORKAROUND_MASK BIT(1)
+
+#define SYSMGR_SOC64_EMAC_GLOBAL SYSMGR_SOC64_TSN_GLOBAL
+#define SYSMGR_SOC64_EMAC0 SYSMGR_SOC64_TSN_0
+#define SYSMGR_SOC64_EMAC1 SYSMGR_SOC64_TSN_1
+#define SYSMGR_SOC64_EMAC2 SYSMGR_SOC64_TSN_2
+#define SYSMGR_SOC64_EMAC0_ACE SYSMGR_SOC64_TSN_0_ACE
+#define SYSMGR_SOC64_EMAC1_ACE SYSMGR_SOC64_TSN_1_ACE
+#define SYSMGR_SOC64_EMAC2_ACE SYSMGR_SOC64_TSN_2_ACE
+
+#define SYSMGR_SOC64_PINSEL0 0x1000
+#define SYSMGR_SOC64_IOCTRL0 0x1130
+#define SYSMGR_SOC64_EMAC0_USEFPGA 0x1300
+#define SYSMGR_SOC64_EMAC1_USEFPGA 0x1304
+#define SYSMGR_SOC64_EMAC2_USEFPGA 0x1308
+#define SYSMGR_SOC64_I2C0_USEFPGA 0x130c
+#define SYSMGR_SOC64_I2C1_USEFPGA 0x1310
+#define SYSMGR_SOC64_I2C_EMAC0_USEFPGA 0x1314
+#define SYSMGR_SOC64_I2C_EMAC1_USEFPGA 0x1318
+#define SYSMGR_SOC64_I2C_EMAC2_USEFPGA 0x131c
+#define SYSMGR_SOC64_NAND_USEFPGA 0x1320
+#define SYSMGR_SOC64_SPIM0_USEFPGA 0x1328
+#define SYSMGR_SOC64_SPIM1_USEFPGA 0x132c
+#define SYSMGR_SOC64_SPIS0_USEFPGA 0x1330
+#define SYSMGR_SOC64_SPIS1_USEFPGA 0x1334
+#define SYSMGR_SOC64_UART0_USEFPGA 0x1338
+#define SYSMGR_SOC64_UART1_USEFPGA 0x133c
+#define SYSMGR_SOC64_MDIO0_USEFPGA 0x1340
+#define SYSMGR_SOC64_MDIO1_USEFPGA 0x1344
+#define SYSMGR_SOC64_MDIO2_USEFPGA 0x1348
+#define SYSMGR_SOC64_JTAG_USEFPGA 0x1350
+#define SYSMGR_SOC64_SDMMC_USEFPGA 0x1354
+#define SYSMGR_SOC64_HPS_OSC_CLK 0x1358
+#define SYSMGR_SOC64_IODELAY0 0x1400
+#define SYSMGR_SOC64_PERI 0x15D0
+
+/*
+ * Bits for SYSMGR_SOC64_BOOT_SCRATCH_COLD8
+ * Bit[31] reserved for FSBL to check DBE is triggered (set by SDM to "1") ?
+ *
+ * Bit[30] reserved for FSBL to update the DDR init progress
+ * 1 - means in progress, 0 - haven't started / DDR is up running.
+ *
+* Bit[19] store ATF CPU0 ON OFF value.
+*
+ * Bit[18] reserved for SDM to configure ACF
+ * Bit[17:1] - Setting by Linux EDAC.
+ * Bit[1](ECC_OCRAM), Bit[16](ECC_DDR0), Bit[17](ECC_DDR1)
+ */
+#define ALT_SYSMGR_SCRATCH_REG_8_DDR_DBE_MASK BIT(31)
+#define ALT_SYSMGR_SCRATCH_REG_8_DDR_PROGRESS_MASK BIT(30)
+#define SYSMGR_SCRATCH_REG_8_ACF_DDR_RATE_MASK BIT(18)
+#define SYSMGR_SCRATCH_REG_8_ACF_DDR_RATE_SHIFT 18
+
+#define SYSMGR_SDMMC SYSMGR_SOC64_SDMMC
+
+#define SYSMGR_ROMCODEGRP_CTRL_WARMRSTCFGPINMUX BIT(0)
+#define SYSMGR_ROMCODEGRP_CTRL_WARMRSTCFGIO BIT(1)
+#define SYSMGR_ECC_OCRAM_EN BIT(0)
+#define SYSMGR_ECC_OCRAM_SERR BIT(3)
+#define SYSMGR_ECC_OCRAM_DERR BIT(4)
+#define SYSMGR_FPGACONFIG_FPGA_COMPLETE BIT(0)
+#define SYSMGR_FPGACONFIG_EARLY_USERMODE BIT(1)
+#define SYSMGR_FPGACONFIG_READY_MASK (SYSMGR_FPGACONFIG_FPGA_COMPLETE | \
+ SYSMGR_FPGACONFIG_EARLY_USERMODE)
+
+#define SYSMGR_FPGAINTF_USEFPGA 0x1
+#define SYSMGR_FPGAINTF_NAND BIT(4)
+#define SYSMGR_FPGAINTF_SDMMC BIT(8)
+#define SYSMGR_FPGAINTF_SPIM0 BIT(16)
+#define SYSMGR_FPGAINTF_SPIM1 BIT(24)
+#define SYSMGR_FPGAINTF_EMAC0 BIT(0)
+#define SYSMGR_FPGAINTF_EMAC1 BIT(8)
+#define SYSMGR_FPGAINTF_EMAC2 BIT(16)
+
+#define SYSMGR_SDMMC_SMPLSEL_SHIFT 4
+#define SYSMGR_SDMMC_DRVSEL_SHIFT 0
+
+/* EMAC Group Bit definitions */
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
+
+#define SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB 0
+#define SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB 2
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x3
+
+#define SYSMGR_NOC_H2F_MSK 0x00000001
+#define SYSMGR_NOC_LWH2F_MSK 0x00000010
+#define SYSMGR_HMC_CLK_STATUS_MSK 0x00000001
+
+#define SYSMGR_DMA_IRQ_NS 0xFF000000
+#define SYSMGR_DMA_MGR_NS 0x00010000
+
+#define SYSMGR_DMAPERIPH_ALL_NS 0xFFFFFFFF
+
+#define SYSMGR_WDDBG_PAUSE_ALL_CPU 0x0F0F0F0F
+
+void agilex5_security_interleaving_on(void);
+void agilex5_security_interleaving_off(void);
+void agilex5_initialize_security_policies(void);
+void agilex5_sysmgr_pinmux_init(void);
+
+#endif /* _SOC64_SYSTEM_MANAGER_H_ */
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 05/10] ARM: socfpga: add Arrow AXE5 Agilex5 board
2024-10-29 8:42 [PATCH 00/10] ARM: SoCFPGA: Add initial support for Agilex5 Steffen Trumtrar
` (3 preceding siblings ...)
2024-10-29 8:42 ` [PATCH 04/10] arm: socfgpa: add support for SoCFPGA Agilex5 Steffen Trumtrar
@ 2024-10-29 8:42 ` Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 06/10] net: add support for Designware XGMAC (10gb) ethernet Steffen Trumtrar
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Steffen Trumtrar @ 2024-10-29 8:42 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
Add the Agilex5-based Arrow AXE5-Eagle board.
It consists among other things of:
- Agilex5 SoCFPGA
- 1 GB LPDDR4 SDRAM for HPS
- 1 GB LPDDR4 SDRAM for FPGA
- 1 Gb QSPI for configuration via SDM
- microSD
- 4-port USB hub
- 2x 1Gb Ethernet
- HDMI output
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
arch/arm/boards/Makefile | 1 +
arch/arm/boards/arrow-axe5-eagle/Makefile | 3 +
arch/arm/boards/arrow-axe5-eagle/board.c | 23 +++++++
arch/arm/boards/arrow-axe5-eagle/lowlevel.c | 58 ++++++++++++++++++
arch/arm/configs/socfpga-agilex5_defconfig | 88 +++++++++++++++++++++++++++
arch/arm/dts/Makefile | 1 +
arch/arm/dts/socfpga_agilex5_axe5_eagle.dts | 94 +++++++++++++++++++++++++++++
images/Makefile.socfpga | 9 +++
8 files changed, 277 insertions(+)
diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index e0dc27cb3d21cc7bc763f148595321562d65d740..bc4d3bb4ea9e5691de90cbf7e6b0fbc577076732 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -111,6 +111,7 @@ obj-$(CONFIG_MACH_SAMA5D4_WIFX) += sama5d4_wifx/
obj-$(CONFIG_MACH_SCB9328) += scb9328/
obj-$(CONFIG_MACH_SEEED_ODYSSEY) += seeed-odyssey/
obj-$(CONFIG_MACH_SOCFPGA_ALTERA_SOCDK) += altera-socdk/
+obj-$(CONFIG_MACH_SOCFPGA_ARROW_AXE5_EAGLE) += arrow-axe5-eagle/
obj-$(CONFIG_MACH_SOCFPGA_EBV_SOCRATES) += ebv-socrates/
obj-$(CONFIG_MACH_SOCFPGA_ENCLUSTRA_AA1) += enclustra-aa1/
obj-$(CONFIG_MACH_SOCFPGA_REFLEX_ACHILLES) += reflex-achilles/
diff --git a/arch/arm/boards/arrow-axe5-eagle/Makefile b/arch/arm/boards/arrow-axe5-eagle/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..1d052d28c9fc6a82dbf806eedac60fac8a56d4f9
--- /dev/null
+++ b/arch/arm/boards/arrow-axe5-eagle/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+lwl-y += lowlevel.o
+obj-y += board.o
diff --git a/arch/arm/boards/arrow-axe5-eagle/board.c b/arch/arm/boards/arrow-axe5-eagle/board.c
new file mode 100644
index 0000000000000000000000000000000000000000..1efea0b3d9cf0aa5ecd7c67ea9348708dcfd0b80
--- /dev/null
+++ b/arch/arm/boards/arrow-axe5-eagle/board.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <bbu.h>
+#include <mach/socfpga/soc64-regs.h>
+
+static int axe5_init(void)
+{
+ if (!of_machine_is_compatible("arrow,axe5-eagle"))
+ return 0;
+
+ pr_debug("Change the pullup values on EMAC2 HPS mii signals\n");
+ writel(0x14, SOCFPGA_PINMUX_ADDRESS + 0x224);
+ writel(0x14, SOCFPGA_PINMUX_ADDRESS + 0x228);
+ writel(0x14, SOCFPGA_PINMUX_ADDRESS + 0x23c);
+ writel(0x14, SOCFPGA_PINMUX_ADDRESS + 0x234);
+ writel(0x14, SOCFPGA_PINMUX_ADDRESS + 0x248);
+ writel(0x14, SOCFPGA_PINMUX_ADDRESS + 0x24c);
+
+ return 0;
+}
+postcore_initcall(axe5_init);
diff --git a/arch/arm/boards/arrow-axe5-eagle/lowlevel.c b/arch/arm/boards/arrow-axe5-eagle/lowlevel.c
new file mode 100644
index 0000000000000000000000000000000000000000..f69d4d91f9ea9a60c17ae58d4f3c124663c600ff
--- /dev/null
+++ b/arch/arm/boards/arrow-axe5-eagle/lowlevel.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <common.h>
+#include <io.h>
+#include <linux/sizes.h>
+#include <asm/barebox-arm.h>
+#include <asm/system.h>
+#include <pbl.h>
+#include <mach/socfpga/debug_ll.h>
+#include <mach/socfpga/init.h>
+#include <mach/socfpga/generic.h>
+#include <mach/socfpga/mailbox_s10.h>
+#include <mach/socfpga/soc64-firewall.h>
+#include <mach/socfpga/soc64-regs.h>
+#include <mach/socfpga/soc64-sdram.h>
+#include <mach/socfpga/soc64-system-manager.h>
+
+extern char __dtb_z_socfpga_agilex5_axe5_eagle_start[];
+
+#define AXE5_STACKTOP (SZ_512K)
+
+static noinline void axe5_eagle_continue(void)
+{
+ void *fdt;
+
+ agilex5_clk_init();
+
+ socfpga_uart_setup_ll();
+ pbl_set_putc(socfpga_uart_putc, (void *) SOCFPGA_UART0_ADDRESS);
+
+ pr_debug("Lowlevel init done\n");
+
+ if (current_el() == 3) {
+ agilex5_initialize_security_policies();
+ pr_debug("Security policies initialized\n");
+
+ agilex5_ddr_init_full();
+
+ mbox_init();
+ mbox_qspi_open();
+
+ agilex5_load_and_start_image_via_tfa(SZ_1G);
+ }
+
+ fdt = __dtb_z_socfpga_agilex5_axe5_eagle_start;
+
+ barebox_arm_entry(SOCFPGA_AGILEX5_DDR_BASE + SZ_1M, SZ_1G - SZ_1M, fdt);
+}
+
+ENTRY_FUNCTION_WITHSTACK(start_socfpga_agilex5_axe5_eagle, AXE5_STACKTOP, r0, r1, r2)
+{
+ if (current_el() == 3)
+ socfpga_agilex5_cpu_lowlevel_init();
+
+ relocate_to_current_adr();
+ setup_c();
+
+ axe5_eagle_continue();
+}
diff --git a/arch/arm/configs/socfpga-agilex5_defconfig b/arch/arm/configs/socfpga-agilex5_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..b443a1281e6ad621d7270cade3ea0d60ccdc9af5
--- /dev/null
+++ b/arch/arm/configs/socfpga-agilex5_defconfig
@@ -0,0 +1,88 @@
+CONFIG_ARCH_SOCFPGA=y
+CONFIG_MACH_SOCFPGA_ARROW_AXE5_EAGLE=y
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_MMU=y
+CONFIG_MALLOC_SIZE=0x0
+CONFIG_MALLOC_TLSF=y
+CONFIG_KALLSYMS=y
+CONFIG_PROMPT="barebox> "
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+# CONFIG_TIMESTAMP is not set
+CONFIG_BOOTM_SHOW_TYPE=y
+CONFIG_BOOTM_VERBOSE=y
+CONFIG_BOOTM_INITRD=y
+CONFIG_BOOTM_OFTREE=y
+CONFIG_BOOTM_OFTREE_UIMAGE=y
+CONFIG_BOOTM_AIMAGE=y
+CONFIG_BLSPEC=y
+CONFIG_SYSTEM_PARTITIONS=y
+CONFIG_CONSOLE_ACTIVATE_FIRST=y
+CONFIG_CONSOLE_ALLOW_COLOR=y
+CONFIG_PBL_CONSOLE=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_RESET_SOURCE=y
+CONFIG_PRINTF_FULL=y
+CONFIG_CMD_DMESG=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_DEFAULTENV=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_SHA256SUM=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_LET=y
+CONFIG_CMD_READF=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_ETHLOG=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_LOGIN=y
+CONFIG_CMD_PASSWD=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_CLK=y
+CONFIG_CMD_DETECT=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_OF_DIFF=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OF_DISPLAY_TIMINGS=y
+CONFIG_CMD_OF_FIXUP_STATUS=y
+CONFIG_CMD_OF_OVERLAY=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_TIME=y
+CONFIG_NET=y
+CONFIG_OF_BAREBOX_DRIVERS=y
+CONFIG_OF_BAREBOX_ENV_IN_FS=y
+CONFIG_OF_OVERLAY_LIVE=y
+CONFIG_SERIAL_DEV_BUS=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+# CONFIG_SPI is not set
+CONFIG_MTD=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_SPI_CADENCE_QUADSPI=y
+CONFIG_MFD_SYSCON=y
+# CONFIG_PINCTRL is not set
+CONFIG_ARM_SCMI_PROTOCOL=y
+# CONFIG_VIRTIO_MENU is not set
+CONFIG_MAILBOX=y
+CONFIG_FS_TFTP=y
+CONFIG_ZLIB=y
+CONFIG_CRC_CCITT=y
+CONFIG_NLS=y
+# CONFIG_MISSING_FIRMWARE_ERROR is not set
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 3b3236b4165f7ff9fa7acb57bbf9c0ad597c778f..50b7429142ee2fb573d33166c76020975fb5b49f 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -137,6 +137,7 @@ lwl-$(CONFIG_MACH_SOCFPGA_REFLEX_ACHILLES) += socfpga_arria10_achilles.dtb.o
lwl-$(CONFIG_MACH_SOCFPGA_TERASIC_DE0_NANO_SOC) += socfpga_cyclone5_de0_nano_soc.dtb.o
lwl-$(CONFIG_MACH_SOCFPGA_TERASIC_DE10_NANO) += socfpga_cyclone5_de10_nano.dtb.o
lwl-$(CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT) += socfpga_cyclone5_sockit.dtb.o
+lwl-$(CONFIG_MACH_SOCFPGA_ARROW_AXE5_EAGLE) += socfpga_agilex5_axe5_eagle.dtb.o
lwl-$(CONFIG_MACH_SOLIDRUN_CUBOX) += dove-cubox-bb.dtb.o
lwl-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += imx6dl-hummingboard.dtb.o imx6q-hummingboard.dtb.o \
imx6dl-hummingboard2.dtb.o imx6q-hummingboard2.dtb.o \
diff --git a/arch/arm/dts/socfpga_agilex5_axe5_eagle.dts b/arch/arm/dts/socfpga_agilex5_axe5_eagle.dts
new file mode 100644
index 0000000000000000000000000000000000000000..cd12a2ccd22adca728dcf196a489fdc8c7b9347f
--- /dev/null
+++ b/arch/arm/dts/socfpga_agilex5_axe5_eagle.dts
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de>
+ */
+
+#include <arm64/intel/socfpga_agilex5.dtsi>
+#include "socfpga_agilex5.dtsi"
+
+/ {
+ model = "SoCFPGA Agilex5 AXE5-Eagle";
+ compatible = "arrow,axe5-eagle", "intel,socfpga-agilex","altr,socfpga";
+
+ aliases {
+ serial0 = &uart0;
+ ethernet0 = &gmac2;
+ };
+
+ chosen {
+ stdout-path = &uart0;
+ };
+
+ memory@80100000 {
+ device_type = "memory";
+ reg = <0 0x80100000 0 0x3ff00000>;
+ };
+};
+
+&osc1 {
+ clock-frequency = <25000000>;
+};
+
+&gpio0 {
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&qspi {
+ status = "okay";
+
+ flash0: flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "mt25qu02g";
+ reg = <0>;
+ spi-max-frequency = <100000000>;
+
+ m25p,fast-read;
+ cdns,page-size = <256>;
+ cdns,block-size = <16>;
+ cdns,read-delay = <1>;
+ cdns,tshsl-ns = <50>;
+ cdns,tsd2d-ns = <50>;
+ cdns,tchsh-ns = <4>;
+ cdns,tslch-ns = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ qspi_boot: partition@0 {
+ label = "u-boot";
+ reg = <0x0 0x04200000>;
+ };
+
+ root: partition@4200000 {
+ label = "root";
+ reg = <0x04200000 0x0BE00000>;
+ };
+ };
+ };
+};
+
+&gmac2 {
+ status = "okay";
+ phy-mode = "rgmii-id";
+ phy-handle = <&emac2_phy0>;
+
+ max-frame-size = <9000>;
+
+ mdio0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+ emac2_phy0: ethernet-phy@1 {
+ reg = <0x1>;
+ adi,rx-internal-delay-ps = <2000>;
+ adi,tx-internal-delay-ps = <2000>;
+ };
+ };
+};
diff --git a/images/Makefile.socfpga b/images/Makefile.socfpga
index 807ca78e4ac8636382107f844eeb83ba9007a583..db1a47b6a1ad7f6a7d08036bdeed6a50b707ac47 100644
--- a/images/Makefile.socfpga
+++ b/images/Makefile.socfpga
@@ -87,6 +87,15 @@ pblb-$(CONFIG_MACH_SOCFPGA_EBV_SOCRATES) += start_socfpga_socrates
FILE_barebox-socfpga-socrates.img = start_socfpga_socrates.pblb
socfpga-barebox-$(CONFIG_MACH_SOCFPGA_EBV_SOCRATES) += barebox-socfpga-socrates.img
+# ----------------------- Agilex5 based boards ---------------------------
+pblb-$(CONFIG_MACH_SOCFPGA_ARROW_AXE5_EAGLE) += start_socfpga_agilex5_axe5_eagle
+FILE_barebox-socfpga-agilex5-axe5-eagle.img = start_socfpga_agilex5_axe5_eagle.pblb.hex
+socfpga-barebox-$(CONFIG_MACH_SOCFPGA_ARROW_AXE5_EAGLE) += barebox-socfpga-agilex5-axe5-eagle.img
+
+pblb-$(CONFIG_MACH_SOCFPGA_ARROW_AXE5_EAGLE) += start_socfpga_agilex5_axe5_eagle
+FILE_barebox-socfpga-agilex5-axe5-eagle-2nd.img = start_socfpga_agilex5_axe5_eagle.pblb
+socfpga-barebox-$(CONFIG_MACH_SOCFPGA_ARROW_AXE5_EAGLE) += barebox-socfpga-agilex5-axe5-eagle-2nd.img
+
ifdef CONFIG_ARCH_SOCFPGA_XLOAD
image-y += $(socfpga-xload-y)
else
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 06/10] net: add support for Designware XGMAC (10gb) ethernet
2024-10-29 8:42 [PATCH 00/10] ARM: SoCFPGA: Add initial support for Agilex5 Steffen Trumtrar
` (4 preceding siblings ...)
2024-10-29 8:42 ` [PATCH 05/10] ARM: socfpga: add Arrow AXE5 Agilex5 board Steffen Trumtrar
@ 2024-10-29 8:42 ` Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 07/10] net: phy: add Analog Devices ADIN1300 Steffen Trumtrar
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Steffen Trumtrar @ 2024-10-29 8:42 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
The Designware XGMAC is designed for 1/2.5/5/10G ethernet applications.
It is mostly identical to the eqos driver but has a different register
layout.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
drivers/net/Kconfig | 18 +
drivers/net/Makefile | 2 +
drivers/net/designware_xgmac.c | 829 +++++++++++++++++++++++++++++++++
drivers/net/designware_xgmac.h | 294 ++++++++++++
drivers/net/designware_xgmac_socfpga.c | 156 +++++++
5 files changed, 1299 insertions(+)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 13e9ff6924bbf454c77487ca247c68c458d18f1a..b5134be4b8b3186cd765a1005ade6fade5dd939e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -140,6 +140,24 @@ config DRIVER_NET_DESIGNWARE_ROCKCHIP
help
This option enables support for the Ethernet MAC on different Rockchip SoCs
+config DRIVER_NET_DESIGNWARE_XGMAC
+ bool "Designware XGMAC Ethernet driver support" if COMPILE_TEST
+ depends on HAS_DMA && OFTREE
+ select PHYLIB
+ select MFD_SYSCON
+ help
+ This option enables support for the Synopsys Designware Ethernet XGMAC (10G Ethernet MAC).
+
+config DRIVER_NET_DESIGNWARE_XGMAC_SOCFPGA
+ bool "Designware XGMAC Ethernet driver support for SOCFPGA"
+ select DRIVER_NET_DESIGNWARE_XGMAC
+ depends on (ARCH_SOCFPGA_AGILEX5 || COMPILE_TEST)
+ select RESET_CONTROLLER if ARCH_SOCFPGA
+ select RESET_SIMPLE if ARCH_SOCFPGA_AGILEX5
+ help
+ This option enables support for the Synopsys Designware Ethernet XGMAC with specific configuration
+ for the Intel SoC FPGA chip.
+
config DRIVER_NET_DM9K
bool "Davicom dm9k[E|A|B] ethernet driver"
depends on HAS_DM9000 || COMPILE_TEST
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 207345cfa3688a4d65d2f7f20bd56cef32759024..76582fde366393905b05629772be175a3910b4c6 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -19,6 +19,8 @@ obj-$(CONFIG_DRIVER_NET_DESIGNWARE_IMX8) += designware_imx.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE_STM32) += designware_stm32.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE_TEGRA186) += designware_tegra186.o
obj-$(CONFIG_DRIVER_NET_DESIGNWARE_ROCKCHIP) += designware_rockchip.o
+obj-$(CONFIG_DRIVER_NET_DESIGNWARE_XGMAC) += designware_xgmac.o
+obj-$(CONFIG_DRIVER_NET_DESIGNWARE_XGMAC_SOCFPGA) += designware_xgmac_socfpga.o
obj-$(CONFIG_DRIVER_NET_DM9K) += dm9k.o
obj-$(CONFIG_DRIVER_NET_E1000) += e1000/
obj-$(CONFIG_DRIVER_NET_ENC28J60) += enc28j60.o
diff --git a/drivers/net/designware_xgmac.c b/drivers/net/designware_xgmac.c
new file mode 100644
index 0000000000000000000000000000000000000000..7b7c288ada559095d1c4fefb0a7823a5ba358ee7
--- /dev/null
+++ b/drivers/net/designware_xgmac.c
@@ -0,0 +1,829 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023, Intel Corporation.
+ *
+ * Portions based on U-Boot's dwc_eth_qos.c.
+ */
+
+/*
+ * This driver supports the Synopsys Designware Ethernet XGMAC (10G Ethernet
+ * MAC) IP block. The IP supports multiple options for bus type, clocking/
+ * reset structure, and feature list.
+ *
+ * The driver is written such that generic core logic is kept separate from
+ * configuration-specific logic. Code that interacts with configuration-
+ * specific resources is split out into separate functions to avoid polluting
+ * common code. If/when this driver is enhanced to support multiple
+ * configurations, the core code should be adapted to call all configuration-
+ * specific functions through function pointers, with the definition of those
+ * function pointers being supplied by struct udevice_id xgmac_ids[]'s .data
+ * field.
+ *
+ * This configuration uses an AXI master/DMA bus, an AHB slave/register bus,
+ * contains the DMA, MTL, and MAC sub-blocks, and supports a single RGMII PHY.
+ * This configuration also has SW control over all clock and reset signals to
+ * the HW block.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <dma.h>
+#include <errno.h>
+#include <malloc.h>
+#include <net.h>
+#include <of_net.h>
+#include <linux/iopoll.h>
+#include <linux/phy.h>
+#include <asm/cache.h>
+#include "designware_xgmac.h"
+
+static int xgmac_mdio_wait_idle(struct xgmac_priv *xgmac)
+{
+ u32 idle;
+
+ return readl_poll_timeout(&xgmac->mac_regs->mdio_data, idle,
+ !(idle & XGMAC_MAC_MDIO_ADDRESS_SBUSY),
+ XGMAC_TIMEOUT_100MS);
+}
+
+static int xgmac_mdio_read(struct mii_bus *bus, int mdio_addr, int mdio_reg)
+{
+ struct xgmac_priv *xgmac = bus->priv;
+ u32 val;
+ u32 hw_addr;
+ u32 idle;
+ int ret;
+
+ ret = readl_poll_timeout(&xgmac->mac_regs->mdio_data, idle,
+ !(idle & XGMAC_MAC_MDIO_ADDRESS_SBUSY),
+ XGMAC_TIMEOUT_100MS);
+ if (ret) {
+ pr_err("MDIO not idle at entry: %d\n", ret);
+ return ret;
+ }
+
+ /* Set clause 22 format */
+ val = BIT(mdio_addr);
+ writel(val, &xgmac->mac_regs->mdio_clause_22_port);
+
+ hw_addr = (mdio_addr << XGMAC_MAC_MDIO_ADDRESS_PA_SHIFT) |
+ (mdio_reg & XGMAC_MAC_MDIO_REG_ADDR_C22P_MASK);
+
+ val = xgmac->config->config_mac_mdio <<
+ XGMAC_MAC_MDIO_ADDRESS_CR_SHIFT;
+
+ val |= XGMAC_MAC_MDIO_ADDRESS_SADDR |
+ XGMAC_MDIO_SINGLE_CMD_ADDR_CMD_READ |
+ XGMAC_MAC_MDIO_ADDRESS_SBUSY;
+
+ ret = readl_poll_timeout(&xgmac->mac_regs->mdio_data, idle,
+ !(idle & XGMAC_MAC_MDIO_ADDRESS_SBUSY),
+ XGMAC_TIMEOUT_100MS);
+ if (ret) {
+ pr_err("MDIO not idle at entry: %d\n", ret);
+ return ret;
+ }
+
+ writel(hw_addr, &xgmac->mac_regs->mdio_address);
+ writel(val, &xgmac->mac_regs->mdio_data);
+
+ ret = readl_poll_timeout(&xgmac->mac_regs->mdio_data, idle,
+ !(idle & XGMAC_MAC_MDIO_ADDRESS_SBUSY),
+ XGMAC_TIMEOUT_100MS);
+ if (ret) {
+ pr_err("MDIO read didn't complete: %d\n", ret);
+ return ret;
+ }
+
+ val = readl(&xgmac->mac_regs->mdio_data);
+ val &= XGMAC_MAC_MDIO_DATA_GD_MASK;
+
+ return val;
+}
+
+static int xgmac_mdio_write(struct mii_bus *bus, int mdio_addr, int mdio_reg,
+ u16 mdio_val)
+{
+ struct xgmac_priv *xgmac = bus->priv;
+ u32 val;
+ u32 hw_addr;
+ int ret;
+
+ ret = xgmac_mdio_wait_idle(xgmac);
+ if (ret) {
+ pr_err("MDIO not idle at entry: %d\n", ret);
+ return ret;
+ }
+
+ /* Set clause 22 format */
+ val = BIT(mdio_addr);
+ writel(val, &xgmac->mac_regs->mdio_clause_22_port);
+
+ hw_addr = (mdio_addr << XGMAC_MAC_MDIO_ADDRESS_PA_SHIFT) |
+ (mdio_reg & XGMAC_MAC_MDIO_REG_ADDR_C22P_MASK);
+
+ hw_addr |= (mdio_reg >> XGMAC_MAC_MDIO_ADDRESS_PA_SHIFT) <<
+ XGMAC_MAC_MDIO_ADDRESS_DA_SHIFT;
+
+ val = (xgmac->config->config_mac_mdio <<
+ XGMAC_MAC_MDIO_ADDRESS_CR_SHIFT);
+
+ val |= XGMAC_MAC_MDIO_ADDRESS_SADDR |
+ mdio_val | XGMAC_MDIO_SINGLE_CMD_ADDR_CMD_WRITE |
+ XGMAC_MAC_MDIO_ADDRESS_SBUSY;
+
+ ret = xgmac_mdio_wait_idle(xgmac);
+ if (ret) {
+ pr_err("MDIO not idle at entry: %d\n", ret);
+ return ret;
+ }
+
+ writel(hw_addr, &xgmac->mac_regs->mdio_address);
+ writel(val, &xgmac->mac_regs->mdio_data);
+
+ ret = xgmac_mdio_wait_idle(xgmac);
+ if (ret) {
+ pr_err("MDIO write didn't complete: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int xgmac_set_full_duplex(struct device *dev)
+{
+ struct xgmac_priv *xgmac = dev_get_priv(dev);
+
+ clrbits_le32(&xgmac->mac_regs->mac_extended_conf, XGMAC_MAC_EXT_CONF_HD);
+
+ return 0;
+}
+
+static int xgmac_set_half_duplex(struct device *dev)
+{
+ struct xgmac_priv *xgmac = dev_get_priv(dev);
+
+ setbits_le32(&xgmac->mac_regs->mac_extended_conf, XGMAC_MAC_EXT_CONF_HD);
+
+ /* WAR: Flush TX queue when switching to half-duplex */
+ setbits_le32(&xgmac->mtl_regs->txq0_operation_mode,
+ XGMAC_MTL_TXQ0_OPERATION_MODE_FTQ);
+
+ return 0;
+}
+
+static int xgmac_set_gmii_speed(struct device *dev)
+{
+ struct xgmac_priv *xgmac = dev_get_priv(dev);
+
+ clrsetbits_le32(&xgmac->mac_regs->tx_configuration,
+ XGMAC_MAC_CONF_SS_SHIFT_MASK,
+ XGMAC_MAC_CONF_SS_1G_GMII << XGMAC_MAC_CONF_SS_SHIFT);
+
+ return 0;
+}
+
+static int xgmac_set_mii_speed_100(struct device *dev)
+{
+ struct xgmac_priv *xgmac = dev_get_priv(dev);
+
+ clrsetbits_le32(&xgmac->mac_regs->tx_configuration,
+ XGMAC_MAC_CONF_SS_SHIFT_MASK,
+ XGMAC_MAC_CONF_SS_100M_MII << XGMAC_MAC_CONF_SS_SHIFT);
+
+ return 0;
+}
+
+static int xgmac_set_mii_speed_10(struct device *dev)
+{
+ struct xgmac_priv *xgmac = dev_get_priv(dev);
+
+ clrsetbits_le32(&xgmac->mac_regs->tx_configuration,
+ XGMAC_MAC_CONF_SS_SHIFT_MASK,
+ XGMAC_MAC_CONF_SS_2_10M_MII << XGMAC_MAC_CONF_SS_SHIFT);
+
+ return 0;
+}
+
+static void xgmac_adjust_link(struct eth_device *edev)
+{
+ struct device *dev = edev->parent;
+ bool en_calibration;
+ int ret;
+
+ if (edev->phydev->duplex)
+ ret = xgmac_set_full_duplex(dev);
+ else
+ ret = xgmac_set_half_duplex(dev);
+ if (ret < 0) {
+ pr_err("xgmac_set_*_duplex() failed: %d\n", ret);
+ }
+
+ switch (edev->phydev->speed) {
+ case SPEED_1000:
+ en_calibration = true;
+ ret = xgmac_set_gmii_speed(dev);
+ break;
+ case SPEED_100:
+ en_calibration = true;
+ ret = xgmac_set_mii_speed_100(dev);
+ break;
+ case SPEED_10:
+ en_calibration = false;
+ ret = xgmac_set_mii_speed_10(dev);
+ break;
+ default:
+ pr_err("invalid speed %d\n", edev->phydev->speed);
+ }
+ if (ret < 0)
+ pr_err("xgmac_set_*mii_speed*() failed: %d\n", ret);
+}
+
+static int xgmac_write_hwaddr(struct eth_device *edev, const unsigned char *mac)
+{
+ struct xgmac_priv *xgmac = edev->priv;
+ u32 val;
+
+ memcpy(xgmac->macaddr, mac, ETH_ALEN);
+
+ /*
+ * This function may be called before start() or after stop(). At that
+ * time, on at least some configurations of the XGMAC HW, all clocks to
+ * the XGMAC HW block will be stopped, and a reset signal applied. If
+ * any register access is attempted in this state, bus timeouts or CPU
+ * hangs may occur. This check prevents that.
+ *
+ * A simple solution to this problem would be to not implement
+ * write_hwaddr(), since start() always writes the MAC address into HW
+ * anyway. However, it is desirable to implement write_hwaddr() to
+ * support the case of SW that runs subsequent to U-Boot which expects
+ * the MAC address to already be programmed into the XGMAC registers,
+ * which must happen irrespective of whether the U-Boot user (or
+ * scripts) actually made use of the XGMAC device, and hence
+ * irrespective of whether start() was ever called.
+ *
+ */
+ if (!xgmac->config->reg_access_always_ok && !xgmac->reg_access_ok)
+ return 0;
+
+ /* Update the MAC address */
+ val = (xgmac->macaddr[5] << 8) |
+ (xgmac->macaddr[4]);
+ writel(val, &xgmac->mac_regs->address0_high);
+ val = (xgmac->macaddr[3] << 24) |
+ (xgmac->macaddr[2] << 16) |
+ (xgmac->macaddr[1] << 8) |
+ (xgmac->macaddr[0]);
+ writel(val, &xgmac->mac_regs->address0_low);
+ return 0;
+}
+
+static int xgmac_read_rom_hwaddr(struct eth_device *edev, unsigned char *mac)
+{
+ struct xgmac_priv *xgmac = edev->priv;
+ int ret;
+
+ ret = xgmac->config->ops->xgmac_get_enetaddr(edev->parent);
+ if (ret < 0)
+ return ret;
+
+ return !is_valid_ether_addr(xgmac->macaddr);
+}
+
+static int xgmac_start(struct eth_device *edev)
+{
+ struct xgmac_priv *xgmac = edev->priv;
+ int ret, i;
+ u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl;
+ ulong last_rx_desc;
+ ulong desc_pad;
+ u32 idle;
+
+ ret = phy_device_connect(edev, &xgmac->miibus, xgmac->phy_addr,
+ xgmac_adjust_link, 0, xgmac->interface);
+ if (ret)
+ return ret;
+
+ ret = xgmac->config->ops->xgmac_start_resets(edev->parent);
+ if (ret < 0) {
+ pr_err("xgmac_start_resets() failed: %d\n", ret);
+ goto err;
+ }
+
+ xgmac->reg_access_ok = true;
+
+ setbits_le32(&xgmac->dma_regs->mode, XGMAC_DMA_MODE_SWR);
+
+ ret = readl_poll_timeout(&xgmac->dma_regs->mode, idle,
+ !(idle & XGMAC_DMA_MODE_SWR),
+ XGMAC_TIMEOUT_100MS);
+ if (ret) {
+ pr_err("XGMAC_DMA_MODE_SWR stuck: %d\n", ret);
+ goto err;
+ }
+
+ /* Configure MTL */
+
+ /* Enable Store and Forward mode for TX */
+ /* Program Tx operating mode */
+ setbits_le32(&xgmac->mtl_regs->txq0_operation_mode,
+ XGMAC_MTL_TXQ0_OPERATION_MODE_TSF |
+ (XGMAC_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED <<
+ XGMAC_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT));
+
+ /* Transmit Queue weight */
+ writel(0x10, &xgmac->mtl_regs->txq0_quantum_weight);
+
+ /* Enable Store and Forward mode for RX, since no jumbo frame */
+ setbits_le32(&xgmac->mtl_regs->rxq0_operation_mode,
+ XGMAC_MTL_RXQ0_OPERATION_MODE_RSF);
+
+ /* Transmit/Receive queue fifo size; use all RAM for 1 queue */
+ val = readl(&xgmac->mac_regs->hw_feature1);
+ tx_fifo_sz = (val >> XGMAC_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT) &
+ XGMAC_MAC_HW_FEATURE1_TXFIFOSIZE_MASK;
+ rx_fifo_sz = (val >> XGMAC_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT) &
+ XGMAC_MAC_HW_FEATURE1_RXFIFOSIZE_MASK;
+
+ /*
+ * r/tx_fifo_sz is encoded as log2(n / 128). Undo that by shifting.
+ * r/tqs is encoded as (n / 256) - 1.
+ */
+ tqs = (128 << tx_fifo_sz) / 256 - 1;
+ rqs = (128 << rx_fifo_sz) / 256 - 1;
+
+ clrsetbits_le32(&xgmac->mtl_regs->txq0_operation_mode,
+ XGMAC_MTL_TXQ0_OPERATION_MODE_TQS_MASK <<
+ XGMAC_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT,
+ tqs << XGMAC_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT);
+ clrsetbits_le32(&xgmac->mtl_regs->rxq0_operation_mode,
+ XGMAC_MTL_RXQ0_OPERATION_MODE_RQS_MASK <<
+ XGMAC_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT,
+ rqs << XGMAC_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT);
+
+ setbits_le32(&xgmac->mtl_regs->rxq0_operation_mode,
+ XGMAC_MTL_RXQ0_OPERATION_MODE_EHFC);
+
+ /* Configure MAC */
+ clrsetbits_le32(&xgmac->mac_regs->rxq_ctrl0,
+ XGMAC_MAC_RXQ_CTRL0_RXQ0EN_MASK <<
+ XGMAC_MAC_RXQ_CTRL0_RXQ0EN_SHIFT,
+ xgmac->config->config_mac <<
+ XGMAC_MAC_RXQ_CTRL0_RXQ0EN_SHIFT);
+
+ /* Multicast and Broadcast Queue Enable */
+ setbits_le32(&xgmac->mac_regs->rxq_ctrl1,
+ XGMAC_MAC_RXQ_CTRL1_MCBCQEN);
+
+ /* enable promisc mode and receive all mode */
+ setbits_le32(&xgmac->mac_regs->mac_packet_filter,
+ XGMAC_MAC_PACKET_FILTER_RA |
+ XGMAC_MAC_PACKET_FILTER_PR);
+
+ /* Set TX flow control parameters */
+ /* Set Pause Time */
+ setbits_le32(&xgmac->mac_regs->q0_tx_flow_ctrl,
+ XGMAC_MAC_Q0_TX_FLOW_CTRL_PT_MASK <<
+ XGMAC_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT);
+
+ /* Assign priority for RX flow control */
+ clrbits_le32(&xgmac->mac_regs->rxq_ctrl2,
+ XGMAC_MAC_RXQ_CTRL2_PSRQ0_MASK <<
+ XGMAC_MAC_RXQ_CTRL2_PSRQ0_SHIFT);
+
+ /* Enable flow control */
+ setbits_le32(&xgmac->mac_regs->q0_tx_flow_ctrl,
+ XGMAC_MAC_Q0_TX_FLOW_CTRL_TFE);
+ setbits_le32(&xgmac->mac_regs->rx_flow_ctrl,
+ XGMAC_MAC_RX_FLOW_CTRL_RFE);
+
+ clrbits_le32(&xgmac->mac_regs->tx_configuration,
+ XGMAC_MAC_CONF_JD);
+
+ clrbits_le32(&xgmac->mac_regs->rx_configuration,
+ XGMAC_MAC_CONF_JE |
+ XGMAC_MAC_CONF_GPSLCE |
+ XGMAC_MAC_CONF_WD);
+
+ setbits_le32(&xgmac->mac_regs->rx_configuration,
+ XGMAC_MAC_CONF_ACS |
+ XGMAC_MAC_CONF_CST);
+
+ /* Configure DMA */
+ clrsetbits_le32(&xgmac->dma_regs->sysbus_mode,
+ XGMAC_DMA_SYSBUS_MODE_AAL,
+ XGMAC_DMA_SYSBUS_MODE_EAME |
+ XGMAC_DMA_SYSBUS_MODE_UNDEF);
+
+ /* Enable OSP mode */
+ setbits_le32(&xgmac->dma_regs->ch0_tx_control,
+ XGMAC_DMA_CH0_TX_CONTROL_OSP);
+
+ /* RX buffer size. Must be a multiple of bus width */
+ clrsetbits_le32(&xgmac->dma_regs->ch0_rx_control,
+ XGMAC_DMA_CH0_RX_CONTROL_RBSZ_MASK <<
+ XGMAC_DMA_CH0_RX_CONTROL_RBSZ_SHIFT,
+ XGMAC_MAX_PACKET_SIZE <<
+ XGMAC_DMA_CH0_RX_CONTROL_RBSZ_SHIFT);
+
+ desc_pad = 0;
+
+ setbits_le32(&xgmac->dma_regs->ch0_control,
+ XGMAC_DMA_CH0_CONTROL_PBLX8 |
+ (desc_pad << XGMAC_DMA_CH0_CONTROL_DSL_SHIFT));
+
+ /*
+ * Burst length must be < 1/2 FIFO size.
+ * FIFO size in tqs is encoded as (n / 256) - 1.
+ * Each burst is n * 8 (PBLX8) * 16 (AXI width) == 128 bytes.
+ * Half of n * 256 is n * 128, so pbl == tqs, modulo the -1.
+ */
+ pbl = tqs + 1;
+ if (pbl > 32)
+ pbl = 32;
+
+ clrsetbits_le32(&xgmac->dma_regs->ch0_tx_control,
+ XGMAC_DMA_CH0_TX_CONTROL_TXPBL_MASK <<
+ XGMAC_DMA_CH0_TX_CONTROL_TXPBL_SHIFT,
+ pbl << XGMAC_DMA_CH0_TX_CONTROL_TXPBL_SHIFT);
+
+ clrsetbits_le32(&xgmac->dma_regs->ch0_rx_control,
+ XGMAC_DMA_CH0_RX_CONTROL_RXPBL_MASK <<
+ XGMAC_DMA_CH0_RX_CONTROL_RXPBL_SHIFT,
+ 8 << XGMAC_DMA_CH0_RX_CONTROL_RXPBL_SHIFT);
+
+ /* DMA performance configuration */
+ val = (XGMAC_DMA_SYSBUS_MODE_RD_OSR_LMT_MASK <<
+ XGMAC_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT) |
+ (XGMAC_DMA_SYSBUS_MODE_WR_OSR_LMT_MASK <<
+ XGMAC_DMA_SYSBUS_MODE_WR_OSR_LMT_SHIFT) |
+ XGMAC_DMA_SYSBUS_MODE_EAME |
+ XGMAC_DMA_SYSBUS_MODE_BLEN16 |
+ XGMAC_DMA_SYSBUS_MODE_BLEN8 |
+ XGMAC_DMA_SYSBUS_MODE_BLEN4 |
+ XGMAC_DMA_SYSBUS_MODE_BLEN32;
+
+ writel(val, &xgmac->dma_regs->sysbus_mode);
+
+ /* Set up descriptors */
+
+ xgmac->tx_desc_idx = 0;
+ xgmac->rx_desc_idx = 0;
+
+ for (i = 0; i < XGMAC_DESCRIPTORS_NUM; i++) {
+ struct xgmac_desc *rx_desc = &xgmac->rx_descs[i];
+
+ writel(XGMAC_DESC3_OWN, &rx_desc->des3);
+ }
+
+ writel(0, &xgmac->dma_regs->ch0_txdesc_list_haddress);
+ writel(xgmac->tx_descs_phys, &xgmac->dma_regs->ch0_txdesc_list_address);
+ writel(XGMAC_DESCRIPTORS_NUM - 1,
+ &xgmac->dma_regs->ch0_txdesc_ring_length);
+
+ writel(0, &xgmac->dma_regs->ch0_rxdesc_list_haddress);
+ writel(xgmac->rx_descs_phys, &xgmac->dma_regs->ch0_rxdesc_list_address);
+ writel(XGMAC_DESCRIPTORS_NUM - 1,
+ &xgmac->dma_regs->ch0_rxdesc_ring_length);
+
+ /* Enable everything */
+ setbits_le32(&xgmac->dma_regs->ch0_tx_control,
+ XGMAC_DMA_CH0_TX_CONTROL_ST);
+ setbits_le32(&xgmac->dma_regs->ch0_rx_control,
+ XGMAC_DMA_CH0_RX_CONTROL_SR);
+ setbits_le32(&xgmac->mac_regs->tx_configuration,
+ XGMAC_MAC_CONF_TE);
+ setbits_le32(&xgmac->mac_regs->rx_configuration,
+ XGMAC_MAC_CONF_RE);
+
+ /* TX tail pointer not written until we need to TX a packet */
+ /*
+ * Point RX tail pointer at last descriptor. Ideally, we'd point at the
+ * first descriptor, implying all descriptors were available. However,
+ * that's not distinguishable from none of the descriptors being
+ * available.
+ */
+ last_rx_desc = (ulong)&xgmac->rx_descs[(XGMAC_DESCRIPTORS_NUM - 1)];
+ writel(last_rx_desc, &xgmac->dma_regs->ch0_rxdesc_tail_pointer);
+
+ xgmac->started = true;
+
+ return 0;
+
+err:
+ return ret;
+}
+
+static void xgmac_stop(struct eth_device *edev)
+{
+ struct xgmac_priv *xgmac = edev->priv;
+ u64 start_time;
+ u32 val;
+ u32 trcsts;
+ u32 txqsts;
+ u32 prxq;
+ u32 rxqsts;
+
+ debug("%s(dev=%p):\n", __func__, edev);
+
+ if (!xgmac->started)
+ return;
+ xgmac->started = false;
+ xgmac->reg_access_ok = false;
+
+ /* Disable TX DMA */
+ clrbits_le32(&xgmac->dma_regs->ch0_tx_control,
+ XGMAC_DMA_CH0_TX_CONTROL_ST);
+
+ /* Wait for TX all packets to drain out of MTL */
+ start_time = get_time_ns();
+
+ while (!is_timeout(start_time, XGMAC_TIMEOUT_100MS)) {
+ val = readl(&xgmac->mtl_regs->txq0_debug);
+
+ trcsts = (val >> XGMAC_MTL_TXQ0_DEBUG_TRCSTS_SHIFT) &
+ XGMAC_MTL_TXQ0_DEBUG_TRCSTS_MASK;
+
+ txqsts = val & XGMAC_MTL_TXQ0_DEBUG_TXQSTS;
+
+ if (trcsts != XGMAC_MTL_TXQ0_DEBUG_TRCSTS_READ_STATE && !txqsts)
+ break;
+ }
+
+ /* Turn off MAC TX and RX */
+ clrbits_le32(&xgmac->mac_regs->tx_configuration,
+ XGMAC_MAC_CONF_RE);
+ clrbits_le32(&xgmac->mac_regs->rx_configuration,
+ XGMAC_MAC_CONF_RE);
+
+ /* Wait for all RX packets to drain out of MTL */
+ start_time = get_time_ns();
+
+ while (!is_timeout(start_time, XGMAC_TIMEOUT_100MS)) {
+ val = readl(&xgmac->mtl_regs->rxq0_debug);
+
+ prxq = (val >> XGMAC_MTL_RXQ0_DEBUG_PRXQ_SHIFT) &
+ XGMAC_MTL_RXQ0_DEBUG_PRXQ_MASK;
+
+ rxqsts = (val >> XGMAC_MTL_RXQ0_DEBUG_RXQSTS_SHIFT) &
+ XGMAC_MTL_RXQ0_DEBUG_RXQSTS_MASK;
+
+ if (!prxq && !rxqsts)
+ break;
+ }
+
+ /* Turn off RX DMA */
+ clrbits_le32(&xgmac->dma_regs->ch0_rx_control,
+ XGMAC_DMA_CH0_RX_CONTROL_SR);
+}
+
+static int xgmac_send(struct eth_device *edev, void *packet, int length)
+{
+ struct xgmac_priv *xgmac = edev->priv;
+ struct xgmac_desc *tx_desc;
+ dma_addr_t dma;
+ u32 des3_prev, des3;
+ int ret;
+
+ tx_desc = &xgmac->tx_descs[xgmac->tx_desc_idx];
+ xgmac->tx_desc_idx++;
+ xgmac->tx_desc_idx %= XGMAC_DESCRIPTORS_NUM;
+
+ dma = dma_map_single(edev->parent, packet, length, DMA_TO_DEVICE);
+ if (dma_mapping_error(edev->parent, dma))
+ return -EFAULT;
+
+ tx_desc->des0 = dma;
+ tx_desc->des1 = 0;
+ tx_desc->des2 = length;
+ /*
+ * Make sure that if HW sees the _OWN write below, it will see all the
+ * writes to the rest of the descriptor too.
+ */
+ barrier();
+
+ des3_prev = XGMAC_DESC3_OWN | XGMAC_DESC3_FD | XGMAC_DESC3_LD | length;
+ writel(des3_prev, &tx_desc->des3);
+ writel((ulong)(tx_desc + 1), &xgmac->dma_regs->ch0_txdesc_tail_pointer); // <-- TODO
+
+ ret = readl_poll_timeout(&tx_desc->des3, des3,
+ !(des3 & XGMAC_DESC3_OWN),
+ 100 * USEC_PER_MSEC);
+
+ dma_unmap_single(edev->parent, dma, length, DMA_TO_DEVICE);
+
+ if (ret == -ETIMEDOUT)
+ debug("%s: TX timeout 0x%08x\n", __func__, des3);
+
+ return ret;
+}
+
+static void xgmac_recv(struct eth_device *edev)
+{
+ struct xgmac_priv *xgmac = edev->priv;
+ struct xgmac_desc *rx_desc;
+ dma_addr_t dma;
+ void *pkt;
+ int length;
+
+ rx_desc = &xgmac->rx_descs[xgmac->rx_desc_idx];
+
+ if (rx_desc->des3 & XGMAC_DESC3_OWN)
+ return;
+
+ dma = xgmac->dma_rx_buf[xgmac->rx_desc_idx];
+ pkt = phys_to_virt(dma);
+ length = rx_desc->des3 & XGMAC_RDES3_PKT_LENGTH_MASK;
+
+ dma_sync_single_for_cpu(edev->parent, (unsigned long)pkt, length,
+ DMA_FROM_DEVICE);
+ net_receive(edev, pkt, length);
+ dma_sync_single_for_device(edev->parent, (unsigned long)pkt,
+ length, DMA_FROM_DEVICE);
+
+ /* Read Format RX descriptor */
+ rx_desc = &xgmac->rx_descs[xgmac->rx_desc_idx];
+ rx_desc->des0 = dma;
+ rx_desc->des1 = 0;
+ rx_desc->des2 = 0;
+ /*
+ * Make sure that if HW sees the _OWN write below, it will see all the
+ * writes to the rest of the descriptor too.
+ */
+ rx_desc->des3 = XGMAC_DESC3_OWN;
+ barrier();
+
+ writel((ulong)rx_desc, &xgmac->dma_regs->ch0_rxdesc_tail_pointer);
+
+ xgmac->rx_desc_idx++;
+ xgmac->rx_desc_idx %= XGMAC_DESCRIPTORS_NUM;
+}
+
+static int xgmac_probe_resources_core(struct device *dev)
+{
+ struct xgmac_priv *xgmac = dev_get_priv(dev);
+ unsigned int desc_step;
+ int ret = 0;
+ void *p;
+ int i;
+
+ /* Maximum distance between neighboring descriptors, in Bytes. */
+ desc_step = sizeof(struct xgmac_desc);
+
+ xgmac->tx_descs = dma_alloc_coherent(XGMAC_DESCRIPTORS_SIZE,
+ &xgmac->tx_descs_phys);
+ if (!xgmac->tx_descs) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ xgmac->rx_descs = dma_alloc_coherent(XGMAC_DESCRIPTORS_SIZE,
+ &xgmac->rx_descs_phys);
+ if (!xgmac->rx_descs) {
+ ret = -ENOMEM;
+ goto err_free_tx_descs;
+ }
+
+ p = dma_alloc(XGMAC_RX_BUFFER_SIZE);
+ if (!p)
+ goto err_free_descs;
+
+ for (i = 0; i < XGMAC_DESCRIPTORS_NUM; i++) {
+ struct xgmac_desc *rx_desc = &xgmac->rx_descs[i];
+ dma_addr_t dma;
+
+ dma = dma_map_single(dev, p, XGMAC_MAX_PACKET_SIZE, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, dma)) {
+ ret = -EFAULT;
+ goto err_free_dma_bufs;
+ }
+
+ rx_desc->des0 = dma;
+ xgmac->dma_rx_buf[i] = dma;
+
+ p += XGMAC_MAX_PACKET_SIZE;
+ }
+
+ return 0;
+
+err_free_dma_bufs:
+ dma_free(phys_to_virt(xgmac->rx_descs[0].des0));
+err_free_descs:
+ dma_free_coherent(xgmac->rx_descs, xgmac->rx_descs_phys, XGMAC_DESCRIPTORS_SIZE);
+err_free_tx_descs:
+ dma_free_coherent(xgmac->tx_descs, xgmac->tx_descs_phys, XGMAC_DESCRIPTORS_SIZE);
+err:
+
+ return ret;
+}
+
+static int xgmac_remove_resources_core(struct device *dev)
+{
+ struct xgmac_priv *xgmac = dev_get_priv(dev);
+
+ dma_free(xgmac->rx_dma_buf);
+ dma_free_coherent(xgmac->rx_descs, xgmac->rx_descs_phys, XGMAC_DESCRIPTORS_SIZE);
+ dma_free_coherent(xgmac->tx_descs, xgmac->tx_descs_phys, XGMAC_DESCRIPTORS_SIZE);
+
+ return 0;
+}
+
+static void xgmac_probe_dt(struct device *dev, struct xgmac_priv *xgmac)
+{
+ struct device_node *child;
+
+ xgmac->interface = of_get_phy_mode(dev->of_node);
+ xgmac->phy_addr = 0;
+
+ /* Set MDIO bus device node, if present. */
+ for_each_child_of_node(dev->of_node, child) {
+ if (of_device_is_compatible(child, "snps,dwmac-mdio") ||
+ (child->name && !of_node_cmp(child->name, "mdio"))) {
+ xgmac->miibus.dev.of_node = child;
+ break;
+ }
+ }
+}
+
+int xgmac_probe(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct mii_bus *miibus;
+ struct xgmac_priv *xgmac;
+ struct resource *iores;
+ struct eth_device *edev;
+ int ret = 0;
+
+ xgmac = xzalloc(sizeof(*xgmac));
+
+ xgmac->dev = dev;
+ ret = dev_get_drvdata(dev, (const void **)&xgmac->config);
+ if (ret < 0) {
+ pr_err("xgmac_probe() failed to get driver data: %d\n", ret);
+ return ret;
+ }
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+ xgmac->regs = IOMEM(iores->start);
+
+ xgmac->mac_regs = (void *)(xgmac->regs + XGMAC_MAC_REGS_BASE);
+ xgmac->mtl_regs = (void *)(xgmac->regs + XGMAC_MTL_REGS_BASE);
+ xgmac->dma_regs = (void *)(xgmac->regs + XGMAC_DMA_REGS_BASE);
+
+ xgmac_probe_dt(dev, xgmac);
+
+ edev = &xgmac->netdev;
+ dev->priv = edev->priv = xgmac;
+
+ edev->parent = dev;
+ edev->open = xgmac_start;
+ edev->send = xgmac_send;
+ edev->halt = xgmac_stop;
+ edev->recv = xgmac_recv;
+ edev->get_ethaddr = xgmac_read_rom_hwaddr;
+ edev->set_ethaddr = xgmac_write_hwaddr;
+
+ of_property_read_u32(np, "max-speed", &xgmac->max_speed);
+
+ miibus = &xgmac->miibus;
+ miibus->parent = edev->parent;
+ miibus->read = xgmac_mdio_read;
+ miibus->write = xgmac_mdio_write;
+ miibus->priv = xgmac;
+
+ ret = xgmac_probe_resources_core(dev);
+ if (ret < 0) {
+ pr_err("xgmac_probe_resources_core() failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = xgmac->config->ops->xgmac_probe_resources(dev);
+ if (ret < 0) {
+ pr_err("xgmac_probe_resources() failed: %d\n", ret);
+ goto err_remove_resources_core;
+ }
+
+ ret = mdiobus_register(miibus);
+ if (ret)
+ return ret;
+
+ return eth_register(edev);
+
+err_remove_resources_core:
+ xgmac_remove_resources_core(dev);
+
+ return ret;
+}
+
+void xgmac_remove(struct device *dev)
+{
+ struct xgmac_priv *xgmac = dev_get_priv(dev);
+
+ eth_unregister(&xgmac->netdev);
+ mdiobus_unregister(&xgmac->miibus);
+
+ xgmac_remove_resources_core(dev);
+}
diff --git a/drivers/net/designware_xgmac.h b/drivers/net/designware_xgmac.h
new file mode 100644
index 0000000000000000000000000000000000000000..f6d39adf6c21cd7c17805add7aee3ffe396e18a4
--- /dev/null
+++ b/drivers/net/designware_xgmac.h
@@ -0,0 +1,294 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2023 Intel Coporation.
+ */
+
+#include <linux/bitops.h>
+#include <linux/phy.h>
+
+/* Core registers */
+
+#define XGMAC_MAC_REGS_BASE 0x000
+
+struct xgmac_mac_regs {
+ u32 tx_configuration; /* 0x000 */
+ u32 rx_configuration; /* 0x004 */
+ u32 mac_packet_filter; /* 0x008 */
+ u32 unused_00c[(0x070 - 0x00c) / 4]; /* 0x00c */
+ u32 q0_tx_flow_ctrl; /* 0x070 */
+ u32 unused_070[(0x090 - 0x074) / 4]; /* 0x074 */
+ u32 rx_flow_ctrl; /* 0x090 */
+ u32 unused_094[(0x0a0 - 0x094) / 4]; /* 0x094 */
+ u32 rxq_ctrl0; /* 0x0a0 */
+ u32 rxq_ctrl1; /* 0x0a4 */
+ u32 rxq_ctrl2; /* 0x0a8 */
+ u32 unused_0ac[(0x0dc - 0x0ac) / 4]; /* 0x0ac */
+ u32 us_tic_counter; /* 0x0dc */
+ u32 unused_0e0[(0x11c - 0x0e0) / 4]; /* 0x0e0 */
+ u32 hw_feature0; /* 0x11c */
+ u32 hw_feature1; /* 0x120 */
+ u32 hw_feature2; /* 0x124 */
+ u32 hw_feature3; /* 0x128 */
+ u32 hw_feature4; /* 0x12c */
+ u32 unused_130[(0x140 - 0x130) / 4]; /* 0x130 */
+ u32 mac_extended_conf; /* 0x140 */
+ u32 unused_144[(0x200 - 0x144) / 4]; /* 0x144 */
+ u32 mdio_address; /* 0x200 */
+ u32 mdio_data; /* 0x204 */
+ u32 mdio_cont_write_addr; /* 0x208 */
+ u32 mdio_cont_write_data; /* 0x20c */
+ u32 mdio_cont_scan_port_enable; /* 0x210 */
+ u32 mdio_intr_status; /* 0x214 */
+ u32 mdio_intr_enable; /* 0x218 */
+ u32 mdio_port_cnct_dsnct_status; /* 0x21c */
+ u32 mdio_clause_22_port; /* 0x220 */
+ u32 unused_224[(0x300 - 0x224) / 4]; /* 0x224 */
+ u32 address0_high; /* 0x300 */
+ u32 address0_low; /* 0x304 */
+};
+
+#define XGMAC_TIMEOUT_100MS 100000
+#define XGMAC_MAC_CONF_SS_SHIFT 29
+#define XGMAC_MAC_CONF_SS_SHIFT_MASK GENMASK(31, 29)
+#define XGMAC_MAC_CONF_SS_10G_XGMII 0
+#define XGMAC_MAC_CONF_SS_2_5G_GMII 2
+#define XGMAC_MAC_CONF_SS_1G_GMII 3
+#define XGMAC_MAC_CONF_SS_100M_MII 4
+#define XGMAC_MAC_CONF_SS_5G_XGMII 5
+#define XGMAC_MAC_CONF_SS_2_5G_XGMII 6
+#define XGMAC_MAC_CONF_SS_2_10M_MII 7
+
+#define XGMAC_MAC_CONF_JD BIT(16)
+#define XGMAC_MAC_CONF_JE BIT(8)
+#define XGMAC_MAC_CONF_WD BIT(7)
+#define XGMAC_MAC_CONF_GPSLCE BIT(6)
+#define XGMAC_MAC_CONF_CST BIT(2)
+#define XGMAC_MAC_CONF_ACS BIT(1)
+#define XGMAC_MAC_CONF_TE BIT(0)
+#define XGMAC_MAC_CONF_RE BIT(0)
+
+#define XGMAC_MAC_EXT_CONF_HD BIT(24)
+
+#define XGMAC_MAC_PACKET_FILTER_RA BIT(31)
+#define XGMAC_MAC_PACKET_FILTER_PR BIT(0)
+
+#define XGMAC_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT 16
+#define XGMAC_MAC_Q0_TX_FLOW_CTRL_PT_MASK GENMASK(15, 0)
+#define XGMAC_MAC_Q0_TX_FLOW_CTRL_TFE BIT(1)
+
+#define XGMAC_MAC_RX_FLOW_CTRL_RFE BIT(0)
+#define XGMAC_MAC_RXQ_CTRL0_RXQ0EN_SHIFT 0
+#define XGMAC_MAC_RXQ_CTRL0_RXQ0EN_MASK GENMASK(1, 0)
+#define XGMAC_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED 0
+#define XGMAC_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB 2
+#define XGMAC_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV 1
+
+#define XGMAC_MAC_RXQ_CTRL1_MCBCQEN BIT(15)
+
+#define XGMAC_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0
+#define XGMAC_MAC_RXQ_CTRL2_PSRQ0_MASK GENMASK(7, 0)
+
+#define XGMAC_MAC_HW_FEATURE1_TXFIFOSIZE_SHIFT 6
+#define XGMAC_MAC_HW_FEATURE1_TXFIFOSIZE_MASK GENMASK(4, 0)
+#define XGMAC_MAC_HW_FEATURE1_RXFIFOSIZE_SHIFT 0
+#define XGMAC_MAC_HW_FEATURE1_RXFIFOSIZE_MASK GENMASK(4, 0)
+
+#define XGMAC_MDIO_SINGLE_CMD_SHIFT 16
+#define XGMAC_MDIO_SINGLE_CMD_ADDR_CMD_READ 3 << XGMAC_MDIO_SINGLE_CMD_SHIFT
+#define XGMAC_MDIO_SINGLE_CMD_ADDR_CMD_WRITE BIT(16)
+#define XGMAC_MAC_MDIO_ADDRESS_PA_SHIFT 16
+#define XGMAC_MAC_MDIO_ADDRESS_PA_MASK GENMASK(15, 0)
+#define XGMAC_MAC_MDIO_ADDRESS_DA_SHIFT 21
+#define XGMAC_MAC_MDIO_ADDRESS_CR_SHIFT 19
+#define XGMAC_MAC_MDIO_ADDRESS_CR_100_150 0
+#define XGMAC_MAC_MDIO_ADDRESS_CR_150_250 1
+#define XGMAC_MAC_MDIO_ADDRESS_CR_250_300 2
+#define XGMAC_MAC_MDIO_ADDRESS_CR_300_350 3
+#define XGMAC_MAC_MDIO_ADDRESS_CR_350_400 4
+#define XGMAC_MAC_MDIO_ADDRESS_CR_400_500 5
+#define XGMAC_MAC_MDIO_ADDRESS_SADDR BIT(18)
+#define XGMAC_MAC_MDIO_ADDRESS_SBUSY BIT(22)
+#define XGMAC_MAC_MDIO_REG_ADDR_C22P_MASK GENMASK(4, 0)
+#define XGMAC_MAC_MDIO_DATA_GD_MASK GENMASK(15, 0)
+
+/* MTL Registers */
+
+#define XGMAC_MTL_REGS_BASE 0x1000
+
+struct xgmac_mtl_regs {
+ u32 mtl_operation_mode; /* 0x1000 */
+ u32 unused_1004[(0x1030 - 0x1004) / 4]; /* 0x1004 */
+ u32 mtl_rxq_dma_map0; /* 0x1030 */
+ u32 mtl_rxq_dma_map1; /* 0x1034 */
+ u32 mtl_rxq_dma_map2; /* 0x1038 */
+ u32 mtl_rxq_dma_map3; /* 0x103c */
+ u32 mtl_tc_prty_map0; /* 0x1040 */
+ u32 mtl_tc_prty_map1; /* 0x1044 */
+ u32 unused_1048[(0x1100 - 0x1048) / 4]; /* 0x1048 */
+ u32 txq0_operation_mode; /* 0x1100 */
+ u32 unused_1104; /* 0x1104 */
+ u32 txq0_debug; /* 0x1108 */
+ u32 unused_100c[(0x1118 - 0x110c) / 4]; /* 0x110c */
+ u32 txq0_quantum_weight; /* 0x1118 */
+ u32 unused_111c[(0x1140 - 0x111c) / 4]; /* 0x111c */
+ u32 rxq0_operation_mode; /* 0x1140 */
+ u32 unused_1144; /* 0x1144 */
+ u32 rxq0_debug; /* 0x1148 */
+};
+
+#define XGMAC_MTL_TXQ0_OPERATION_MODE_TQS_SHIFT 16
+#define XGMAC_MTL_TXQ0_OPERATION_MODE_TQS_MASK GENMASK(8, 0)
+#define XGMAC_MTL_TXQ0_OPERATION_MODE_TXQEN_SHIFT 2
+#define XGMAC_MTL_TXQ0_OPERATION_MODE_TXQEN_ENABLED 2
+#define XGMAC_MTL_TXQ0_OPERATION_MODE_TSF BIT(1)
+#define XGMAC_MTL_TXQ0_OPERATION_MODE_FTQ BIT(0)
+
+#define XGMAC_MTL_TXQ0_DEBUG_TXQSTS BIT(4)
+#define XGMAC_MTL_TXQ0_DEBUG_TRCSTS_SHIFT 1
+#define XGMAC_MTL_TXQ0_DEBUG_TRCSTS_MASK GENMASK(2, 0)
+#define XGMAC_MTL_TXQ0_DEBUG_TRCSTS_READ_STATE 0x1
+
+#define XGMAC_MTL_RXQ0_OPERATION_MODE_RQS_SHIFT 16
+#define XGMAC_MTL_RXQ0_OPERATION_MODE_RQS_MASK GENMASK(9, 0)
+#define XGMAC_MTL_RXQ0_OPERATION_MODE_EHFC BIT(7)
+#define XGMAC_MTL_RXQ0_OPERATION_MODE_RSF BIT(5)
+
+#define XGMAC_MTL_RXQ0_DEBUG_PRXQ_SHIFT 16
+#define XGMAC_MTL_RXQ0_DEBUG_PRXQ_MASK GENMASK(14, 0)
+#define XGMAC_MTL_RXQ0_DEBUG_RXQSTS_SHIFT 4
+#define XGMAC_MTL_RXQ0_DEBUG_RXQSTS_MASK GENMASK(1, 0)
+
+/* DMA Registers */
+
+#define XGMAC_DMA_REGS_BASE 0x3000
+
+struct xgmac_dma_regs {
+ u32 mode; /* 0x3000 */
+ u32 sysbus_mode; /* 0x3004 */
+ u32 unused_3008[(0x3100 - 0x3008) / 4]; /* 0x3008 */
+ u32 ch0_control; /* 0x3100 */
+ u32 ch0_tx_control; /* 0x3104 */
+ u32 ch0_rx_control; /* 0x3108 */
+ u32 slot_func_control_status; /* 0x310c */
+ u32 ch0_txdesc_list_haddress; /* 0x3110 */
+ u32 ch0_txdesc_list_address; /* 0x3114 */
+ u32 ch0_rxdesc_list_haddress; /* 0x3118 */
+ u32 ch0_rxdesc_list_address; /* 0x311c */
+ u32 unused_3120; /* 0x3120 */
+ u32 ch0_txdesc_tail_pointer; /* 0x3124 */
+ u32 unused_3128; /* 0x3128 */
+ u32 ch0_rxdesc_tail_pointer; /* 0x312c */
+ u32 ch0_txdesc_ring_length; /* 0x3130 */
+ u32 ch0_rxdesc_ring_length; /* 0x3134 */
+ u32 unused_3138[(0x3160 - 0x3138) / 4]; /* 0x3138 */
+ u32 ch0_status; /* 0x3160 */
+};
+
+#define XGMAC_DMA_MODE_SWR BIT(0)
+#define XGMAC_DMA_SYSBUS_MODE_WR_OSR_LMT_SHIFT 24
+#define XGMAC_DMA_SYSBUS_MODE_WR_OSR_LMT_MASK GENMASK(4, 0)
+#define XGMAC_DMA_SYSBUS_MODE_RD_OSR_LMT_SHIFT 16
+#define XGMAC_DMA_SYSBUS_MODE_RD_OSR_LMT_MASK GENMASK(4, 0)
+#define XGMAC_DMA_SYSBUS_MODE_AAL BIT(12)
+#define XGMAC_DMA_SYSBUS_MODE_EAME BIT(11)
+#define XGMAC_DMA_SYSBUS_MODE_BLEN32 BIT(4)
+#define XGMAC_DMA_SYSBUS_MODE_BLEN16 BIT(3)
+#define XGMAC_DMA_SYSBUS_MODE_BLEN8 BIT(2)
+#define XGMAC_DMA_SYSBUS_MODE_BLEN4 BIT(1)
+#define XGMAC_DMA_SYSBUS_MODE_UNDEF BIT(0)
+
+#define XGMAC_DMA_CH0_CONTROL_DSL_SHIFT 18
+#define XGMAC_DMA_CH0_CONTROL_PBLX8 BIT(16)
+
+#define XGMAC_DMA_CH0_TX_CONTROL_TXPBL_SHIFT 16
+#define XGMAC_DMA_CH0_TX_CONTROL_TXPBL_MASK GENMASK(5, 0)
+#define XGMAC_DMA_CH0_TX_CONTROL_OSP BIT(4)
+#define XGMAC_DMA_CH0_TX_CONTROL_ST BIT(0)
+
+#define XGMAC_DMA_CH0_RX_CONTROL_RXPBL_SHIFT 16
+#define XGMAC_DMA_CH0_RX_CONTROL_RXPBL_MASK GENMASK(5, 0)
+#define XGMAC_DMA_CH0_RX_CONTROL_RBSZ_SHIFT 4
+#define XGMAC_DMA_CH0_RX_CONTROL_RBSZ_MASK GENMASK(10, 0)
+#define XGMAC_DMA_CH0_RX_CONTROL_SR BIT(0)
+
+/* Descriptors */
+#define XGMAC_DESCRIPTOR_WORDS 4
+#define XGMAC_DESCRIPTOR_SIZE (XGMAC_DESCRIPTOR_WORDS * 4)
+#define XGMAC_DESCRIPTORS_NUM 8
+#define XGMAC_DESCRIPTOR_ALIGN 64
+#define XGMAC_DESCRIPTORS_SIZE ALIGN(XGMAC_DESCRIPTORS_NUM * \
+ XGMAC_DESCRIPTOR_SIZE, XGMAC_DESCRIPTOR_ALIGN)
+#define XGMAC_BUFFER_ALIGN XGMAC_DESCRIPTOR_ALIGN
+#define XGMAC_MAX_PACKET_SIZE ALIGN(1568, XGMAC_DESCRIPTOR_ALIGN)
+#define XGMAC_RX_BUFFER_SIZE (XGMAC_DESCRIPTORS_NUM * XGMAC_MAX_PACKET_SIZE)
+
+#define XGMAC_RDES3_PKT_LENGTH_MASK GENMASK(13, 0)
+
+struct xgmac_desc {
+ u32 des0;
+ u32 des1;
+ u32 des2;
+ u32 des3;
+};
+
+#define XGMAC_DESC3_OWN BIT(31)
+#define XGMAC_DESC3_FD BIT(29)
+#define XGMAC_DESC3_LD BIT(28)
+
+#define XGMAC_AXI_WIDTH_32 4
+#define XGMAC_AXI_WIDTH_64 8
+#define XGMAC_AXI_WIDTH_128 16
+
+struct xgmac_config {
+ bool reg_access_always_ok;
+ int swr_wait;
+ int config_mac;
+ int config_mac_mdio;
+ unsigned int axi_bus_width;
+ phy_interface_t interface;
+ struct xgmac_ops *ops;
+};
+
+struct xgmac_ops {
+ int (*xgmac_probe_resources)(struct device *dev);
+ int (*xgmac_start_resets)(struct device *dev);
+ int (*xgmac_get_enetaddr)(struct device *dev);
+};
+
+struct xgmac_priv {
+ struct eth_device netdev;
+ struct device *dev;
+ const struct xgmac_config *config;
+ void __iomem *regs;
+ struct xgmac_mac_regs *mac_regs;
+ struct xgmac_mtl_regs *mtl_regs;
+ struct xgmac_dma_regs *dma_regs;
+ struct reset_control *rst;
+ struct reset_control *rst_ocp;
+ struct mii_bus miibus;
+ int phy_addr;
+ phy_interface_t interface;
+
+ u8 macaddr[6];
+
+ u32 reg_offset, reg_shift;
+ u32 max_speed;
+ struct xgmac_desc *tx_descs, *rx_descs;
+ dma_addr_t tx_descs_phys, rx_descs_phys;
+ dma_addr_t dma_rx_buf[XGMAC_DESCRIPTORS_NUM];
+ int tx_desc_idx, rx_desc_idx;
+ unsigned int desc_size;
+ unsigned int desc_per_cacheline;
+ void *rx_dma_buf;
+ bool started;
+ bool reg_access_ok;
+ bool clk_ck_enabled;
+};
+
+int xgmac_probe(struct device *dev);
+void xgmac_remove(struct device *dev);
+void xgmac_flush_desc_generic(void *desc);
+void xgmac_flush_buffer_generic(void *buf, size_t size);
+int xgmac_null_ops(struct device *dev);
+
+extern struct xgmac_config xgmac_socfpga_config;
diff --git a/drivers/net/designware_xgmac_socfpga.c b/drivers/net/designware_xgmac_socfpga.c
new file mode 100644
index 0000000000000000000000000000000000000000..7d8dba3c17cdb3fe7c82a6fa9315fecfdbfcc32a
--- /dev/null
+++ b/drivers/net/designware_xgmac_socfpga.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023, Intel Corporation
+ */
+#define DEBUG
+#include <common.h>
+#include <init.h>
+#include <errno.h>
+#include <malloc.h>
+#include <net.h>
+#include <linux/reset.h>
+#include <linux/phy.h>
+#include <mfd/syscon.h>
+#include <linux/clk.h>
+#include <mach/socfpga/soc64-system-manager.h>
+#include <mach/socfpga/secure_reg_helper.h>
+
+#include "designware_xgmac.h"
+
+#define SOCFPGA_XGMAC_SYSCON_ARG_COUNT 2
+
+static int dwxgmac_socfpga_do_setphy(struct device *dev, u32 modereg)
+{
+ struct xgmac_priv *xgmac = dev_get_priv(dev);
+ u32 modemask = SYSMGR_EMACGRP_CTRL_PHYSEL_MASK;
+ u32 index = (xgmac->reg_offset - SYSMGR_SOC64_EMAC0) >> 2;
+ u32 id = SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC0 + index;
+ int ret;
+
+ ret = socfpga_secure_reg_update32(id, modemask, modereg);
+ if (ret) {
+ dev_err(dev, "Failed to set PHY register via SMC call\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int xgmac_probe_resources_socfpga(struct device *dev)
+{
+ struct xgmac_priv *xgmac = dev_get_priv(dev);
+ phy_interface_t interface;
+ int ret;
+ u32 modereg;
+
+ interface = xgmac->interface;
+
+ switch (interface) {
+ case PHY_INTERFACE_MODE_MII:
+ case PHY_INTERFACE_MODE_GMII:
+ modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII;
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
+ break;
+ default:
+ dev_err(dev, "Unsupported PHY mode\n");
+ return -EINVAL;
+ }
+
+ /* Get PHY syscon */
+ ret = of_property_read_u32_index(dev->of_node, "altr,sysmgr-syscon",
+ 1, &xgmac->reg_offset);
+ if (ret) {
+ dev_err(dev, "Could not read reg_offset from sysmgr-syscon! Please update the devicetree.\n");
+
+ return -EINVAL;
+ }
+
+ ret = of_property_read_u32_index(dev->of_node, "altr,sysmgr-syscon",
+ 2, &xgmac->reg_shift);
+ if (ret) {
+ dev_err(dev, "Could not read reg_shift from sysmgr-syscon! Please update the devicetree.\n");
+ return -EINVAL;
+ }
+
+ xgmac->rst = reset_control_get(dev, "stmmaceth");
+ if (IS_ERR(xgmac->rst)) {
+ dev_err(dev, "Invalid reset line 'stmmaceth'.\n");
+ return PTR_ERR(xgmac->rst);
+ }
+ xgmac->rst_ocp = reset_control_get(dev, "stmmaceth-ocp");
+ if (IS_ERR(xgmac->rst_ocp)) {
+ dev_err(dev, "Invalid reset line 'stmmaceth-ocp'.\n");
+ return PTR_ERR(xgmac->rst_ocp);
+ }
+
+ reset_control_assert(xgmac->rst_ocp);
+ reset_control_assert(xgmac->rst);
+
+ ret = dwxgmac_socfpga_do_setphy(dev, modereg);
+ if (ret)
+ return ret;
+
+ reset_control_deassert(xgmac->rst_ocp);
+ reset_control_deassert(xgmac->rst);
+
+ return 0;
+}
+
+static int xgmac_get_enetaddr_socfpga(struct device *dev)
+{
+ return -ENOTSUPP;
+}
+
+static int xgmac_start_resets_socfpga(struct device *dev)
+{
+ struct xgmac_priv *xgmac = dev_get_priv(dev);
+
+ reset_control_assert(xgmac->rst);
+ reset_control_assert(xgmac->rst_ocp);
+
+ udelay(2);
+
+ reset_control_deassert(xgmac->rst);
+ reset_control_deassert(xgmac->rst_ocp);
+
+ return 0;
+}
+
+static struct xgmac_ops xgmac_socfpga_ops = {
+ .xgmac_probe_resources = xgmac_probe_resources_socfpga,
+ .xgmac_start_resets = xgmac_start_resets_socfpga,
+ .xgmac_get_enetaddr = xgmac_get_enetaddr_socfpga,
+};
+
+struct xgmac_config __maybe_unused xgmac_socfpga_config = {
+ .reg_access_always_ok = false,
+ .swr_wait = 50,
+ .config_mac = XGMAC_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
+ .config_mac_mdio = XGMAC_MAC_MDIO_ADDRESS_CR_350_400,
+ .axi_bus_width = XGMAC_AXI_WIDTH_64,
+ .ops = &xgmac_socfpga_ops
+};
+
+static __maybe_unused struct of_device_id xgmac_socfpga_compatible[] = {
+ {
+ .compatible = "intel,socfpga-dwxgmac",
+ .data = &xgmac_socfpga_config
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, xgmac_socfpga_compatible);
+
+static struct driver xgmac_socfpga_driver = {
+ .name = "designware-xgmac-socfpga",
+ .probe = xgmac_probe,
+ .remove = xgmac_remove,
+ .of_compatible = DRV_OF_COMPAT(xgmac_socfpga_compatible),
+};
+device_platform_driver(xgmac_socfpga_driver);
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 07/10] net: phy: add Analog Devices ADIN1300
2024-10-29 8:42 [PATCH 00/10] ARM: SoCFPGA: Add initial support for Agilex5 Steffen Trumtrar
` (5 preceding siblings ...)
2024-10-29 8:42 ` [PATCH 06/10] net: add support for Designware XGMAC (10gb) ethernet Steffen Trumtrar
@ 2024-10-29 8:42 ` Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 08/10] linux: clk: add clk_parent_data Steffen Trumtrar
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Steffen Trumtrar @ 2024-10-29 8:42 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
The Analog Devices ADIN1300 is a low power 10Mbps,100Mbps, and 1Gbps
ethernet phy.
(https://www.analog.com/media/en/technical-documentation/data-sheets/adin1300.pdf)
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
drivers/net/phy/Kconfig | 7 +
drivers/net/phy/Makefile | 1 +
drivers/net/phy/adin.c | 360 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 368 insertions(+)
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 8e12671801f39a4507937e16d2382e60c258990e..ac6fcf79027aa587b658d5f43cfbf7bb4f86f1f3 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -9,6 +9,13 @@ if PHYLIB
comment "MII PHY device drivers"
+config ADIN_PHY
+ bool "Driver for Analog Devices Industrial Ethernet PHYs"
+ help
+ Currently supports the:
+ - ADIN1300
+ Ethernet PHY
+
config AR8327N_PHY
bool "Driver for QCA AR8327N PHYs"
help
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index ce15e1bab79fb227f48dca5e9cdba2d0f7e92f7b..862a7e9ba1d19a12b272431c88d452e1434e757a 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-y += phy.o mdio_bus.o phy-core.o
+obj-$(CONFIG_ADIN_PHY) += adin.o
obj-$(CONFIG_AR8327N_PHY) += ar8327.o
obj-$(CONFIG_AT803X_PHY) += at803x.o
obj-$(CONFIG_DAVICOM_PHY) += davicom.o
diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
new file mode 100644
index 0000000000000000000000000000000000000000..413722d9297d28c50633c1f6c1892a055fb728f9
--- /dev/null
+++ b/drivers/net/phy/adin.c
@@ -0,0 +1,360 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for Analog Devices Industrial Ethernet PHYs
+ *
+ * Copyright 2019 Analog Devices Inc.
+ */
+#include <common.h>
+#include <init.h>
+#include <linux/bitfield.h>
+#include <linux/mdio.h>
+#include <linux/phy.h>
+#include <linux/string.h>
+
+#define PHY_ID_ADIN1200 0x0283bc20
+#define PHY_ID_ADIN1300 0x0283bc30
+
+#define ADIN1300_MII_EXT_REG_PTR 0x0010
+#define ADIN1300_MII_EXT_REG_DATA 0x0011
+
+#define ADIN1300_PHY_CTRL1 0x0012
+#define ADIN1300_AUTO_MDI_EN BIT(10)
+#define ADIN1300_MAN_MDIX_EN BIT(9)
+#define ADIN1300_DIAG_CLK_EN BIT(2)
+
+#define ADIN1300_RX_ERR_CNT 0x0014
+
+#define ADIN1300_PHY_CTRL_STATUS2 0x0015
+#define ADIN1300_NRG_PD_EN BIT(3)
+#define ADIN1300_NRG_PD_TX_EN BIT(2)
+#define ADIN1300_NRG_PD_STATUS BIT(1)
+
+#define ADIN1300_PHY_CTRL2 0x0016
+#define ADIN1300_DOWNSPEED_AN_100_EN BIT(11)
+#define ADIN1300_DOWNSPEED_AN_10_EN BIT(10)
+#define ADIN1300_GROUP_MDIO_EN BIT(6)
+#define ADIN1300_DOWNSPEEDS_EN \
+ (ADIN1300_DOWNSPEED_AN_100_EN | ADIN1300_DOWNSPEED_AN_10_EN)
+
+#define ADIN1300_PHY_CTRL3 0x0017
+#define ADIN1300_LINKING_EN BIT(13)
+#define ADIN1300_DOWNSPEED_RETRIES_MSK GENMASK(12, 10)
+
+#define ADIN1300_INT_MASK_REG 0x0018
+#define ADIN1300_INT_MDIO_SYNC_EN BIT(9)
+#define ADIN1300_INT_ANEG_STAT_CHNG_EN BIT(8)
+#define ADIN1300_INT_ANEG_PAGE_RX_EN BIT(6)
+#define ADIN1300_INT_IDLE_ERR_CNT_EN BIT(5)
+#define ADIN1300_INT_MAC_FIFO_OU_EN BIT(4)
+#define ADIN1300_INT_RX_STAT_CHNG_EN BIT(3)
+#define ADIN1300_INT_LINK_STAT_CHNG_EN BIT(2)
+#define ADIN1300_INT_SPEED_CHNG_EN BIT(1)
+#define ADIN1300_INT_HW_IRQ_EN BIT(0)
+#define ADIN1300_INT_MASK_EN \
+ (ADIN1300_INT_LINK_STAT_CHNG_EN | ADIN1300_INT_HW_IRQ_EN)
+#define ADIN1300_INT_STATUS_REG 0x0019
+
+#define ADIN1300_PHY_STATUS1 0x001a
+#define ADIN1300_PAIR_01_SWAP BIT(11)
+
+/* EEE register addresses, accessible via Clause 22 access using
+ * ADIN1300_MII_EXT_REG_PTR & ADIN1300_MII_EXT_REG_DATA.
+ * The bit-fields are the same as specified by IEEE for EEE.
+ */
+#define ADIN1300_EEE_CAP_REG 0x8000
+#define ADIN1300_EEE_ADV_REG 0x8001
+#define ADIN1300_EEE_LPABLE_REG 0x8002
+#define ADIN1300_CLOCK_STOP_REG 0x9400
+#define ADIN1300_LPI_WAKE_ERR_CNT_REG 0xa000
+
+#define ADIN1300_CDIAG_RUN 0xba1b
+#define ADIN1300_CDIAG_RUN_EN BIT(0)
+
+/*
+ * The XSIM3/2/1 and XSHRT3/2/1 are actually relative.
+ * For CDIAG_DTLD_RSLTS(0) it's ADIN1300_CDIAG_RSLT_XSIM3/2/1
+ * For CDIAG_DTLD_RSLTS(1) it's ADIN1300_CDIAG_RSLT_XSIM3/2/0
+ * For CDIAG_DTLD_RSLTS(2) it's ADIN1300_CDIAG_RSLT_XSIM3/1/0
+ * For CDIAG_DTLD_RSLTS(3) it's ADIN1300_CDIAG_RSLT_XSIM2/1/0
+ */
+#define ADIN1300_CDIAG_DTLD_RSLTS(x) (0xba1d + (x))
+#define ADIN1300_CDIAG_RSLT_BUSY BIT(10)
+#define ADIN1300_CDIAG_RSLT_XSIM3 BIT(9)
+#define ADIN1300_CDIAG_RSLT_XSIM2 BIT(8)
+#define ADIN1300_CDIAG_RSLT_XSIM1 BIT(7)
+#define ADIN1300_CDIAG_RSLT_SIM BIT(6)
+#define ADIN1300_CDIAG_RSLT_XSHRT3 BIT(5)
+#define ADIN1300_CDIAG_RSLT_XSHRT2 BIT(4)
+#define ADIN1300_CDIAG_RSLT_XSHRT1 BIT(3)
+#define ADIN1300_CDIAG_RSLT_SHRT BIT(2)
+#define ADIN1300_CDIAG_RSLT_OPEN BIT(1)
+#define ADIN1300_CDIAG_RSLT_GOOD BIT(0)
+
+#define ADIN1300_CDIAG_FLT_DIST(x) (0xba21 + (x))
+
+#define ADIN1300_GE_SOFT_RESET_REG 0xff0c
+#define ADIN1300_GE_SOFT_RESET BIT(0)
+
+#define ADIN1300_GE_CLK_CFG_REG 0xff1f
+#define ADIN1300_GE_CLK_CFG_MASK GENMASK(5, 0)
+#define ADIN1300_GE_CLK_CFG_RCVR_125 BIT(5)
+#define ADIN1300_GE_CLK_CFG_FREE_125 BIT(4)
+#define ADIN1300_GE_CLK_CFG_REF_EN BIT(3)
+#define ADIN1300_GE_CLK_CFG_HRT_RCVR BIT(2)
+#define ADIN1300_GE_CLK_CFG_HRT_FREE BIT(1)
+#define ADIN1300_GE_CLK_CFG_25 BIT(0)
+
+#define ADIN1300_GE_RGMII_CFG_REG 0xff23
+#define ADIN1300_GE_RGMII_RX_MSK GENMASK(8, 6)
+#define ADIN1300_GE_RGMII_RX_SEL(x) \
+ FIELD_PREP(ADIN1300_GE_RGMII_RX_MSK, x)
+#define ADIN1300_GE_RGMII_GTX_MSK GENMASK(5, 3)
+#define ADIN1300_GE_RGMII_GTX_SEL(x) \
+ FIELD_PREP(ADIN1300_GE_RGMII_GTX_MSK, x)
+#define ADIN1300_GE_RGMII_RXID_EN BIT(2)
+#define ADIN1300_GE_RGMII_TXID_EN BIT(1)
+#define ADIN1300_GE_RGMII_EN BIT(0)
+
+/* RGMII internal delay settings for rx and tx for ADIN1300 */
+#define ADIN1300_RGMII_1_60_NS 0x0001
+#define ADIN1300_RGMII_1_80_NS 0x0002
+#define ADIN1300_RGMII_2_00_NS 0x0000
+#define ADIN1300_RGMII_2_20_NS 0x0006
+#define ADIN1300_RGMII_2_40_NS 0x0007
+
+#define ADIN1300_GE_RMII_CFG_REG 0xff24
+#define ADIN1300_GE_RMII_FIFO_DEPTH_MSK GENMASK(6, 4)
+#define ADIN1300_GE_RMII_FIFO_DEPTH_SEL(x) \
+ FIELD_PREP(ADIN1300_GE_RMII_FIFO_DEPTH_MSK, x)
+#define ADIN1300_GE_RMII_EN BIT(0)
+
+/* RMII fifo depth values */
+#define ADIN1300_RMII_4_BITS 0x0000
+#define ADIN1300_RMII_8_BITS 0x0001
+#define ADIN1300_RMII_12_BITS 0x0002
+#define ADIN1300_RMII_16_BITS 0x0003
+#define ADIN1300_RMII_20_BITS 0x0004
+#define ADIN1300_RMII_24_BITS 0x0005
+
+/**
+ * struct adin_cfg_reg_map - map a config value to aregister value
+ * @cfg: value in device configuration
+ * @reg: value in the register
+ */
+struct adin_cfg_reg_map {
+ int cfg;
+ int reg;
+};
+
+static const struct adin_cfg_reg_map adin_rgmii_delays[] = {
+ { 1600, ADIN1300_RGMII_1_60_NS },
+ { 1800, ADIN1300_RGMII_1_80_NS },
+ { 2000, ADIN1300_RGMII_2_00_NS },
+ { 2200, ADIN1300_RGMII_2_20_NS },
+ { 2400, ADIN1300_RGMII_2_40_NS },
+ { },
+};
+
+static const struct adin_cfg_reg_map adin_rmii_fifo_depths[] = {
+ { 4, ADIN1300_RMII_4_BITS },
+ { 8, ADIN1300_RMII_8_BITS },
+ { 12, ADIN1300_RMII_12_BITS },
+ { 16, ADIN1300_RMII_16_BITS },
+ { 20, ADIN1300_RMII_20_BITS },
+ { 24, ADIN1300_RMII_24_BITS },
+ { },
+};
+
+static int adin_lookup_reg_value(const struct adin_cfg_reg_map *tbl, int cfg)
+{
+ size_t i;
+
+ for (i = 0; tbl[i].cfg; i++) {
+ if (tbl[i].cfg == cfg)
+ return tbl[i].reg;
+ }
+
+ return -EINVAL;
+}
+
+static u32 adin_get_reg_value(struct phy_device *phydev,
+ const char *prop_name,
+ const struct adin_cfg_reg_map *tbl,
+ u32 dflt)
+{
+ struct device *dev = &phydev->bus->dev;
+ u32 val;
+ int rc;
+
+ if (of_property_read_u32(dev->of_node, prop_name, &val))
+ return dflt;
+
+ rc = adin_lookup_reg_value(tbl, val);
+ if (rc < 0) {
+ phydev_warn(phydev,
+ "Unsupported value %u for %s using default (%u)\n",
+ val, prop_name, dflt);
+ return dflt;
+ }
+
+ return rc;
+}
+
+static u16 adin_ext_read(struct phy_device *phydev, const u32 regnum)
+{
+ u16 val;
+
+ phy_write(phydev, ADIN1300_MII_EXT_REG_PTR, regnum);
+ val = phy_read(phydev, ADIN1300_MII_EXT_REG_DATA);
+
+ debug("%s: adin@0x%x 0x%x=0x%x\n", __func__, phydev->addr, regnum, val);
+
+ return val;
+}
+
+static int adin_ext_write(struct phy_device *phydev, const u32 regnum, const u16 val)
+{
+ debug("%s: adin@0x%x 0x%x=0x%x\n", __func__, phydev->addr, regnum, val);
+
+ phy_write(phydev, ADIN1300_MII_EXT_REG_PTR, regnum);
+
+ return phy_write(phydev, ADIN1300_MII_EXT_REG_DATA, val);
+}
+
+static int adin_config_rgmii_mode(struct phy_device *phydev)
+{
+ u32 val;
+ int reg;
+
+ if (!phy_interface_is_rgmii(phydev))
+ return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ ADIN1300_GE_RGMII_CFG_REG,
+ ADIN1300_GE_RGMII_EN);
+
+ reg = adin_ext_read(phydev, ADIN1300_GE_RGMII_CFG_REG);
+ if (reg < 0)
+ return reg;
+
+ reg |= ADIN1300_GE_RGMII_EN;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
+ reg |= ADIN1300_GE_RGMII_RXID_EN;
+
+ val = adin_get_reg_value(phydev, "adi,rx-internal-delay-ps",
+ adin_rgmii_delays,
+ ADIN1300_RGMII_2_00_NS);
+ reg &= ~ADIN1300_GE_RGMII_RX_MSK;
+ reg |= ADIN1300_GE_RGMII_RX_SEL(val);
+ } else {
+ reg &= ~ADIN1300_GE_RGMII_RXID_EN;
+ }
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
+ reg |= ADIN1300_GE_RGMII_TXID_EN;
+
+ val = adin_get_reg_value(phydev, "adi,tx-internal-delay-ps",
+ adin_rgmii_delays,
+ ADIN1300_RGMII_2_00_NS);
+ reg &= ~ADIN1300_GE_RGMII_GTX_MSK;
+ reg |= ADIN1300_GE_RGMII_GTX_SEL(val);
+ } else {
+ reg &= ~ADIN1300_GE_RGMII_TXID_EN;
+ }
+
+ return adin_ext_write(phydev, ADIN1300_GE_RGMII_CFG_REG, reg);
+}
+
+static int adin_config_rmii_mode(struct phy_device *phydev)
+{
+ u32 val;
+ int reg;
+
+ if (phydev->interface != PHY_INTERFACE_MODE_RMII)
+ return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ ADIN1300_GE_RMII_CFG_REG,
+ ADIN1300_GE_RMII_EN);
+
+ reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_GE_RMII_CFG_REG);
+ if (reg < 0)
+ return reg;
+
+ reg |= ADIN1300_GE_RMII_EN;
+
+ val = adin_get_reg_value(phydev, "adi,fifo-depth-bits",
+ adin_rmii_fifo_depths,
+ ADIN1300_RMII_8_BITS);
+
+ reg &= ~ADIN1300_GE_RMII_FIFO_DEPTH_MSK;
+ reg |= ADIN1300_GE_RMII_FIFO_DEPTH_SEL(val);
+
+ return phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ ADIN1300_GE_RMII_CFG_REG, reg);
+}
+
+static int adin_config_init(struct phy_device *phydev)
+{
+ int rc;
+
+ rc = adin_config_rgmii_mode(phydev);
+ if (rc < 0)
+ return rc;
+
+ rc = adin_config_rmii_mode(phydev);
+ if (rc < 0)
+ return rc;
+
+ return genphy_config_init(phydev);
+}
+
+static int adin_soft_reset(struct phy_device *phydev)
+{
+ int rc;
+
+ /* Read link and autonegotiation status */
+ /* The reset bit is self-clearing, set it and wait */
+ rc = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ ADIN1300_GE_SOFT_RESET_REG,
+ ADIN1300_GE_SOFT_RESET);
+ if (rc < 0)
+ return rc;
+
+ mdelay(20);
+
+ /* If we get a read error something may be wrong */
+ rc = phy_read_mmd(phydev, MDIO_MMD_VEND1,
+ ADIN1300_GE_SOFT_RESET_REG);
+
+ return rc < 0 ? rc : 0;
+}
+
+static int adin_config_aneg(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = genphy_config_aneg(phydev);
+ if (ret < 0)
+ return ret;
+
+ /* Enable Autonegotiation */
+ phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
+ phydev->autoneg = AUTONEG_ENABLE;
+
+ return 0;
+}
+
+static struct phy_driver adin_driver[] = {
+ {
+ .phy_id = 0x0283bc30,
+ .phy_id_mask = 0xffffffff,
+ .drv.name = "ADIN1300",
+ .features = PHY_GBIT_FEATURES,
+ .config_init = adin_config_init,
+ .soft_reset = adin_soft_reset,
+ .config_aneg = adin_config_aneg,
+ .read_status = genphy_read_status,
+ },
+};
+
+device_phy_drivers(adin_driver);
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 08/10] linux: clk: add clk_parent_data
2024-10-29 8:42 [PATCH 00/10] ARM: SoCFPGA: Add initial support for Agilex5 Steffen Trumtrar
` (6 preceding siblings ...)
2024-10-29 8:42 ` [PATCH 07/10] net: phy: add Analog Devices ADIN1300 Steffen Trumtrar
@ 2024-10-29 8:42 ` Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 09/10] clk: support init->parent_data Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 10/10] clk: socfpga: add agilex5 clock support Steffen Trumtrar
9 siblings, 0 replies; 11+ messages in thread
From: Steffen Trumtrar @ 2024-10-29 8:42 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
Some linux clock drivers use the clk_parent_data struct.
Import it from linux to make driver porting easier.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
include/linux/clk.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/include/linux/clk.h b/include/linux/clk.h
index ae03dcfdb2a27266188bdec99da74f861c8b8846..b7a7b8138a555c0508821d313ade153cd720195e 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -333,6 +333,20 @@ struct clk_ops {
int (*get_phase)(struct clk_hw *hw);
};
+/**
+ * struct clk_parent_data - clk parent information
+ * @hw: parent clk_hw pointer (used for clk providers with internal clks)
+ * @fw_name: parent name local to provider registering clk
+ * @name: globally unique parent name (used as a fallback)
+ * @index: parent index local to provider registering clk (if @fw_name absent)
+ */
+struct clk_parent_data {
+ const struct clk_hw *hw;
+ const char *fw_name;
+ const char *name;
+ int index;
+};
+
/**
* struct clk_init_data - holds init data that's common to all clocks and is
* shared between the clock provider and the common clock framework.
@@ -349,6 +363,7 @@ struct clk_init_data {
const char *name;
const struct clk_ops *ops;
const char * const *parent_names;
+ const struct clk_parent_data *parent_data;
const struct clk_hw **parent_hws;
unsigned int num_parents;
unsigned long flags;
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 09/10] clk: support init->parent_data
2024-10-29 8:42 [PATCH 00/10] ARM: SoCFPGA: Add initial support for Agilex5 Steffen Trumtrar
` (7 preceding siblings ...)
2024-10-29 8:42 ` [PATCH 08/10] linux: clk: add clk_parent_data Steffen Trumtrar
@ 2024-10-29 8:42 ` Steffen Trumtrar
2024-10-29 8:42 ` [PATCH 10/10] clk: socfpga: add agilex5 clock support Steffen Trumtrar
9 siblings, 0 replies; 11+ messages in thread
From: Steffen Trumtrar @ 2024-10-29 8:42 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
Linux clk driver supports matching parents via init->parent_data instead
of init->parent_names.
Add support for this feature to barebox, too.
Linux however supports setting a "name" and "fw_name" for a parent
clock. "fw_name" is a local name for the provider registering the clock
and "name" is a globally unique parent name. For the time being, only
support the globally unique "name" field.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
drivers/clk/clk.c | 48 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 40 insertions(+), 8 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bd368782804c9a2cce1ced7826501363c0c2ab2d..be4060e6d5a0d7ecbed729b4d96570d7980f5857 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -476,11 +476,28 @@ int bclk_register(struct clk *clk)
return ret;
}
+static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist)
+{
+ const char *dst;
+
+ if (!src) {
+ if (must_exist)
+ return -EINVAL;
+ return 0;
+ }
+
+ *dst_p = dst = xstrdup(src);
+ if (!dst)
+ return -ENOMEM;
+
+ return 0;
+}
+
struct clk *clk_register(struct device *dev, struct clk_hw *hw)
{
struct clk *clk;
const struct clk_init_data *init = hw->init;
- char **parent_names = NULL;
+ const char **parent_names = NULL;
int i, ret;
if (!hw->init)
@@ -496,14 +513,29 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
clk->parents = xzalloc(sizeof(struct clk *) * clk->num_parents);
- if (init->parent_names) {
+ if (init->parent_names || init->parent_data) {
parent_names = xzalloc(init->num_parents * sizeof(char *));
- for (i = 0; i < init->num_parents; i++)
- parent_names[i] = xstrdup(init->parent_names[i]);
-
- clk->parent_names = (const char *const*)parent_names;
-
+ for (i = 0; i < init->num_parents; i++) {
+ if (init->parent_names) {
+ ret = clk_cpy_name(&parent_names[i],
+ init->parent_names[i], true);
+ } else if (init->parent_data) {
+ /* Linux copies fw_name and if successful also name.
+ * As fw_name is not handled in barebox, just copy the
+ * name field and fallback to hw->clk.name if it doesn't
+ * exist.
+ */
+ ret = clk_cpy_name(&parent_names[i],
+ init->parent_data[i].name,
+ true);
+ if (ret)
+ ret = clk_cpy_name(&parent_names[i],
+ init->parent_data[i].hw->clk.name,
+ false);
+ }
+ }
+ clk->parent_names = (const char *const *)parent_names;
} else {
for (i = 0; i < init->num_parents; i++)
clk->parents[i] = clk_hw_to_clk(init->parent_hws[i]);
@@ -515,7 +547,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
if (ret) {
if (parent_names) {
for (i = 0; i < init->num_parents; i++)
- free(parent_names[i]);
+ free(&parent_names[i]);
free(parent_names);
}
free(clk->parents);
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 10/10] clk: socfpga: add agilex5 clock support
2024-10-29 8:42 [PATCH 00/10] ARM: SoCFPGA: Add initial support for Agilex5 Steffen Trumtrar
` (8 preceding siblings ...)
2024-10-29 8:42 ` [PATCH 09/10] clk: support init->parent_data Steffen Trumtrar
@ 2024-10-29 8:42 ` Steffen Trumtrar
9 siblings, 0 replies; 11+ messages in thread
From: Steffen Trumtrar @ 2024-10-29 8:42 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
Add support for the Stratix10 and Agilex5 pll,gate and periph clocks.
Only tested on Agilex5.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
drivers/clk/socfpga/Makefile | 4 +-
drivers/clk/socfpga/clk-agilex5.c | 834 ++++++++++++++++++++++++++++++
drivers/clk/socfpga/clk-gate-s10.c | 184 +++++++
drivers/clk/socfpga/clk-periph-s10.c | 163 ++++++
drivers/clk/socfpga/clk-pll-s10.c | 140 +++++
drivers/clk/socfpga/clk.h | 9 +
drivers/clk/socfpga/stratix10-clk.h | 73 +++
include/dt-bindings/clock/agilex5-clock.h | 135 +++--
8 files changed, 1488 insertions(+), 54 deletions(-)
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
index 0a195cbf3f8efe2828cc2eade549d550001f0ca1..bd6f2266fc6847d3201d3fcb536e8061816ac8e3 100644
--- a/drivers/clk/socfpga/Makefile
+++ b/drivers/clk/socfpga/Makefile
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-y += clk.o
+obj-$(CONFIG_ARCH_SOCFPGA_CYCLONE5) += clk.o
+obj-$(CONFIG_ARCH_SOCFPGA_ARRIA10) += clk.o
obj-$(CONFIG_ARCH_SOCFPGA_ARRIA10) += clk-gate-a10.o clk-periph-a10.o clk-pll-a10.o
+obj-$(CONFIG_ARCH_SOCFPGA_AGILEX5) += clk-agilex5.o clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o
diff --git a/drivers/clk/socfpga/clk-agilex5.c b/drivers/clk/socfpga/clk-agilex5.c
new file mode 100644
index 0000000000000000000000000000000000000000..b6452b960b4fb0a03901c79617e9375185426cf9
--- /dev/null
+++ b/drivers/clk/socfpga/clk-agilex5.c
@@ -0,0 +1,834 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022, Intel Corporation
+ */
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+
+#include <dt-bindings/clock/agilex5-clock.h>
+
+#include "stratix10-clk.h"
+
+static const struct clk_parent_data pll_mux[] = {
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data boot_mux[] = {
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+};
+
+static const struct clk_parent_data core0_free_mux[] = {
+ {
+ .fw_name = "main_pll_c1",
+ .name = "main_pll_c1",
+ },
+ {
+ .fw_name = "peri_pll_c0",
+ .name = "peri_pll_c0",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data core1_free_mux[] = {
+ {
+ .fw_name = "main_pll_c1",
+ .name = "main_pll_c1",
+ },
+ {
+ .fw_name = "peri_pll_c0",
+ .name = "peri_pll_c0",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data core2_free_mux[] = {
+ {
+ .fw_name = "main_pll_c0",
+ .name = "main_pll_c0",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data core3_free_mux[] = {
+ {
+ .fw_name = "main_pll_c0",
+ .name = "main_pll_c0",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data dsu_free_mux[] = {
+ {
+ .fw_name = "main_pll_c2",
+ .name = "main_pll_c2",
+ },
+ {
+ .fw_name = "peri_pll_c0",
+ .name = "peri_pll_c0",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data noc_free_mux[] = {
+ {
+ .fw_name = "main_pll_c3",
+ .name = "main_pll_c3",
+ },
+ {
+ .fw_name = "peri_pll_c1",
+ .name = "peri_pll_c1",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data emaca_free_mux[] = {
+ {
+ .fw_name = "main_pll_c1",
+ .name = "main_pll_c1",
+ },
+ {
+ .fw_name = "peri_pll_c3",
+ .name = "peri_pll_c3",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data emacb_free_mux[] = {
+ {
+ .fw_name = "main_pll_c1",
+ .name = "main_pll_c1",
+ },
+ {
+ .fw_name = "peri_pll_c3",
+ .name = "peri_pll_c3",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data emac_ptp_free_mux[] = {
+ {
+ .fw_name = "main_pll_c3",
+ .name = "main_pll_c3",
+ },
+ {
+ .fw_name = "peri_pll_c3",
+ .name = "peri_pll_c3",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data gpio_db_free_mux[] = {
+ {
+ .fw_name = "main_pll_c3",
+ .name = "main_pll_c3",
+ },
+ {
+ .fw_name = "peri_pll_c1",
+ .name = "peri_pll_c1",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data psi_ref_free_mux[] = {
+ {
+ .fw_name = "main_pll_c1",
+ .name = "main_pll_c1",
+ },
+ {
+ .fw_name = "peri_pll_c3",
+ .name = "peri_pll_c3",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data usb31_free_mux[] = {
+ {
+ .fw_name = "main_pll_c3",
+ .name = "main_pll_c3",
+ },
+ {
+ .fw_name = "peri_pll_c2",
+ .name = "peri_pll_c2",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data s2f_usr0_free_mux[] = {
+ {
+ .fw_name = "main_pll_c1",
+ .name = "main_pll_c1",
+ },
+ {
+ .fw_name = "peri_pll_c3",
+ .name = "peri_pll_c3",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data s2f_usr1_free_mux[] = {
+ {
+ .fw_name = "main_pll_c1",
+ .name = "main_pll_c1",
+ },
+ {
+ .fw_name = "peri_pll_c3",
+ .name = "peri_pll_c3",
+ },
+ {
+ .fw_name = "osc1",
+ .name = "osc1",
+ },
+ {
+ .fw_name = "cb-intosc-hs-div2-clk",
+ .name = "cb-intosc-hs-div2-clk",
+ },
+ {
+ .fw_name = "f2s-free-clk",
+ .name = "f2s-free-clk",
+ },
+};
+
+static const struct clk_parent_data core0_mux[] = {
+ {
+ .fw_name = "core0_free_clk",
+ .name = "core0_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data core1_mux[] = {
+ {
+ .fw_name = "core1_free_clk",
+ .name = "core1_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data core2_mux[] = {
+ {
+ .fw_name = "core2_free_clk",
+ .name = "core2_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data core3_mux[] = {
+ {
+ .fw_name = "core3_free_clk",
+ .name = "core3_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data dsu_mux[] = {
+ {
+ .fw_name = "dsu_free_clk",
+ .name = "dsu_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data emac_mux[] = {
+ {
+ .fw_name = "emaca_free_clk",
+ .name = "emaca_free_clk",
+ },
+ {
+ .fw_name = "emacb_free_clk",
+ .name = "emacb_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data noc_mux[] = {
+ {
+ .fw_name = "noc_free_clk",
+ .name = "noc_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data s2f_user0_mux[] = {
+ {
+ .fw_name = "s2f_user0_free_clk",
+ .name = "s2f_user0_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data s2f_user1_mux[] = {
+ {
+ .fw_name = "s2f_user1_free_clk",
+ .name = "s2f_user1_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data psi_mux[] = {
+ {
+ .fw_name = "psi_ref_free_clk",
+ .name = "psi_ref_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data gpio_db_mux[] = {
+ {
+ .fw_name = "gpio_db_free_clk",
+ .name = "gpio_db_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data emac_ptp_mux[] = {
+ {
+ .fw_name = "emac_ptp_free_clk",
+ .name = "emac_ptp_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+static const struct clk_parent_data usb31_mux[] = {
+ {
+ .fw_name = "usb31_free_clk",
+ .name = "usb31_free_clk",
+ },
+ {
+ .fw_name = "boot_clk",
+ .name = "boot_clk",
+ },
+};
+
+/*
+ * TODO - Clocks in AO (always on) controller
+ * 2 main PLLs only
+ */
+static const struct stratix10_pll_clock agilex5_pll_clks[] = {
+ { AGILEX5_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
+ 0x0 },
+ { AGILEX5_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux), 0,
+ 0x48 },
+ { AGILEX5_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux), 0,
+ 0x9C },
+};
+
+static const struct stratix10_perip_c_clock agilex5_main_perip_c_clks[] = {
+ { AGILEX5_MAIN_PLL_C0_CLK, "main_pll_c0", "main_pll", NULL, 1, 0,
+ 0x5C },
+ { AGILEX5_MAIN_PLL_C1_CLK, "main_pll_c1", "main_pll", NULL, 1, 0,
+ 0x60 },
+ { AGILEX5_MAIN_PLL_C2_CLK, "main_pll_c2", "main_pll", NULL, 1, 0,
+ 0x64 },
+ { AGILEX5_MAIN_PLL_C3_CLK, "main_pll_c3", "main_pll", NULL, 1, 0,
+ 0x68 },
+ { AGILEX5_PERIPH_PLL_C0_CLK, "peri_pll_c0", "periph_pll", NULL, 1, 0,
+ 0xB0 },
+ { AGILEX5_PERIPH_PLL_C1_CLK, "peri_pll_c1", "periph_pll", NULL, 1, 0,
+ 0xB4 },
+ { AGILEX5_PERIPH_PLL_C2_CLK, "peri_pll_c2", "periph_pll", NULL, 1, 0,
+ 0xB8 },
+ { AGILEX5_PERIPH_PLL_C3_CLK, "peri_pll_c3", "periph_pll", NULL, 1, 0,
+ 0xBC },
+};
+
+/* Non-SW clock-gated enabled clocks */
+static const struct stratix10_perip_cnt_clock agilex5_main_perip_cnt_clks[] = {
+ { AGILEX5_CORE0_FREE_CLK, "core0_free_clk", NULL, core0_free_mux,
+ ARRAY_SIZE(core0_free_mux), 0, 0x0104, 0, 0, 0},
+ { AGILEX5_CORE1_FREE_CLK, "core1_free_clk", NULL, core1_free_mux,
+ ARRAY_SIZE(core1_free_mux), 0, 0x0104, 0, 0, 0},
+ { AGILEX5_CORE2_FREE_CLK, "core2_free_clk", NULL, core2_free_mux,
+ ARRAY_SIZE(core2_free_mux), 0, 0x010C, 0, 0, 0},
+ { AGILEX5_CORE3_FREE_CLK, "core3_free_clk", NULL, core3_free_mux,
+ ARRAY_SIZE(core3_free_mux), 0, 0x0110, 0, 0, 0},
+ { AGILEX5_DSU_FREE_CLK, "dsu_free_clk", NULL, dsu_free_mux,
+ ARRAY_SIZE(dsu_free_mux), 0, 0x0100, 0, 0, 0},
+ { AGILEX5_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux,
+ ARRAY_SIZE(noc_free_mux), 0, 0x40, 0, 0, 0 },
+ { AGILEX5_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux,
+ ARRAY_SIZE(emaca_free_mux), 0, 0xD4, 0, 0x88, 0 },
+ { AGILEX5_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux,
+ ARRAY_SIZE(emacb_free_mux), 0, 0xD8, 0, 0x88, 1 },
+ { AGILEX5_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL,
+ emac_ptp_free_mux, ARRAY_SIZE(emac_ptp_free_mux), 0, 0xDC, 0, 0x88,
+ 2 },
+ { AGILEX5_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
+ ARRAY_SIZE(gpio_db_free_mux), 0, 0xE0, 0, 0x88, 3 },
+ { AGILEX5_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", NULL,
+ s2f_usr0_free_mux, ARRAY_SIZE(s2f_usr0_free_mux), 0, 0xE8, 0, 0x30,
+ 2 },
+ { AGILEX5_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL,
+ s2f_usr1_free_mux, ARRAY_SIZE(s2f_usr1_free_mux), 0, 0xEC, 0, 0x88,
+ 5 },
+ { AGILEX5_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux,
+ ARRAY_SIZE(psi_ref_free_mux), 0, 0xF0, 0, 0x88, 6 },
+ { AGILEX5_USB31_FREE_CLK, "usb31_free_clk", NULL, usb31_free_mux,
+ ARRAY_SIZE(usb31_free_mux), 0, 0xF8, 0, 0x88, 7},
+};
+
+/* SW Clock gate enabled clocks */
+static const struct stratix10_gate_clock agilex5_gate_clks[] = {
+
+ /* TODO HW Managed Clocks list */
+
+ /* TODO SW Managed Clocks list */
+
+ /* Main PLL0 Begin */
+ /* MPU clocks */
+ { AGILEX5_CORE0_CLK, "core0_clk", NULL, core0_mux,
+ ARRAY_SIZE(core0_mux), 0, 0x24, 8, 0, 0, 0, 0x30, 5, 0 },
+ { AGILEX5_CORE1_CLK, "core1_clk", NULL, core1_mux,
+ ARRAY_SIZE(core1_mux), 0, 0x24, 9, 0, 0, 0, 0x30, 5, 0 },
+ { AGILEX5_CORE2_CLK, "core2_clk", NULL, core2_mux,
+ ARRAY_SIZE(core2_mux), 0, 0x24, 10, 0, 0, 0, 0x30, 6, 0 },
+ { AGILEX5_CORE3_CLK, "core3_clk", NULL, core3_mux,
+ ARRAY_SIZE(core3_mux), 0, 0x24, 11, 0, 0, 0, 0x30, 7, 0 },
+ { AGILEX5_MPU_CLK, "dsu_clk", NULL, dsu_mux, ARRAY_SIZE(dsu_mux), 0, 0,
+ 0, 0, 0, 0, 0x34, 4, 0 },
+ { AGILEX5_MPU_PERIPH_CLK, "mpu_periph_clk", NULL, dsu_mux,
+ ARRAY_SIZE(dsu_mux), 0, 0, 0, 0x44, 20, 2, 0x34, 4, 0 },
+ { AGILEX5_MPU_CCU_CLK, "mpu_ccu_clk", NULL, dsu_mux,
+ ARRAY_SIZE(dsu_mux), 0, 0, 0, 0x44, 18, 2, 0x34, 4, 0 },
+
+ /* ANGTS TODO l4 main clk has no divider now. To check. */
+ { AGILEX5_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux,
+ ARRAY_SIZE(noc_mux), 0, 0x24, 1, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0,
+ 0x24, 2, 0x44, 4, 2, 0x30, 1, 0 },
+ { AGILEX5_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux,
+ ARRAY_SIZE(noc_mux), 0, 0, 0, 0x44, 2, 2, 0x30, 1, 0 },
+ { AGILEX5_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
+ CLK_IS_CRITICAL, 0x24, 3, 0x44, 6, 2, 0x30, 1, 0 },
+
+ /* Core sight clocks*/
+ { AGILEX5_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0,
+ 0x24, 4, 0x44, 24, 2, 0x30, 1, 0 },
+ { AGILEX5_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux,
+ ARRAY_SIZE(noc_mux), 0, 0x24, 4, 0x44, 26, 2, 0x30, 1, 0 },
+ { AGILEX5_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x24, 4,
+ 0x44, 28, 1, 0, 0, 0 },
+ /* Main PLL0 End */
+
+ /* Main Peripheral PLL1 Begin */
+ { AGILEX5_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux),
+ 0, 0x7C, 0, 0, 0, 0, 0x94, 26, 0 },
+ { AGILEX5_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux),
+ 0, 0x7C, 1, 0, 0, 0, 0x94, 27, 0 },
+ { AGILEX5_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux),
+ 0, 0x7C, 2, 0, 0, 0, 0x94, 28, 0 },
+ { AGILEX5_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux,
+ ARRAY_SIZE(emac_ptp_mux), 0, 0x7C, 3, 0, 0, 0, 0x88, 2, 0 },
+ { AGILEX5_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux,
+ ARRAY_SIZE(gpio_db_mux), 0, 0x7C, 4, 0x98, 0, 16, 0x88, 3, 1 },
+ /* Main Peripheral PLL1 End */
+
+ /* Peripheral clocks */
+ { AGILEX5_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_user0_mux,
+ ARRAY_SIZE(s2f_user0_mux), 0, 0x24, 6, 0, 0, 0, 0x30, 2, 0 },
+ { AGILEX5_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux,
+ ARRAY_SIZE(s2f_user1_mux), 0, 0x7C, 6, 0, 0, 0, 0x88, 5, 0 },
+ { AGILEX5_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux,
+ ARRAY_SIZE(psi_mux), 0, 0x7C, 7, 0, 0, 0, 0x88, 6, 0 },
+ { AGILEX5_USB31_SUSPEND_CLK, "usb31_suspend_clk", NULL, usb31_mux,
+ ARRAY_SIZE(usb31_mux), 0, 0x7C, 25, 0, 0, 0, 0x88, 7, 0 },
+ { AGILEX5_USB31_BUS_CLK_EARLY, "usb31_bus_clk_early", "l4_main_clk",
+ NULL, 1, 0, 0x7C, 25, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_USB2OTG_HCLK, "usb2otg_hclk", "l4_mp_clk", NULL, 1, 0, 0x7C,
+ 8, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_SPIM_0_CLK, "spim_0_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, 9,
+ 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_SPIM_1_CLK, "spim_1_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, 11,
+ 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_SPIS_0_CLK, "spis_0_clk", "l4_sp_clk", NULL, 1, 0, 0x7C, 12,
+ 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_SPIS_1_CLK, "spis_1_clk", "l4_sp_clk", NULL, 1, 0, 0x7C, 13,
+ 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_DMA_CORE_CLK, "dma_core_clk", "l4_mp_clk", NULL, 1, 0, 0x7C,
+ 14, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_DMA_HS_CLK, "dma_hs_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, 14,
+ 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_I3C_0_CORE_CLK, "i3c_0_core_clk", "l4_mp_clk", NULL, 1, 0,
+ 0x7C, 18, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_I3C_1_CORE_CLK, "i3c_1_core_clk", "l4_mp_clk", NULL, 1, 0,
+ 0x7C, 19, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_I2C_0_PCLK, "i2c_0_pclk", "l4_sp_clk", NULL, 1, 0, 0x7C, 15,
+ 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_I2C_1_PCLK, "i2c_1_pclk", "l4_sp_clk", NULL, 1, 0, 0x7C, 16,
+ 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_I2C_EMAC0_PCLK, "i2c_emac0_pclk", "l4_sp_clk", NULL, 1, 0,
+ 0x7C, 17, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_I2C_EMAC1_PCLK, "i2c_emac1_pclk", "l4_sp_clk", NULL, 1, 0,
+ 0x7C, 22, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_I2C_EMAC2_PCLK, "i2c_emac2_pclk", "l4_sp_clk", NULL, 1, 0,
+ 0x7C, 27, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_UART_0_PCLK, "uart_0_pclk", "l4_sp_clk", NULL, 1, 0, 0x7C, 20,
+ 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_UART_1_PCLK, "uart_1_pclk", "l4_sp_clk", NULL, 1, 0, 0x7C, 21,
+ 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_SPTIMER_0_PCLK, "sptimer_0_pclk", "l4_sp_clk", NULL, 1, 0,
+ 0x7C, 23, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_SPTIMER_1_PCLK, "sptimer_1_pclk", "l4_sp_clk", NULL, 1, 0,
+ 0x7C, 24, 0, 0, 0, 0, 0, 0 },
+
+ /*NAND, SD/MMC and SoftPHY overall clocking*/
+ { AGILEX5_DFI_CLK, "dfi_clk", "l4_mp_clk", NULL, 1, 0, 0, 0, 0x44, 16,
+ 2, 0, 0, 0 },
+ { AGILEX5_NAND_NF_CLK, "nand_nf_clk", "dfi_clk", NULL, 1, 0, 0x7C, 10,
+ 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_NAND_BCH_CLK, "nand_bch_clk", "l4_mp_clk", NULL, 1, 0, 0x7C,
+ 10, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_SDMMC_SDPHY_REG_CLK, "sdmmc_sdphy_reg_clk", "l4_mp_clk", NULL,
+ 1, 0, 0x7C, 5, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_SDMCLK, "sdmclk", "dfi_clk", NULL, 1, 0, 0x7C, 5, 0, 0, 0, 0,
+ 0, 0 },
+ { AGILEX5_SOFTPHY_REG_PCLK, "softphy_reg_pclk", "l4_mp_clk", NULL, 1, 0,
+ 0x7C, 26, 0, 0, 0, 0, 0, 0 },
+ { AGILEX5_SOFTPHY_PHY_CLK, "softphy_phy_clk", "l4_mp_clk", NULL, 1, 0,
+ 0x7C, 26, 0x44, 16, 2, 0, 0, 0 },
+ { AGILEX5_SOFTPHY_CTRL_CLK, "softphy_ctrl_clk", "dfi_clk", NULL, 1, 0,
+ 0x7C, 26, 0, 0, 0, 0, 0, 0 },
+};
+
+static int
+agilex5_clk_register_c_perip(const struct stratix10_perip_c_clock *clks,
+ int nums, struct stratix10_clock_data *data)
+{
+ struct clk_hw *hw_clk;
+ void __iomem *base = data->base;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ hw_clk = s10_register_periph(&clks[i], base);
+ if (IS_ERR(hw_clk)) {
+ pr_err("%s: failed to register clock %s\n", __func__,
+ clks[i].name);
+ continue;
+ }
+ data->clk_data.hws[clks[i].id] = hw_clk;
+ }
+ return 0;
+}
+
+static int
+agilex5_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks,
+ int nums, struct stratix10_clock_data *data)
+{
+ struct clk_hw *hw_clk;
+ void __iomem *base = data->base;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ hw_clk = s10_register_cnt_periph(&clks[i], base);
+ if (IS_ERR(hw_clk)) {
+ pr_err("%s: failed to register clock %s\n", __func__,
+ clks[i].name);
+ continue;
+ }
+ data->clk_data.hws[clks[i].id] = hw_clk;
+ }
+
+ return 0;
+}
+
+static int agilex5_clk_register_gate(const struct stratix10_gate_clock *clks,
+ int nums,
+ struct stratix10_clock_data *data)
+{
+ struct clk_hw *hw_clk;
+ void __iomem *base = data->base;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ hw_clk = agilex_register_gate(&clks[i], base);
+ if (IS_ERR(hw_clk)) {
+ pr_err("%s: failed to register clock %s\n", __func__,
+ clks[i].name);
+ continue;
+ }
+ data->clk_data.hws[clks[i].id] = hw_clk;
+ }
+
+ return 0;
+}
+
+static int agilex5_clk_register_pll(const struct stratix10_pll_clock *clks,
+ int nums, struct stratix10_clock_data *data)
+{
+ struct clk_hw *hw_clk;
+ void __iomem *base = data->base;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ hw_clk = agilex5_register_pll(&clks[i], base);
+ if (IS_ERR(hw_clk)) {
+ pr_err("%s: failed to register clock %s\n", __func__,
+ clks[i].name);
+ continue;
+ }
+ data->clk_data.hws[clks[i].id] = hw_clk;
+ }
+
+ return 0;
+}
+
+static int agilex5_clkmgr_probe(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct stratix10_clock_data *clk_data;
+ struct resource *res;
+ int i, num_clks;
+
+ res = dev_get_resource(dev, IORESOURCE_MEM, 0);
+ if (IS_ERR(res))
+ return PTR_ERR(res);
+
+ num_clks = AGILEX5_NUM_CLKS;
+
+ clk_data = xzalloc(struct_size(clk_data, clk_data.hws, num_clks));
+ if (!clk_data)
+ return -ENOMEM;
+
+ for (i = 0; i < num_clks; i++)
+ clk_data->clk_data.hws[i] = ERR_PTR(-ENOENT);
+
+ clk_data->base = IOMEM(res->start);
+ clk_data->clk_data.num = num_clks;
+
+ agilex5_clk_register_pll(agilex5_pll_clks, ARRAY_SIZE(agilex5_pll_clks),
+ clk_data);
+
+ agilex5_clk_register_c_perip(agilex5_main_perip_c_clks,
+ ARRAY_SIZE(agilex5_main_perip_c_clks),
+ clk_data);
+
+ agilex5_clk_register_cnt_perip(agilex5_main_perip_cnt_clks,
+ ARRAY_SIZE(agilex5_main_perip_cnt_clks),
+ clk_data);
+
+ agilex5_clk_register_gate(agilex5_gate_clks,
+ ARRAY_SIZE(agilex5_gate_clks), clk_data);
+
+ of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &clk_data->clk_data);
+ return 0;
+}
+
+static const struct of_device_id agilex5_clkmgr_match_table[] = {
+ {
+ .compatible = "intel,agilex5-clkmgr",
+ } , {
+ /* sentinel */
+ }
+};
+
+static struct driver agilex5_clkmgr_driver = {
+ .name = "agilex5-clkmgr",
+ .of_match_table = agilex5_clkmgr_match_table,
+ .probe = agilex5_clkmgr_probe,
+};
+
+static int __init agilex5_clk_init(void)
+{
+ return platform_driver_register(&agilex5_clkmgr_driver);
+}
+core_initcall(agilex5_clk_init);
diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c
new file mode 100644
index 0000000000000000000000000000000000000000..2aac28c7c2d4bc24d640bcab5c6fa047123fafa0
--- /dev/null
+++ b/drivers/clk/socfpga/clk-gate-s10.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#include "stratix10-clk.h"
+#include "clk.h"
+
+#define SOCFPGA_CS_PDBG_CLK "cs_pdbg_clk"
+#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw)
+
+#define SOCFPGA_EMAC0_CLK "emac0_clk"
+#define SOCFPGA_EMAC1_CLK "emac1_clk"
+#define SOCFPGA_EMAC2_CLK "emac2_clk"
+#define AGILEX_BYPASS_OFFSET 0xC
+#define STRATIX10_BYPASS_OFFSET 0x2C
+#define BOOTCLK_BYPASS 2
+
+static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+ u32 div = 1, val;
+
+ if (socfpgaclk->fixed_div) {
+ div = socfpgaclk->fixed_div;
+ } else if (socfpgaclk->div_reg) {
+ val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+ val &= GENMASK(socfpgaclk->width - 1, 0);
+ div = (1 << val);
+ }
+ return parent_rate / div;
+}
+
+static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+ u32 div, val;
+
+ val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+ val &= GENMASK(socfpgaclk->width - 1, 0);
+ div = (1 << val);
+ div = div ? 4 : 1;
+
+ return parent_rate / div;
+}
+
+static int socfpga_gate_get_parent(struct clk_hw *hwclk)
+{
+ struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+ u32 mask, second_bypass;
+ u8 parent = 0;
+ const char *name = clk_hw_get_name(hwclk);
+
+printk("%s: %s\n", __func__, name);
+
+ if (socfpgaclk->bypass_reg) {
+ mask = (0x1 << socfpgaclk->bypass_shift);
+ parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+ socfpgaclk->bypass_shift);
+printk("%s: parent %d\n", __func__, parent);
+ }
+
+ if (streq(name, SOCFPGA_EMAC0_CLK) ||
+ streq(name, SOCFPGA_EMAC1_CLK) ||
+ streq(name, SOCFPGA_EMAC2_CLK)) {
+ second_bypass = readl(socfpgaclk->bypass_reg -
+ STRATIX10_BYPASS_OFFSET);
+ /* EMACA bypass to bootclk @0xB0 offset */
+ if (second_bypass & 0x1)
+ if (parent == 0) /* only applicable if parent is maca */
+ parent = BOOTCLK_BYPASS;
+
+ if (second_bypass & 0x2)
+ if (parent == 1) /* only applicable if parent is macb */
+ parent = BOOTCLK_BYPASS;
+ }
+ return parent;
+}
+
+static int socfpga_agilex_gate_get_parent(struct clk_hw *hwclk)
+{
+ struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+ u32 mask, second_bypass;
+ u8 parent = 0;
+ const char *name = clk_hw_get_name(hwclk);
+
+ if (socfpgaclk->bypass_reg) {
+ mask = (0x1 << socfpgaclk->bypass_shift);
+ parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+ socfpgaclk->bypass_shift);
+ }
+
+ if (streq(name, SOCFPGA_EMAC0_CLK) ||
+ streq(name, SOCFPGA_EMAC1_CLK) ||
+ streq(name, SOCFPGA_EMAC2_CLK)) {
+ second_bypass = readl(socfpgaclk->bypass_reg -
+ AGILEX_BYPASS_OFFSET);
+ /* EMACA bypass to bootclk @0x88 offset */
+ if (second_bypass & 0x1)
+ if (parent == 0) /* only applicable if parent is maca */
+ parent = BOOTCLK_BYPASS;
+
+ if (second_bypass & 0x2)
+ if (parent == 1) /* only applicable if parent is macb */
+ parent = BOOTCLK_BYPASS;
+ }
+
+ return parent;
+}
+
+static struct clk_ops agilex_gateclk_ops = {
+ .recalc_rate = socfpga_gate_clk_recalc_rate,
+ .get_parent = socfpga_agilex_gate_get_parent,
+};
+
+static const struct clk_ops dbgclk_ops = {
+ .recalc_rate = socfpga_dbg_clk_recalc_rate,
+ .get_parent = socfpga_gate_get_parent,
+};
+
+struct clk_hw *agilex_register_gate(const struct stratix10_gate_clock *clks, void __iomem *regbase)
+{
+ struct clk_hw *hw_clk;
+ struct socfpga_gate_clk *socfpga_clk;
+ struct clk_init_data init;
+ const char *parent_name = clks->parent_name;
+ int ret;
+
+ socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
+ if (!socfpga_clk)
+ return NULL;
+
+ socfpga_clk->reg = regbase + clks->gate_reg;
+ socfpga_clk->bit_idx = clks->gate_idx;
+
+ agilex_gateclk_ops.enable = clk_gate_ops.enable;
+ agilex_gateclk_ops.disable = clk_gate_ops.disable;
+
+ socfpga_clk->fixed_div = clks->fixed_div;
+
+ if (clks->div_reg)
+ socfpga_clk->div_reg = regbase + clks->div_reg;
+ else
+ socfpga_clk->div_reg = NULL;
+
+ socfpga_clk->width = clks->div_width;
+ socfpga_clk->shift = clks->div_offset;
+
+ if (clks->bypass_reg)
+ socfpga_clk->bypass_reg = regbase + clks->bypass_reg;
+ else
+ socfpga_clk->bypass_reg = NULL;
+ socfpga_clk->bypass_shift = clks->bypass_shift;
+
+ if (streq(clks->name, "cs_pdbg_clk"))
+ init.ops = &dbgclk_ops;
+ else
+ init.ops = &agilex_gateclk_ops;
+ init.name = clks->name;
+ init.flags = clks->flags;
+
+ init.num_parents = clks->num_parents;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ if (init.parent_names == NULL)
+ init.parent_data = clks->parent_data;
+ socfpga_clk->hw.init = &init;
+
+ hw_clk = &socfpga_clk->hw;
+
+ ret = clk_hw_register(NULL, &socfpga_clk->hw);
+ if (ret) {
+ kfree(socfpga_clk);
+ return ERR_PTR(ret);
+ }
+ return hw_clk;
+}
diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
new file mode 100644
index 0000000000000000000000000000000000000000..68f9d4bc80af5587666e1a4900362eba290ef4f4
--- /dev/null
+++ b/drivers/clk/socfpga/clk-periph-s10.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk-provider.h>
+
+#include "stratix10-clk.h"
+#include "clk.h"
+
+#define CLK_MGR_FREE_SHIFT 16
+#define CLK_MGR_FREE_MASK 0x7
+#define SWCTRLBTCLKSEN_SHIFT 8
+
+#define to_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw)
+
+static unsigned long clk_peri_c_clk_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+ unsigned long div = 1;
+ u32 val;
+
+ val = readl(socfpgaclk->reg);
+ val &= GENMASK(SWCTRLBTCLKSEN_SHIFT - 1, 0);
+ parent_rate /= val;
+
+ return parent_rate / div;
+}
+
+static unsigned long clk_peri_cnt_clk_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+ unsigned long div = 1;
+
+ if (socfpgaclk->fixed_div) {
+ div = socfpgaclk->fixed_div;
+ } else {
+ if (socfpgaclk->reg)
+ div = ((readl(socfpgaclk->reg) & 0x7ff) + 1);
+ }
+
+ return parent_rate / div;
+}
+
+static int clk_periclk_get_parent(struct clk_hw *hwclk)
+{
+ struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
+ u32 clk_src, mask;
+ u8 parent = 0;
+
+ /* handle the bypass first */
+ if (socfpgaclk->bypass_reg) {
+ mask = (0x1 << socfpgaclk->bypass_shift);
+ parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
+ socfpgaclk->bypass_shift);
+ if (parent)
+ return parent;
+ }
+
+ if (socfpgaclk->reg) {
+ clk_src = readl(socfpgaclk->reg);
+ parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
+ CLK_MGR_FREE_MASK;
+ }
+ return parent;
+}
+
+static const struct clk_ops peri_c_clk_ops = {
+ .recalc_rate = clk_peri_c_clk_recalc_rate,
+ .get_parent = clk_periclk_get_parent,
+};
+
+static const struct clk_ops peri_cnt_clk_ops = {
+ .recalc_rate = clk_peri_cnt_clk_recalc_rate,
+ .get_parent = clk_periclk_get_parent,
+};
+
+struct clk_hw *s10_register_periph(const struct stratix10_perip_c_clock *clks,
+ void __iomem *reg)
+{
+ struct clk_hw *hw_clk;
+ struct socfpga_periph_clk *periph_clk;
+ struct clk_init_data init;
+ const char *name = clks->name;
+ const char *parent_name = clks->parent_name;
+ int ret;
+
+ periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+ if (WARN_ON(!periph_clk))
+ return NULL;
+
+ periph_clk->reg = reg + clks->offset;
+
+ init.name = name;
+ init.ops = &peri_c_clk_ops;
+ init.flags = clks->flags;
+
+ init.num_parents = clks->num_parents;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ if (init.parent_names == NULL)
+ init.parent_data = clks->parent_data;
+
+ periph_clk->hw.init = &init;
+ hw_clk = &periph_clk->hw;
+
+ ret = clk_hw_register(NULL, hw_clk);
+ if (ret) {
+ kfree(periph_clk);
+ return ERR_PTR(ret);
+ }
+ return hw_clk;
+}
+
+struct clk_hw *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *clks,
+ void __iomem *regbase)
+{
+ struct clk_hw *hw_clk;
+ struct socfpga_periph_clk *periph_clk;
+ struct clk_init_data init;
+ const char *name = clks->name;
+ const char *parent_name = clks->parent_name;
+ int ret;
+
+ periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+ if (WARN_ON(!periph_clk))
+ return NULL;
+
+ if (clks->offset)
+ periph_clk->reg = regbase + clks->offset;
+ else
+ periph_clk->reg = NULL;
+
+ if (clks->bypass_reg)
+ periph_clk->bypass_reg = regbase + clks->bypass_reg;
+ else
+ periph_clk->bypass_reg = NULL;
+ periph_clk->bypass_shift = clks->bypass_shift;
+ periph_clk->fixed_div = clks->fixed_divider;
+
+ init.name = name;
+ init.ops = &peri_cnt_clk_ops;
+ init.flags = clks->flags;
+
+ init.num_parents = clks->num_parents;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ if (init.parent_names == NULL)
+ init.parent_data = clks->parent_data;
+
+ periph_clk->hw.init = &init;
+ hw_clk = &periph_clk->hw;
+
+ ret = clk_hw_register(NULL, hw_clk);
+ if (ret) {
+ kfree(periph_clk);
+ return ERR_PTR(ret);
+ }
+ return hw_clk;
+}
diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c
new file mode 100644
index 0000000000000000000000000000000000000000..59e5ec33b06b6cf634b353bf6d6fe4d345171550
--- /dev/null
+++ b/drivers/clk/socfpga/clk-pll-s10.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#include "stratix10-clk.h"
+#include "clk.h"
+
+/* Clock Manager offsets */
+#define CLK_MGR_PLL_CLK_SRC_SHIFT 16
+#define CLK_MGR_PLL_CLK_SRC_MASK 0x3
+
+/* PLL Clock enable bits */
+#define SOCFPGA_PLL_POWER 0
+#define SOCFPGA_PLL_RESET_MASK 0x2
+#define SOCFPGA_PLL_REFDIV_MASK 0x00003F00
+#define SOCFPGA_PLL_REFDIV_SHIFT 8
+#define SOCFPGA_PLL_AREFDIV_MASK 0x00000F00
+#define SOCFPGA_PLL_DREFDIV_MASK 0x00003000
+#define SOCFPGA_PLL_DREFDIV_SHIFT 12
+#define SOCFPGA_PLL_MDIV_MASK 0xFF000000
+#define SOCFPGA_PLL_MDIV_SHIFT 24
+#define SOCFPGA_AGILEX_PLL_MDIV_MASK 0x000003FF
+#define SWCTRLBTCLKSEL_MASK 0x200
+#define SWCTRLBTCLKSEL_SHIFT 9
+
+#define SOCFPGA_BOOT_CLK "boot_clk"
+
+#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw)
+
+static unsigned long agilex_clk_pll_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+ unsigned long arefdiv, reg, mdiv;
+ unsigned long long vco_freq;
+
+ /* read VCO1 reg for numerator and denominator */
+ reg = readl(socfpgaclk->reg);
+ arefdiv = (reg & SOCFPGA_PLL_AREFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
+
+ vco_freq = (unsigned long long)parent_rate / arefdiv;
+
+ /* Read mdiv and fdiv from the fdbck register */
+ reg = readl(socfpgaclk->reg + 0x24);
+ mdiv = reg & SOCFPGA_AGILEX_PLL_MDIV_MASK;
+
+ vco_freq = (unsigned long long)vco_freq * mdiv;
+ return (unsigned long)vco_freq;
+}
+
+static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
+ unsigned long parent_rate)
+{
+ struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+ u32 div;
+
+ div = ((readl(socfpgaclk->reg) &
+ SWCTRLBTCLKSEL_MASK) >>
+ SWCTRLBTCLKSEL_SHIFT);
+ div += 1;
+ return parent_rate / div;
+}
+
+static int clk_pll_get_parent(struct clk_hw *hwclk)
+{
+ struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+ u32 pll_src;
+
+ pll_src = readl(socfpgaclk->reg);
+ return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
+ CLK_MGR_PLL_CLK_SRC_MASK;
+}
+
+static int clk_boot_get_parent(struct clk_hw *hwclk)
+{
+ struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+ u32 pll_src;
+
+ pll_src = readl(socfpgaclk->reg);
+ return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
+ SWCTRLBTCLKSEL_MASK;
+}
+
+/* TODO need to fix, Agilex5 SM requires change */
+static const struct clk_ops agilex5_clk_pll_ops = {
+ /* TODO This may require a custom Agilex5 implementation */
+ .recalc_rate = agilex_clk_pll_recalc_rate,
+ .get_parent = clk_pll_get_parent,
+};
+
+static const struct clk_ops clk_boot_ops = {
+ .recalc_rate = clk_boot_clk_recalc_rate,
+ .get_parent = clk_boot_get_parent,
+};
+
+struct clk_hw *agilex5_register_pll(const struct stratix10_pll_clock *clks,
+ void __iomem *reg)
+{
+ struct clk_hw *hw_clk;
+ struct socfpga_pll *pll_clk;
+ struct clk_init_data init;
+ const char *name = clks->name;
+ int ret;
+
+ pll_clk = xzalloc(sizeof(*pll_clk));
+ if (!pll_clk)
+ return ERR_PTR(-ENOMEM);
+
+ pll_clk->reg = reg + clks->offset;
+
+ if (streq(name, SOCFPGA_BOOT_CLK))
+ init.ops = &clk_boot_ops;
+ else
+ init.ops = &agilex5_clk_pll_ops;
+
+ init.name = name;
+ init.flags = clks->flags;
+
+ init.num_parents = clks->num_parents;
+ init.parent_names = NULL;
+ init.parent_data = clks->parent_data;
+ pll_clk->hw.init = &init;
+
+ pll_clk->bit_idx = SOCFPGA_PLL_POWER;
+ hw_clk = &pll_clk->hw;
+
+ ret = clk_hw_register(NULL, hw_clk);
+ if (ret) {
+ kfree(pll_clk);
+ return ERR_PTR(ret);
+ }
+ return hw_clk;
+}
+
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
index 402f714436ab2f94dc5ecbad244915f0fa1c6194..19fc45e7f639583342b37422f30762d673421760 100644
--- a/drivers/clk/socfpga/clk.h
+++ b/drivers/clk/socfpga/clk.h
@@ -20,6 +20,11 @@
#define SOCFPGA_MAX_PARENTS 5
#define streq(a, b) (strcmp((a), (b)) == 0)
+#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
+ ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
+
+#define SYSMGR_SDMMC_CTRL_SET_AS10(smplsel, drvsel) \
+ ((((smplsel) & 0x7) << 4) | (((drvsel) & 0x7) << 0))
extern void __iomem *clk_mgr_base_addr;
@@ -58,11 +63,13 @@ struct socfpga_gate_clk {
char *parent_name;
u32 fixed_div;
void __iomem *div_reg;
+ void __iomem *bypass_reg;
struct regmap *sys_mgr_base_addr;
u32 width; /* only valid if div_reg != 0 */
u32 shift; /* only valid if div_reg != 0 */
u32 bit_idx;
void __iomem *reg;
+ u32 bypass_shift; /* only valid if bypass_reg != 0 */
u32 clk_phase[2];
const char *parent_names[SOCFPGA_MAX_PARENTS];
};
@@ -73,8 +80,10 @@ struct socfpga_periph_clk {
char *parent_name;
u32 fixed_div;
void __iomem *div_reg;
+ void __iomem *bypass_reg;
u32 width; /* only valid if div_reg != 0 */
u32 shift; /* only valid if div_reg != 0 */
+ u32 bypass_shift; /* only valid if bypass_reg != 0 */
const char *parent_names[SOCFPGA_MAX_PARENTS];
};
diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h
new file mode 100644
index 0000000000000000000000000000000000000000..1fe025f65f7a05faf00efc3991d2afc9c564d5ca
--- /dev/null
+++ b/drivers/clk/socfpga/stratix10-clk.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017, Intel Corporation
+ */
+
+#ifndef __STRATIX10_CLK_H
+#define __STRATIX10_CLK_H
+
+struct stratix10_clock_data {
+ void __iomem *base;
+
+ /* Must be last */
+ struct clk_hw_onecell_data clk_data;
+};
+
+struct stratix10_pll_clock {
+ unsigned int id;
+ const char *name;
+ const struct clk_parent_data *parent_data;
+ u8 num_parents;
+ unsigned long flags;
+ unsigned long offset;
+};
+
+struct stratix10_perip_c_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent_name;
+ const struct clk_parent_data *parent_data;
+ u8 num_parents;
+ unsigned long flags;
+ unsigned long offset;
+};
+
+struct stratix10_perip_cnt_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent_name;
+ const struct clk_parent_data *parent_data;
+ u8 num_parents;
+ unsigned long flags;
+ unsigned long offset;
+ u8 fixed_divider;
+ unsigned long bypass_reg;
+ unsigned long bypass_shift;
+};
+
+struct stratix10_gate_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent_name;
+ const struct clk_parent_data *parent_data;
+ u8 num_parents;
+ unsigned long flags;
+ unsigned long gate_reg;
+ u8 gate_idx;
+ unsigned long div_reg;
+ u8 div_offset;
+ u8 div_width;
+ unsigned long bypass_reg;
+ u8 bypass_shift;
+ u8 fixed_div;
+};
+
+struct clk_hw *agilex5_register_pll(const struct stratix10_pll_clock *clks,
+ void __iomem *reg);
+struct clk_hw *s10_register_periph(const struct stratix10_perip_c_clock *clks,
+ void __iomem *reg);
+struct clk_hw *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *clks,
+ void __iomem *reg);
+struct clk_hw *agilex_register_gate(const struct stratix10_gate_clock *clks,
+ void __iomem *reg);
+#endif /* __STRATIX10_CLK_H */
diff --git a/include/dt-bindings/clock/agilex5-clock.h b/include/dt-bindings/clock/agilex5-clock.h
index 269108465387c0becb165d5fdc5d5eb4460ed9c8..8ddb96407eacdbb8998f5915d680328bf85b91aa 100644
--- a/include/dt-bindings/clock/agilex5-clock.h
+++ b/include/dt-bindings/clock/agilex5-clock.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Copyright (C) 2019-2022, Intel Corporation
+ * Copyright (C) 2022, Intel Corporation
*/
#ifndef __AGILEX5_CLOCK_H
@@ -9,63 +9,92 @@
/* fixed rate clocks */
#define AGILEX5_OSC1 0
#define AGILEX5_CB_INTOSC_HS_DIV2_CLK 1
-#define AGILEX5_CB_INTOSC_LS_CLK 2
-#define AGILEX5_L4_SYS_FREE_CLK 3
-#define AGILEX5_F2S_FREE_CLK 4
+#define AGILEX5_CB_INTOSC_LS_CLK 2
+#define AGILEX5_F2S_FREE_CLK 3
/* PLL clocks */
-#define AGILEX5_MAIN_PLL_CLK 5
-#define AGILEX5_MAIN_PLL_C0_CLK 6
-#define AGILEX5_MAIN_PLL_C1_CLK 7
-#define AGILEX5_MAIN_PLL_C2_CLK 8
-#define AGILEX5_MAIN_PLL_C3_CLK 9
-#define AGILEX5_PERIPH_PLL_CLK 10
-#define AGILEX5_PERIPH_PLL_C0_CLK 11
-#define AGILEX5_PERIPH_PLL_C1_CLK 12
-#define AGILEX5_PERIPH_PLL_C2_CLK 13
-#define AGILEX5_PERIPH_PLL_C3_CLK 14
-#define AGILEX5_MPU_FREE_CLK 15
-#define AGILEX5_MPU_CCU_CLK 16
-#define AGILEX5_BOOT_CLK 17
+#define AGILEX5_MAIN_PLL_CLK 4
+#define AGILEX5_MAIN_PLL_C0_CLK 5
+#define AGILEX5_MAIN_PLL_C1_CLK 6
+#define AGILEX5_MAIN_PLL_C2_CLK 7
+#define AGILEX5_MAIN_PLL_C3_CLK 8
+#define AGILEX5_PERIPH_PLL_CLK 9
+#define AGILEX5_PERIPH_PLL_C0_CLK 10
+#define AGILEX5_PERIPH_PLL_C1_CLK 11
+#define AGILEX5_PERIPH_PLL_C2_CLK 12
+#define AGILEX5_PERIPH_PLL_C3_CLK 13
+#define AGILEX5_CORE0_FREE_CLK 14
+#define AGILEX5_CORE1_FREE_CLK 15
+#define AGILEX5_CORE2_FREE_CLK 16
+#define AGILEX5_CORE3_FREE_CLK 17
+#define AGILEX5_DSU_FREE_CLK 18
+#define AGILEX5_BOOT_CLK 19
/* fixed factor clocks */
-#define AGILEX5_L3_MAIN_FREE_CLK 18
-#define AGILEX5_NOC_FREE_CLK 19
-#define AGILEX5_S2F_USR0_CLK 20
-#define AGILEX5_NOC_CLK 21
-#define AGILEX5_EMAC_A_FREE_CLK 22
-#define AGILEX5_EMAC_B_FREE_CLK 23
-#define AGILEX5_EMAC_PTP_FREE_CLK 24
-#define AGILEX5_GPIO_DB_FREE_CLK 25
-#define AGILEX5_SDMMC_FREE_CLK 26
-#define AGILEX5_S2F_USER0_FREE_CLK 27
-#define AGILEX5_S2F_USER1_FREE_CLK 28
-#define AGILEX5_PSI_REF_FREE_CLK 29
+#define AGILEX5_L3_MAIN_FREE_CLK 20
+#define AGILEX5_NOC_FREE_CLK 21
+#define AGILEX5_S2F_USR0_CLK 22
+#define AGILEX5_NOC_CLK 23
+#define AGILEX5_EMAC_A_FREE_CLK 24
+#define AGILEX5_EMAC_B_FREE_CLK 25
+#define AGILEX5_EMAC_PTP_FREE_CLK 26
+#define AGILEX5_GPIO_DB_FREE_CLK 27
+#define AGILEX5_S2F_USER0_FREE_CLK 28
+#define AGILEX5_S2F_USER1_FREE_CLK 29
+#define AGILEX5_PSI_REF_FREE_CLK 30
+#define AGILEX5_USB31_FREE_CLK 31
/* Gate clocks */
-#define AGILEX5_MPU_CLK 30
-#define AGILEX5_MPU_PERIPH_CLK 31
-#define AGILEX5_L4_MAIN_CLK 32
-#define AGILEX5_L4_MP_CLK 33
-#define AGILEX5_L4_SP_CLK 34
-#define AGILEX5_CS_AT_CLK 35
-#define AGILEX5_CS_TRACE_CLK 36
-#define AGILEX5_CS_PDBG_CLK 37
-#define AGILEX5_CS_TIMER_CLK 38
-#define AGILEX5_S2F_USER0_CLK 39
-#define AGILEX5_EMAC0_CLK 40
-#define AGILEX5_EMAC1_CLK 41
-#define AGILEX5_EMAC2_CLK 42
-#define AGILEX5_EMAC_PTP_CLK 43
-#define AGILEX5_GPIO_DB_CLK 44
-#define AGILEX5_NAND_CLK 45
-#define AGILEX5_PSI_REF_CLK 46
-#define AGILEX5_S2F_USER1_CLK 47
-#define AGILEX5_SDMMC_CLK 48
-#define AGILEX5_SPI_M_CLK 49
-#define AGILEX5_USB_CLK 50
-#define AGILEX5_NAND_X_CLK 51
-#define AGILEX5_NAND_ECC_CLK 52
-#define AGILEX5_NUM_CLKS 53
+#define AGILEX5_CORE0_CLK 32
+#define AGILEX5_CORE1_CLK 33
+#define AGILEX5_CORE2_CLK 34
+#define AGILEX5_CORE3_CLK 35
+#define AGILEX5_MPU_CLK 36
+#define AGILEX5_MPU_PERIPH_CLK 37
+#define AGILEX5_MPU_CCU_CLK 38
+#define AGILEX5_L4_MAIN_CLK 39
+#define AGILEX5_L4_MP_CLK 40
+#define AGILEX5_L4_SYS_FREE_CLK 41
+#define AGILEX5_L4_SP_CLK 42
+#define AGILEX5_CS_AT_CLK 43
+#define AGILEX5_CS_TRACE_CLK 44
+#define AGILEX5_CS_PDBG_CLK 45
+#define AGILEX5_EMAC1_CLK 47
+#define AGILEX5_EMAC2_CLK 48
+#define AGILEX5_EMAC_PTP_CLK 49
+#define AGILEX5_GPIO_DB_CLK 50
+#define AGILEX5_S2F_USER0_CLK 51
+#define AGILEX5_S2F_USER1_CLK 52
+#define AGILEX5_PSI_REF_CLK 53
+#define AGILEX5_USB31_SUSPEND_CLK 54
+#define AGILEX5_EMAC0_CLK 46
+#define AGILEX5_USB31_BUS_CLK_EARLY 55
+#define AGILEX5_USB2OTG_HCLK 56
+#define AGILEX5_SPIM_0_CLK 57
+#define AGILEX5_SPIM_1_CLK 58
+#define AGILEX5_SPIS_0_CLK 59
+#define AGILEX5_SPIS_1_CLK 60
+#define AGILEX5_DMA_CORE_CLK 61
+#define AGILEX5_DMA_HS_CLK 62
+#define AGILEX5_I3C_0_CORE_CLK 63
+#define AGILEX5_I3C_1_CORE_CLK 64
+#define AGILEX5_I2C_0_PCLK 65
+#define AGILEX5_I2C_1_PCLK 66
+#define AGILEX5_I2C_EMAC0_PCLK 67
+#define AGILEX5_I2C_EMAC1_PCLK 68
+#define AGILEX5_I2C_EMAC2_PCLK 69
+#define AGILEX5_UART_0_PCLK 70
+#define AGILEX5_UART_1_PCLK 71
+#define AGILEX5_SPTIMER_0_PCLK 72
+#define AGILEX5_SPTIMER_1_PCLK 73
+#define AGILEX5_DFI_CLK 74
+#define AGILEX5_NAND_NF_CLK 75
+#define AGILEX5_NAND_BCH_CLK 76
+#define AGILEX5_SDMMC_SDPHY_REG_CLK 77
+#define AGILEX5_SDMCLK 78
+#define AGILEX5_SOFTPHY_REG_PCLK 79
+#define AGILEX5_SOFTPHY_PHY_CLK 80
+#define AGILEX5_SOFTPHY_CTRL_CLK 81
+#define AGILEX5_NUM_CLKS 82
#endif /* __AGILEX5_CLOCK_H */
--
2.46.0
^ permalink raw reply [flat|nested] 11+ messages in thread