summaryrefslogtreecommitdiff
path: root/arch/arm/mach-socfpga/altera-sysmgr.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2025-02-25 08:25:00 -0600
committerTom Rini <trini@konsulko.com>2025-02-25 10:54:05 -0600
commit4da90796ca8bde2171cdd5bb7d1293b1edbccab6 (patch)
tree237b788e27beb6337b87113510a47e34fb85e686 /arch/arm/mach-socfpga/altera-sysmgr.c
parent3ecda19009ebbe46a64b0629f8b64173c7a551c0 (diff)
parent7965e52e32b0acd561c09f12c4aac1d075c16622 (diff)
Merge tag 'u-boot-socfpga-next-20250225' of https://source.denx.de/u-boot/custodians/u-boot-socfpga into next
CI: https://source.denx.de/u-boot/custodians/u-boot-socfpga/-/pipelines/24816 Please pull the SoCFPGA changes for next from u-boot-socfpga, containing boot support for the Altera SoCFPGA Agilex 5 platform in U-Boot. The changes include: 1. Board-specific configurations and setup required to enable Agilex 5 operation in U-Boot. 2. Integration of cache coherency unit (CCU) initialization routine, including CCU conguration in DT. 3. Clock, firewall (configured in DT), SMMU, low level initialization specific to Agilex 5. 4. Integration of memory initialization routine, including DDR setup. This patch set has been tested on Agilex 5 devkit with QSPI boot (UBI/UBIFS) and RAM boot (TFTP & ARM DS debugger).
Diffstat (limited to 'arch/arm/mach-socfpga/altera-sysmgr.c')
-rw-r--r--arch/arm/mach-socfpga/altera-sysmgr.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/arch/arm/mach-socfpga/altera-sysmgr.c b/arch/arm/mach-socfpga/altera-sysmgr.c
new file mode 100644
index 00000000000..ca3f5ca7dd5
--- /dev/null
+++ b/arch/arm/mach-socfpga/altera-sysmgr.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2025 Altera Corporation <www.altera.com>
+ */
+
+/*
+ * This driver supports the SOCFPGA System Manager Register block which
+ * aggregates different peripheral function into one area.
+ * On 64 bit ARM parts, the system manager only can be accessed during
+ * EL3 mode. At lower exception level a SMC call is required to perform
+ * the read and write operation.
+ */
+
+#define LOG_CATEGORY UCLASS_NOP
+
+#include <dm.h>
+#include <log.h>
+#include <misc.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch/altera-sysmgr.h>
+#include <asm/arch/smc_api.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/intel-smc.h>
+
+static int altr_sysmgr_read_generic(struct udevice *dev, u32 *addr, u32 *value)
+{
+ u64 args[1];
+ u64 ret_arg;
+ int ret = 0;
+
+ debug("%s: %s(dev=%p, addr=0x%lx):\n", __func__,
+ dev->name, dev, (uintptr_t)addr);
+
+ if (current_el() == 3) {
+ ret_arg = readl((uintptr_t)addr);
+ } else {
+ if (!(IS_ENABLED(CONFIG_SPL_BUILD)) && IS_ENABLED(CONFIG_SPL_ATF)) {
+ args[0] = (u64)(uintptr_t)addr;
+ ret = invoke_smc(INTEL_SIP_SMC_REG_READ, args, 1, &ret_arg, 1);
+ } else {
+ pr_err("%s Failed to read system manager at lower privilege and without BL31\n",
+ dev->name);
+ return -EPROTONOSUPPORT;
+ }
+ }
+
+ *value = (u32)ret_arg;
+ return ret;
+}
+
+static int altr_sysmgr_write_generic(struct udevice *dev, u32 *addr, u32 value)
+{
+ u64 args[2];
+ int ret = 0;
+
+ debug("%s: %s(dev=%p, addr=0x%lx, val=0x%x):\n", __func__,
+ dev->name, dev, (uintptr_t)addr, value);
+
+ if (current_el() == 3) {
+ writel(value, (uintptr_t)addr);
+ } else {
+ if (!(IS_ENABLED(CONFIG_SPL_BUILD)) && IS_ENABLED(CONFIG_SPL_ATF)) {
+ args[0] = (u64)(uintptr_t)(addr);
+ args[1] = value;
+ ret = invoke_smc(INTEL_SIP_SMC_REG_WRITE, args, 2, NULL, 0);
+ } else {
+ pr_err("%s Failed to write to system manager at lower privilege and without BL31\n",
+ dev->name);
+ return -EPROTONOSUPPORT;
+ }
+ }
+
+ return ret;
+}
+
+static int altr_sysmgr_probe(struct udevice *dev)
+{
+ fdt_addr_t addr;
+ struct altr_sysmgr_priv *altr_priv = dev_get_priv(dev);
+
+ debug("%s: %s(dev=%p):\n", __func__, dev->name, dev);
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE) {
+ pr_err("%s dev_read_addr() failed\n", dev->name);
+ return -ENODEV;
+ }
+
+ altr_priv->regs = (void __iomem *)addr;
+ return 0;
+}
+
+static const struct altr_sysmgr_ops sysmgr_ops = {
+ .read = altr_sysmgr_read_generic,
+ .write = altr_sysmgr_write_generic,
+};
+
+static const struct udevice_id altr_sysmgr_ids[] = {
+ { .compatible = "altr,sys-mgr-s10" },
+ { .compatible = "altr,sys-mgr" },
+ { },
+};
+
+U_BOOT_DRIVER(altr_sysmgr) = {
+ .name = "altr_sysmgr",
+ .id = UCLASS_NOP,
+ .of_match = altr_sysmgr_ids,
+ .probe = altr_sysmgr_probe,
+ .ops = &sysmgr_ops,
+ .priv_auto = sizeof(struct altr_sysmgr_priv),
+ .flags = DM_FLAG_PRE_RELOC,
+};