summaryrefslogtreecommitdiff
path: root/arch/arm/mach-stm32mp/stm32mp2
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-stm32mp/stm32mp2')
-rw-r--r--arch/arm/mach-stm32mp/stm32mp2/Makefile1
-rw-r--r--arch/arm/mach-stm32mp/stm32mp2/cpu.c16
-rw-r--r--arch/arm/mach-stm32mp/stm32mp2/rifsc.c130
-rw-r--r--arch/arm/mach-stm32mp/stm32mp2/stm32mp23x.c191
4 files changed, 280 insertions, 58 deletions
diff --git a/arch/arm/mach-stm32mp/stm32mp2/Makefile b/arch/arm/mach-stm32mp/stm32mp2/Makefile
index 5dbf75daa76..27fbf3ae728 100644
--- a/arch/arm/mach-stm32mp/stm32mp2/Makefile
+++ b/arch/arm/mach-stm32mp/stm32mp2/Makefile
@@ -7,4 +7,5 @@ obj-y += cpu.o
obj-y += arm64-mmu.o
obj-y += rifsc.o
obj-$(CONFIG_OF_SYSTEM_SETUP) += fdt.o
+obj-$(CONFIG_STM32MP23X) += stm32mp23x.o
obj-$(CONFIG_STM32MP25X) += stm32mp25x.o
diff --git a/arch/arm/mach-stm32mp/stm32mp2/cpu.c b/arch/arm/mach-stm32mp/stm32mp2/cpu.c
index c3b87d7f981..e081dc605b8 100644
--- a/arch/arm/mach-stm32mp/stm32mp2/cpu.c
+++ b/arch/arm/mach-stm32mp/stm32mp2/cpu.c
@@ -92,13 +92,21 @@ uintptr_t get_stm32mp_bl2_dtb(void)
}
/*
- * Save the FDT address provided by TF-A in r2 at boot time
+ * Save the FDT address provided by TF-A at boot time
* This function is called from start.S
*/
-void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2,
- unsigned long r3)
+void save_boot_params(unsigned long x0, unsigned long x1, unsigned long x2,
+ unsigned long x3)
{
- nt_fw_dtb = r2;
+ /* use the ARM64 kernel booting register settings:
+ * x0 = physical address of device tree blob (dtb) in system RAM.
+ * so kernel can replace U-Boot in FIP wihtout BL31 modification
+ * else falback to x2 used in previous TF-A version
+ */
+ if (x0)
+ nt_fw_dtb = x0;
+ else
+ nt_fw_dtb = x2;
save_boot_params_ret();
}
diff --git a/arch/arm/mach-stm32mp/stm32mp2/rifsc.c b/arch/arm/mach-stm32mp/stm32mp2/rifsc.c
index 50dececf77b..f8f67af4449 100644
--- a/arch/arm/mach-stm32mp/stm32mp2/rifsc.c
+++ b/arch/arm/mach-stm32mp/stm32mp2/rifsc.c
@@ -61,42 +61,41 @@ struct stm32_rifsc_child_plat {
u32 domain_id;
};
-static bool stm32_rif_is_semaphore_available(void *base, u32 id)
+static bool stm32_rif_is_semaphore_available(void *addr)
{
- void *addr = base + RIFSC_RISC_PER0_SEMCR(id);
-
return !(readl(addr) & SEMCR_MUTEX);
}
-static int stm32_rif_acquire_semaphore(void *base, u32 id)
+static int stm32_rifsc_acquire_semaphore(void *base, u32 id)
{
void *addr = base + RIFSC_RISC_PER0_SEMCR(id);
/* Check that the semaphore is available */
- if (!stm32_rif_is_semaphore_available(base, id))
+ if (!stm32_rif_is_semaphore_available(addr) &&
+ FIELD_GET(RIFSC_RISC_SCID_MASK, (readl(addr)) != RIF_CID1))
return -EACCES;
setbits_le32(addr, SEMCR_MUTEX);
/* Check that CID1 has the semaphore */
- if (stm32_rif_is_semaphore_available(base, id) ||
+ if (stm32_rif_is_semaphore_available(addr) ||
FIELD_GET(RIFSC_RISC_SCID_MASK, (readl(addr)) != RIF_CID1))
return -EACCES;
return 0;
}
-static int stm32_rif_release_semaphore(void *base, u32 id)
+static int stm32_rifsc_release_semaphore(void *base, u32 id)
{
void *addr = base + RIFSC_RISC_PER0_SEMCR(id);
- if (stm32_rif_is_semaphore_available(base, id))
+ if (stm32_rif_is_semaphore_available(addr))
return 0;
clrbits_le32(addr, SEMCR_MUTEX);
/* Ok if another compartment takes the semaphore before the check */
- if (!stm32_rif_is_semaphore_available(base, id) &&
+ if (!stm32_rif_is_semaphore_available(addr) &&
FIELD_GET(RIFSC_RISC_SCID_MASK, (readl(addr)) == RIF_CID1))
return -EACCES;
@@ -105,11 +104,10 @@ static int stm32_rif_release_semaphore(void *base, u32 id)
static int rifsc_parse_access_controller(ofnode node, struct ofnode_phandle_args *args)
{
- int ret;
+ int ret = ofnode_parse_phandle_with_args(node, "access-controllers",
+ "#access-controller-cells", 0,
+ 0, args);
- ret = ofnode_parse_phandle_with_args(node, "access-controllers",
- "#access-controller-cells", 0,
- 0, args);
if (ret) {
log_debug("failed to parse access-controller (%d)\n", ret);
return ret;
@@ -170,8 +168,8 @@ static int rifsc_check_access(void *base, u32 id)
log_debug("Not in semaphore whitelist for peripheral %d\n", id);
return -EACCES;
}
- if (!stm32_rif_is_semaphore_available(base, id) &&
- !(FIELD_GET(RIFSC_RISC_SCID_MASK, sem_reg_value) & BIT(RIF_CID1))) {
+ if (!stm32_rif_is_semaphore_available(base + RIFSC_RISC_PER0_SEMCR(id)) &&
+ !(FIELD_GET(RIFSC_RISC_SCID_MASK, sem_reg_value) & RIF_CID1)) {
log_debug("Semaphore unavailable for peripheral %d\n", id);
return -EACCES;
}
@@ -187,22 +185,44 @@ skip_cid_check:
return 0;
}
-int stm32_rifsc_check_access_by_id(ofnode device_node, u32 id)
+int stm32_rifsc_grant_access_by_id(ofnode device_node, u32 id)
{
struct ofnode_phandle_args args;
+ u32 cid_reg_value;
+ void *rifsc_base;
int err;
- if (id >= STM32MP25_RIFSC_ENTRIES)
- return -EINVAL;
-
err = rifsc_parse_access_controller(device_node, &args);
if (err)
+ panic("Failed to parse access-controllers property\n");
+
+ rifsc_base = (void *)ofnode_get_addr(args.node);
+
+ err = rifsc_check_access(rifsc_base, id);
+ if (err)
return err;
- return rifsc_check_access((void *)ofnode_get_addr(args.node), id);
+ cid_reg_value = readl(rifsc_base + RIFSC_RISC_PER0_CIDCFGR(id));
+
+ /*
+ * If the peripheral is in semaphore mode, take the semaphore so that
+ * the CID1 has the ownership.
+ */
+ if (cid_reg_value & CIDCFGR_SEMEN &&
+ (FIELD_GET(RIFSC_RISC_SEMWL_MASK, cid_reg_value) & BIT(RIF_CID1))) {
+ err = stm32_rifsc_acquire_semaphore(rifsc_base, id);
+ if (err) {
+ pr_err("Couldn't acquire RIF semaphore for peripheral %d (%d)\n",
+ id, err);
+ return err;
+ }
+ pr_debug("Acquiring RIF semaphore for peripheral %d\n", id);
+ }
+
+ return 0;
}
-int stm32_rifsc_check_access(ofnode device_node)
+int stm32_rifsc_grant_access(ofnode device_node)
{
struct ofnode_phandle_args args;
int err;
@@ -211,58 +231,60 @@ int stm32_rifsc_check_access(ofnode device_node)
if (err)
return err;
- return rifsc_check_access((void *)ofnode_get_addr(args.node), args.args[0]);
+ return stm32_rifsc_grant_access_by_id(device_node, args.args[0]);
+
}
-static int stm32_rifsc_child_pre_probe(struct udevice *dev)
+void stm32_rifsc_release_access_by_id(ofnode device_node, u32 id)
{
- struct stm32_rifsc_plat *plat = dev_get_plat(dev->parent);
- struct stm32_rifsc_child_plat *child_plat = dev_get_parent_plat(dev);
+ struct ofnode_phandle_args args;
u32 cid_reg_value;
+ void *rifsc_base;
int err;
- u32 id = child_plat->domain_id;
- cid_reg_value = readl(plat->base + RIFSC_RISC_PER0_CIDCFGR(id));
+ err = rifsc_parse_access_controller(device_node, &args);
+ if (err)
+ panic("Failed to parse access-controllers property\n");
- /*
- * If the peripheral is in semaphore mode, take the semaphore so that
- * the CID1 has the ownership.
- */
+ rifsc_base = (void *)ofnode_get_addr(args.node);
+
+ cid_reg_value = readl(rifsc_base + RIFSC_RISC_PER0_CIDCFGR(id));
+
+ /* If the peripheral is in semaphore mode, release it if we have the ownership */
if (cid_reg_value & CIDCFGR_SEMEN &&
(FIELD_GET(RIFSC_RISC_SEMWL_MASK, cid_reg_value) & BIT(RIF_CID1))) {
- err = stm32_rif_acquire_semaphore(plat->base, id);
+ err = stm32_rifsc_release_semaphore(rifsc_base, id);
if (err) {
- dev_err(dev, "Couldn't acquire RIF semaphore for peripheral %d (%d)\n",
- id, err);
- return err;
+ panic("Couldn't release RIF semaphore for peripheral %d (%d)\n", id, err);
}
- dev_dbg(dev, "Acquiring semaphore for peripheral %d\n", id);
+ pr_debug("Releasing RIF semaphore for peripheral %d\n", id);
}
+}
- return 0;
+void stm32_rifsc_release_access(ofnode device_node)
+{
+ struct ofnode_phandle_args args;
+ int err;
+
+ err = rifsc_parse_access_controller(device_node, &args);
+ if (err)
+ panic("Failed to parse access-controllers property\n");
+
+ stm32_rifsc_release_access_by_id(device_node, args.args[0]);
}
-static int stm32_rifsc_child_post_remove(struct udevice *dev)
+static int stm32_rifsc_child_pre_probe(struct udevice *dev)
{
- struct stm32_rifsc_plat *plat = dev_get_plat(dev->parent);
struct stm32_rifsc_child_plat *child_plat = dev_get_parent_plat(dev);
- u32 cid_reg_value;
- int err;
- u32 id = child_plat->domain_id;
- cid_reg_value = readl(plat->base + RIFSC_RISC_PER0_CIDCFGR(id));
+ return stm32_rifsc_grant_access_by_id(dev_ofnode(dev), child_plat->domain_id);
+}
- /*
- * If the peripheral is in semaphore mode, release the semaphore so that
- * there's no ownership.
- */
- if (cid_reg_value & CIDCFGR_SEMEN &&
- (FIELD_GET(RIFSC_RISC_SEMWL_MASK, cid_reg_value) & BIT(RIF_CID1))) {
- err = stm32_rif_release_semaphore(plat->base, id);
- if (err)
- dev_err(dev, "Couldn't release rif semaphore for peripheral %d (%d)\n",
- id, err);
- }
+static int stm32_rifsc_child_post_remove(struct udevice *dev)
+{
+ struct stm32_rifsc_child_plat *child_plat = dev_get_parent_plat(dev);
+
+ stm32_rifsc_release_access_by_id(dev_ofnode(dev), child_plat->domain_id);
return 0;
}
diff --git a/arch/arm/mach-stm32mp/stm32mp2/stm32mp23x.c b/arch/arm/mach-stm32mp/stm32mp2/stm32mp23x.c
new file mode 100644
index 00000000000..022db60811a
--- /dev/null
+++ b/arch/arm/mach-stm32mp/stm32mp2/stm32mp23x.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2025, STMicroelectronics - All Rights Reserved
+ */
+
+#define LOG_CATEGORY LOGC_ARCH
+
+#include <log.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/stm32.h>
+#include <asm/arch/sys_proto.h>
+
+/* SYSCFG register */
+#define SYSCFG_DEVICEID_OFFSET 0x6400
+#define SYSCFG_DEVICEID_DEV_ID_MASK GENMASK(11, 0)
+#define SYSCFG_DEVICEID_DEV_ID_SHIFT 0
+
+/* Revision ID = OTP102[5:0] 6 bits : 3 for Major / 3 for Minor*/
+#define REVID_SHIFT 0
+#define REVID_MASK GENMASK(5, 0)
+
+/* Device Part Number (RPN) = OTP9 */
+#define RPN_SHIFT 0
+#define RPN_MASK GENMASK(31, 0)
+
+/* Package = bit 0:2 of OTP122 => STM32MP23_PKG defines
+ * - 000: Custom package
+ * - 011: TFBGA361 => AL = 10x10, 361 balls pith 0.5mm
+ * - 100: TFBGA424 => AK = 14x14, 424 balls pith 0.5mm
+ * - 101: TFBGA436 => AI = 18x18, 436 balls pith 0.5mm
+ * - others: Reserved
+ */
+#define PKG_SHIFT 0
+#define PKG_MASK GENMASK(2, 0)
+
+static u32 read_deviceid(void)
+{
+ void *syscfg = syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
+
+ return readl(syscfg + SYSCFG_DEVICEID_OFFSET);
+}
+
+u32 get_cpu_dev(void)
+{
+ return (read_deviceid() & SYSCFG_DEVICEID_DEV_ID_MASK) >> SYSCFG_DEVICEID_DEV_ID_SHIFT;
+}
+
+u32 get_cpu_rev(void)
+{
+ return get_otp(BSEC_OTP_REVID, REVID_SHIFT, REVID_MASK);
+}
+
+/* Get Device Part Number (RPN) from OTP */
+u32 get_cpu_type(void)
+{
+ return get_otp(BSEC_OTP_RPN, RPN_SHIFT, RPN_MASK);
+}
+
+/* Get Package options from OTP */
+u32 get_cpu_package(void)
+{
+ return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK);
+}
+
+int get_eth_nb(void)
+{
+ int nb_eth;
+
+ switch (get_cpu_type()) {
+ case CPU_STM32MP235Fxx:
+ fallthrough;
+ case CPU_STM32MP235Dxx:
+ fallthrough;
+ case CPU_STM32MP235Cxx:
+ fallthrough;
+ case CPU_STM32MP235Axx:
+ fallthrough;
+ case CPU_STM32MP233Fxx:
+ fallthrough;
+ case CPU_STM32MP233Dxx:
+ fallthrough;
+ case CPU_STM32MP233Cxx:
+ fallthrough;
+ case CPU_STM32MP233Axx:
+ nb_eth = 2; /* dual ETH */
+ break;
+ case CPU_STM32MP231Fxx:
+ fallthrough;
+ case CPU_STM32MP231Dxx:
+ fallthrough;
+ case CPU_STM32MP231Cxx:
+ fallthrough;
+ case CPU_STM32MP231Axx:
+ nb_eth = 1; /* single ETH */
+ break;
+ default:
+ nb_eth = 0;
+ break;
+ }
+
+ return nb_eth;
+}
+
+void get_soc_name(char name[SOC_NAME_SIZE])
+{
+ char *cpu_s, *cpu_r, *package;
+
+ cpu_s = "????";
+ cpu_r = "?";
+ package = "??";
+ if (get_cpu_dev() == CPU_DEV_STM32MP23) {
+ switch (get_cpu_type()) {
+ case CPU_STM32MP235Fxx:
+ cpu_s = "235F";
+ break;
+ case CPU_STM32MP235Dxx:
+ cpu_s = "235D";
+ break;
+ case CPU_STM32MP235Cxx:
+ cpu_s = "235C";
+ break;
+ case CPU_STM32MP235Axx:
+ cpu_s = "235A";
+ break;
+ case CPU_STM32MP233Fxx:
+ cpu_s = "233F";
+ break;
+ case CPU_STM32MP233Dxx:
+ cpu_s = "233D";
+ break;
+ case CPU_STM32MP233Cxx:
+ cpu_s = "233C";
+ break;
+ case CPU_STM32MP233Axx:
+ cpu_s = "233A";
+ break;
+ case CPU_STM32MP231Fxx:
+ cpu_s = "231F";
+ break;
+ case CPU_STM32MP231Dxx:
+ cpu_s = "231D";
+ break;
+ case CPU_STM32MP231Cxx:
+ cpu_s = "231C";
+ break;
+ case CPU_STM32MP231Axx:
+ cpu_s = "231A";
+ break;
+ default:
+ cpu_s = "23??";
+ break;
+ }
+ /* REVISION */
+ switch (get_cpu_rev()) {
+ case OTP_REVID_1:
+ cpu_r = "A";
+ break;
+ case OTP_REVID_2:
+ cpu_r = "B";
+ break;
+ case OTP_REVID_2_1:
+ cpu_r = "Y";
+ break;
+ case OTP_REVID_2_2:
+ cpu_r = "X";
+ break;
+ default:
+ break;
+ }
+ /* PACKAGE */
+ switch (get_cpu_package()) {
+ case STM32MP23_PKG_CUSTOM:
+ package = "XX";
+ break;
+ case STM32MP23_PKG_AL_VFBGA361:
+ package = "AL";
+ break;
+ case STM32MP23_PKG_AK_VFBGA424:
+ package = "AK";
+ break;
+ case STM32MP23_PKG_AJ_TFBGA361:
+ package = "AJ";
+ break;
+ default:
+ break;
+ }
+ }
+
+ snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s Rev.%s", cpu_s, package, cpu_r);
+}