diff options
Diffstat (limited to 'arch/arm/mach-stm32mp/stm32mp2')
| -rw-r--r-- | arch/arm/mach-stm32mp/stm32mp2/Makefile | 1 | ||||
| -rw-r--r-- | arch/arm/mach-stm32mp/stm32mp2/cpu.c | 16 | ||||
| -rw-r--r-- | arch/arm/mach-stm32mp/stm32mp2/rifsc.c | 130 | ||||
| -rw-r--r-- | arch/arm/mach-stm32mp/stm32mp2/stm32mp23x.c | 191 | 
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); +} | 
