mirror of
				https://source.denx.de/u-boot/u-boot.git
				synced 2025-10-31 16:31:25 +01:00 
			
		
		
		
	Move this out of the common header and include it only where needed. In a number of cases this requires adding "struct udevice;" to avoid adding another large header or in other cases replacing / adding missing header files that had been pulled in, very indirectly. Finally, we have a few cases where we did not need to include <asm/global_data.h> at all, so remove that include. Signed-off-by: Simon Glass <sjg@chromium.org> Signed-off-by: Tom Rini <trini@konsulko.com>
		
			
				
	
	
		
			305 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			305 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0+
 | |
| /*
 | |
|  * Copyright 2019 NXP
 | |
|  */
 | |
| 
 | |
| #include <common.h>
 | |
| #include <log.h>
 | |
| #include <asm/arch/sci/sci.h>
 | |
| #include <asm/arch/sys_proto.h>
 | |
| #include <asm/global_data.h>
 | |
| #include <dm/ofnode.h>
 | |
| #include <fdt_support.h>
 | |
| #include <linux/libfdt.h>
 | |
| 
 | |
| DECLARE_GLOBAL_DATA_PTR;
 | |
| 
 | |
| static bool check_owned_resource(sc_rsrc_t rsrc_id)
 | |
| {
 | |
| 	bool owned;
 | |
| 
 | |
| 	owned = sc_rm_is_resource_owned(-1, rsrc_id);
 | |
| 
 | |
| 	return owned;
 | |
| }
 | |
| 
 | |
| static int disable_fdt_node(void *blob, int nodeoffset)
 | |
| {
 | |
| 	int rc, ret;
 | |
| 	const char *status = "disabled";
 | |
| 
 | |
| 	do {
 | |
| 		rc = fdt_setprop(blob, nodeoffset, "status", status,
 | |
| 				 strlen(status) + 1);
 | |
| 		if (rc) {
 | |
| 			if (rc == -FDT_ERR_NOSPACE) {
 | |
| 				ret = fdt_increase_size(blob, 512);
 | |
| 				if (ret)
 | |
| 					return ret;
 | |
| 			}
 | |
| 		}
 | |
| 	} while (rc == -FDT_ERR_NOSPACE);
 | |
| 
 | |
| 	return rc;
 | |
| }
 | |
| 
 | |
| static void update_fdt_with_owned_resources(void *blob)
 | |
| {
 | |
| 	/*
 | |
| 	 * Traverses the fdt nodes, check its power domain and use
 | |
| 	 * the resource id in the power domain for checking whether
 | |
| 	 * it is owned by current partition
 | |
| 	 */
 | |
| 	struct fdtdec_phandle_args args;
 | |
| 	int offset = 0, depth = 0;
 | |
| 	u32 rsrc_id;
 | |
| 	int rc, i;
 | |
| 
 | |
| 	for (offset = fdt_next_node(blob, offset, &depth); offset > 0;
 | |
| 	     offset = fdt_next_node(blob, offset, &depth)) {
 | |
| 		debug("Node name: %s, depth %d\n",
 | |
| 		      fdt_get_name(blob, offset, NULL), depth);
 | |
| 
 | |
| 		if (!fdt_get_property(blob, offset, "power-domains", NULL)) {
 | |
| 			debug("   - ignoring node %s\n",
 | |
| 			      fdt_get_name(blob, offset, NULL));
 | |
| 			continue;
 | |
| 		}
 | |
| 
 | |
| 		if (!fdtdec_get_is_enabled(blob, offset)) {
 | |
| 			debug("   - ignoring node %s\n",
 | |
| 			      fdt_get_name(blob, offset, NULL));
 | |
| 			continue;
 | |
| 		}
 | |
| 
 | |
| 		i = 0;
 | |
| 		while (true) {
 | |
| 			rc = fdtdec_parse_phandle_with_args(blob, offset,
 | |
| 							    "power-domains",
 | |
| 							    "#power-domain-cells",
 | |
| 							    0, i++, &args);
 | |
| 			if (rc == -ENOENT) {
 | |
| 				break;
 | |
| 			} else if (rc) {
 | |
| 				printf("Parse power-domains of %s wrong: %d\n",
 | |
| 				       fdt_get_name(blob, offset, NULL), rc);
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			rsrc_id = args.args[0];
 | |
| 
 | |
| 			if (!check_owned_resource(rsrc_id)) {
 | |
| 				rc = disable_fdt_node(blob, offset);
 | |
| 				if (!rc) {
 | |
| 					printf("Disable %s rsrc %u not owned\n",
 | |
| 					       fdt_get_name(blob, offset, NULL),
 | |
| 					       rsrc_id);
 | |
| 				} else {
 | |
| 					printf("Unable to disable %s, err=%s\n",
 | |
| 					       fdt_get_name(blob, offset, NULL),
 | |
| 					       fdt_strerror(rc));
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static int config_smmu_resource_sid(int rsrc, int sid)
 | |
| {
 | |
| 	int err;
 | |
| 
 | |
| 	err = sc_rm_set_master_sid(-1, rsrc, sid);
 | |
| 	debug("set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err);
 | |
| 	if (err != SC_ERR_NONE) {
 | |
| 		if (!check_owned_resource(rsrc)) {
 | |
| 			printf("%s rsrc[%d] not owned\n", __func__, rsrc);
 | |
| 			return -1;
 | |
| 		}
 | |
| 		pr_err("fail set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err);
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int config_smmu_fdt_device_sid(void *blob, int device_offset, int sid)
 | |
| {
 | |
| 	const char *name = fdt_get_name(blob, device_offset, NULL);
 | |
| 	struct fdtdec_phandle_args args;
 | |
| 	int rsrc, ret;
 | |
| 	int proplen;
 | |
| 	const fdt32_t *prop;
 | |
| 	int i;
 | |
| 
 | |
| 	prop = fdt_getprop(blob, device_offset, "fsl,sc_rsrc_id", &proplen);
 | |
| 	if (prop) {
 | |
| 		int i;
 | |
| 
 | |
| 		debug("configure node %s sid 0x%x for %d resources\n",
 | |
| 		      name, sid, (int)(proplen / sizeof(fdt32_t)));
 | |
| 		for (i = 0; i < proplen / sizeof(fdt32_t); ++i) {
 | |
| 			ret = config_smmu_resource_sid(fdt32_to_cpu(prop[i]),
 | |
| 						       sid);
 | |
| 			if (ret)
 | |
| 				return ret;
 | |
| 		}
 | |
| 
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	i = 0;
 | |
| 	while (true) {
 | |
| 		ret = fdtdec_parse_phandle_with_args(blob, device_offset,
 | |
| 						     "power-domains",
 | |
| 						     "#power-domain-cells",
 | |
| 						     0, i++, &args);
 | |
| 		if (ret == -ENOENT) {
 | |
| 			break;
 | |
| 		} else if (ret) {
 | |
| 			printf("Parse power-domains of node %s wrong: %d\n",
 | |
| 			       fdt_get_name(blob, device_offset, NULL), ret);
 | |
| 			continue;
 | |
| 		}
 | |
| 
 | |
| 		debug("configure node %s sid 0x%x rsrc=%d\n",
 | |
| 		      name, sid, rsrc);
 | |
| 		rsrc = args.args[0];
 | |
| 
 | |
| 		ret = config_smmu_resource_sid(rsrc, sid);
 | |
| 		if (ret)
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| static int config_smmu_fdt(void *blob)
 | |
| {
 | |
| 	int offset, proplen, i, ret;
 | |
| 	const fdt32_t *prop;
 | |
| 	const char *name;
 | |
| 
 | |
| 	/* Legacy smmu bindings, still used by xen. */
 | |
| 	offset = fdt_node_offset_by_compatible(blob, 0, "arm,mmu-500");
 | |
| 	prop = fdt_getprop(blob, offset, "mmu-masters", &proplen);
 | |
| 	if (offset > 0 && prop) {
 | |
| 		debug("found legacy mmu-masters property\n");
 | |
| 
 | |
| 		for (i = 0; i < proplen / 8; ++i) {
 | |
| 			u32 phandle = fdt32_to_cpu(prop[2 * i]);
 | |
| 			int sid = fdt32_to_cpu(prop[2 * i + 1]);
 | |
| 			int device_offset;
 | |
| 
 | |
| 			device_offset = fdt_node_offset_by_phandle(blob,
 | |
| 								   phandle);
 | |
| 			if (device_offset < 0) {
 | |
| 				pr_err("Not find device from mmu_masters: %d",
 | |
| 				       device_offset);
 | |
| 				continue;
 | |
| 			}
 | |
| 			ret = config_smmu_fdt_device_sid(blob, device_offset,
 | |
| 							 sid);
 | |
| 			if (ret)
 | |
| 				return ret;
 | |
| 		}
 | |
| 
 | |
| 		/* Ignore new bindings if old bindings found, just like linux. */
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	/* Generic smmu bindings */
 | |
| 	offset = 0;
 | |
| 	while ((offset = fdt_next_node(blob, offset, NULL)) > 0) {
 | |
| 		name = fdt_get_name(blob, offset, NULL);
 | |
| 		prop = fdt_getprop(blob, offset, "iommus", &proplen);
 | |
| 		if (!prop)
 | |
| 			continue;
 | |
| 		debug("node %s iommus proplen %d\n", name, proplen);
 | |
| 
 | |
| 		if (proplen == 12) {
 | |
| 			int sid = fdt32_to_cpu(prop[1]);
 | |
| 
 | |
| 			config_smmu_fdt_device_sid(blob, offset, sid);
 | |
| 		} else if (proplen != 4) {
 | |
| 			debug("node %s ignore unexpected iommus proplen=%d\n",
 | |
| 			      name, proplen);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int ft_add_optee_node(void *fdt, struct bd_info *bd)
 | |
| {
 | |
| 	const char *path, *subpath;
 | |
| 	int offs;
 | |
| 
 | |
| 	/*
 | |
| 	 * No TEE space allocated indicating no TEE running, so no
 | |
| 	 * need to add optee node in dts
 | |
| 	 */
 | |
| 	if (!boot_pointer[1])
 | |
| 		return 0;
 | |
| 
 | |
| 	offs = fdt_increase_size(fdt, 512);
 | |
| 	if (offs) {
 | |
| 		printf("No Space for dtb\n");
 | |
| 		return 1;
 | |
| 	}
 | |
| 
 | |
| 	path = "/firmware";
 | |
| 	offs = fdt_path_offset(fdt, path);
 | |
| 	if (offs < 0) {
 | |
| 		path = "/";
 | |
| 		offs = fdt_path_offset(fdt, path);
 | |
| 
 | |
| 		if (offs < 0) {
 | |
| 			printf("Could not find root node.\n");
 | |
| 			return offs;
 | |
| 		}
 | |
| 
 | |
| 		subpath = "firmware";
 | |
| 		offs = fdt_add_subnode(fdt, offs, subpath);
 | |
| 		if (offs < 0) {
 | |
| 			printf("Could not create %s node.\n", subpath);
 | |
| 			return offs;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	subpath = "optee";
 | |
| 	offs = fdt_add_subnode(fdt, offs, subpath);
 | |
| 	if (offs < 0) {
 | |
| 		printf("Could not create %s node.\n", subpath);
 | |
| 		return offs;
 | |
| 	}
 | |
| 
 | |
| 	fdt_setprop_string(fdt, offs, "compatible", "linaro,optee-tz");
 | |
| 	fdt_setprop_string(fdt, offs, "method", "smc");
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int ft_system_setup(void *blob, struct bd_info *bd)
 | |
| {
 | |
| 	int ret;
 | |
| 	int off;
 | |
| 
 | |
| 	if (CONFIG_BOOTAUX_RESERVED_MEM_BASE) {
 | |
| 		off = fdt_add_mem_rsv(blob, CONFIG_BOOTAUX_RESERVED_MEM_BASE,
 | |
| 				      CONFIG_BOOTAUX_RESERVED_MEM_SIZE);
 | |
| 		if (off < 0)
 | |
| 			printf("Failed	to reserve memory for bootaux: %s\n",
 | |
| 			       fdt_strerror(off));
 | |
| 	}
 | |
| 
 | |
| 	update_fdt_with_owned_resources(blob);
 | |
| 
 | |
| 	if (is_imx8qm()) {
 | |
| 		ret = config_smmu_fdt(blob);
 | |
| 		if (ret)
 | |
| 			return ret;
 | |
| 	}
 | |
| 
 | |
| 	return ft_add_optee_node(blob, bd);
 | |
| }
 |