Example #1
0
static int dt_add_psci_node(void *fdt)
{
	int offs;

	if (fdt_path_offset(fdt, "/psci") >= 0) {
		DMSG("PSCI Device Tree node already exists!\n");
		return 0;
	}

	offs = fdt_path_offset(fdt, "/");
	if (offs < 0)
		return -1;
	offs = fdt_add_subnode(fdt, offs, "psci");
	if (offs < 0)
		return -1;
	if (append_psci_compatible(fdt, offs, "arm,psci-1.0"))
		return -1;
	if (append_psci_compatible(fdt, offs, "arm,psci-0.2"))
		return -1;
	if (append_psci_compatible(fdt, offs, "arm,psci"))
		return -1;
	if (fdt_setprop_string(fdt, offs, "method", "smc"))
		return -1;
	if (fdt_setprop_u32(fdt, offs, "cpu_suspend", PSCI_CPU_SUSPEND))
		return -1;
	if (fdt_setprop_u32(fdt, offs, "cpu_off", PSCI_CPU_OFF))
		return -1;
	if (fdt_setprop_u32(fdt, offs, "cpu_on", PSCI_CPU_ON))
		return -1;
	if (fdt_setprop_u32(fdt, offs, "sys_poweroff", PSCI_SYSTEM_OFF))
		return -1;
	if (fdt_setprop_u32(fdt, offs, "sys_reset", PSCI_SYSTEM_RESET))
		return -1;
	return 0;
}
/* Function to add the subsequent RAM partition info to the device tree. */
int dev_tree_add_mem_info(void *fdt, uint32_t offset, uint32_t addr, uint32_t size)
{
	static int mem_info_cnt = 0;
	int ret;

	if (!mem_info_cnt)
	{
		/* Replace any other reg prop in the memory node. */
		ret = fdt_setprop_u32(fdt, offset, "reg", addr);
		mem_info_cnt = 1;
	}
	else
	{
		/* Append the mem info to the reg prop for subsequent nodes.  */
		ret = fdt_appendprop_u32(fdt, offset, "reg", addr);
	}

	if (ret)
	{
		dprintf(CRITICAL, "Failed to add the memory information addr: %d\n",
				ret);
	}


	ret = fdt_appendprop_u32(fdt, offset, "reg", size);

	if (ret)
	{
		dprintf(CRITICAL, "Failed to add the memory information size: %d\n",
				ret);
	}

	return ret;
}
Example #3
0
static inline int fdt_setprop_uxx(void *fdt, int nodeoffset, const char *name,
				  uint64_t val, int is_u64)
{
	if (is_u64)
		return fdt_setprop_u64(fdt, nodeoffset, name, val);
	else
		return fdt_setprop_u32(fdt, nodeoffset, name, (uint32_t)val);
}
Example #4
0
static int ft_fixup_clocks(void *fdt, const char **names, u32 *rates, int num)
{
	int offs, node_offs, ret, i;
	uint32_t phandle;

	offs = fdt_path_offset(fdt, "/ocp/l4@4a000000/cm_core_aon@5000/clocks");
	if (offs < 0) {
		debug("Could not find cm_core_aon clocks node path offset : %s\n",
		      fdt_strerror(offs));
		return offs;
	}

	for (i = 0; i < num; i++) {
		node_offs = fdt_subnode_offset(fdt, offs, names[i]);
		if (node_offs < 0) {
			debug("Could not find clock sub-node %s: %s\n",
			      names[i], fdt_strerror(node_offs));
			return offs;
		}

		phandle = fdt_get_phandle(fdt, node_offs);
		if (!phandle) {
			debug("Could not find phandle for clock %s\n",
			      names[i]);
			return -1;
		}

		ret = fdt_setprop_u32(fdt, node_offs, "assigned-clocks",
				      phandle);
		if (ret < 0) {
			debug("Could not add assigned-clocks property to clock node %s: %s\n",
			      names[i], fdt_strerror(ret));
			return ret;
		}

		ret = fdt_setprop_u32(fdt, node_offs, "assigned-clock-rates",
				      rates[i]);
		if (ret < 0) {
			debug("Could not add assigned-clock-rates property to clock node %s: %s\n",
			      names[i], fdt_strerror(ret));
			return ret;
		}
	}

	return 0;
}
/**
 * cros_ec_write_state() - Write out our state to the state file
 *
 * The caller will ensure that there is a node ready for the state. The node
 * may already contain the old state, in which case it is overridden.
 *
 * @param blob: Device tree blob holding state
 * @param node: Node to write our state into
 */
static int cros_ec_write_state(void *blob, int node)
{
	struct ec_state *ec = g_state;

	/* We are guaranteed enough space to write basic properties */
	fdt_setprop_u32(blob, node, "current-image", ec->current_image);
	fdt_setprop(blob, node, "vbnv-context", ec->vbnv_context,
		    sizeof(ec->vbnv_context));
	return state_setprop(node, "flash-data", ec->flash_data,
			     ec->ec_config.flash.length);
}
Example #6
0
int fdt_record_loadable(void *blob, u32 index, const char *name,
			uintptr_t load_addr, u32 size, uintptr_t entry_point,
			const char *type, const char *os)
{
	int err, node;

	err = fdt_check_header(blob);
	if (err < 0) {
		printf("%s: %s\n", __func__, fdt_strerror(err));
		return err;
	}

	/* find or create "/fit-images" node */
	node = fdt_find_or_add_subnode(blob, 0, "fit-images");
	if (node < 0)
			return node;

	/* find or create "/fit-images/<name>" node */
	node = fdt_find_or_add_subnode(blob, node, name);
	if (node < 0)
		return node;

	/*
	 * We record these as 32bit entities, possibly truncating addresses.
	 * However, spl_fit.c is not 64bit safe either: i.e. we should not
	 * have an issue here.
	 */
	fdt_setprop_u32(blob, node, "load-addr", load_addr);
	if (entry_point != -1)
		fdt_setprop_u32(blob, node, "entry-point", entry_point);
	fdt_setprop_u32(blob, node, "size", size);
	if (type)
		fdt_setprop_string(blob, node, "type", type);
	if (os)
		fdt_setprop_string(blob, node, "os", os);

	return node;
}
Example #7
0
/*
 * This function updates the mmu-masters property on the SMMU
 * node as per the SMMU binding-- phandle and list of stream IDs
 * for each MMU master.
 */
void append_mmu_masters(void *blob, const char *smmu_path,
			const char *master_name, u32 *stream_ids, int count)
{
	u32 phandle;
	int smmu_nodeoffset;
	int master_nodeoffset;
	int i;

	/* get phandle of mmu master device */
	master_nodeoffset = fdt_path_offset(blob, master_name);
	if (master_nodeoffset < 0) {
		printf("\n%s: ERROR: master not found\n", __func__);
		return;
	}
	phandle = fdt_get_phandle(blob, master_nodeoffset);
	if (!phandle) { /* if master has no phandle, create one */
		phandle = fdt_create_phandle(blob, master_nodeoffset);
		if (!phandle) {
			printf("\n%s: ERROR: unable to create phandle\n",
			       __func__);
			return;
		}
	}

	/* append it to mmu-masters */
	smmu_nodeoffset = fdt_path_offset(blob, smmu_path);
	if (fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters",
			       phandle) < 0) {
		printf("\n%s: ERROR: unable to update SMMU node\n", __func__);
		return;
	}

	/* for each stream ID, append to mmu-masters */
	for (i = 0; i < count; i++) {
		fdt_appendprop_u32(blob, smmu_nodeoffset, "mmu-masters",
				   stream_ids[i]);
	}

	/* fix up #stream-id-cells with stream ID count */
	if (fdt_setprop_u32(blob, master_nodeoffset, "#stream-id-cells",
			    count) < 0)
		printf("\n%s: ERROR: unable to update #stream-id-cells\n",
		       __func__);
}
Example #8
0
int dev_tree_setprop_u32(void *fdt, char *node, const char *property, uint32_t value)
{
	int ret = 0;
	int offset;

	offset = fdt_path_offset(fdt, node);
	if (offset < 0) {
		dprintf(CRITICAL, "Could not found %s node.\n" , node);
		return offset;
	}

	ret = fdt_setprop_u32(fdt, offset, property, value);
	if (ret < 0) {
		dprintf(CRITICAL, "Could not set %d value to %s property in %s node.\n",
				value, property, node);
		return ret;
	}

	return ret;
}
/* Function to add the first RAM partition info to the device tree.
 * Note: The function replaces the reg property in the "/memory" node
 * with the addr and size provided.
 */
int dev_tree_add_first_mem_info(uint32_t *fdt, uint32_t offset, uint32_t addr, uint32_t size)
{
	int ret;

	ret = fdt_setprop_u32(fdt, offset, "reg", addr);

	if (ret)
	{
		dprintf(CRITICAL, "Failed to add the memory information addr: %d\n",
				ret);
	}


	ret = fdt_appendprop_u32(fdt, offset, "reg", size);

	if (ret)
	{
		dprintf(CRITICAL, "Failed to add the memory information size: %d\n",
				ret);
	}

	return ret;
}
Example #10
0
}

static int fdtloader_add_single_meminfo(meminfo_pdata_t *pdata, boot_uint64_t addr, boot_uint64_t size)
{
    int rc = 0;

    // set first addr
    if (!pdata->do_append) {
        if (pdata->addr_cell_size == 2) {
            rc = fdt_setprop_u32(pdata->fdt, pdata->memoffset, "reg", addr >> 32);
            if (rc) return -1;

            rc = fdt_appendprop_u32(pdata->fdt, pdata->memoffset, "reg", (boot_uint32_t)addr);
            if (rc) return -1;
        } else {
            rc = fdt_setprop_u32(pdata->fdt, pdata->memoffset, "reg", (boot_uint32_t)addr);
            if (rc) if (rc) return -1;
        }

        pdata->do_append = 1;
    }
    // append addr
    else {
        if (pdata->addr_cell_size == 2) {
            rc = fdt_appendprop_u32(pdata->fdt, pdata->memoffset, "reg", addr >> 32);
            if (rc) return -1;
        }

        rc = fdt_appendprop_u32(pdata->fdt, pdata->memoffset, "reg", (boot_uint32_t)addr);
        if (rc) return -1;
    }
Example #11
0
static __init int remove_gic(void *fdt)
{
	const unsigned int cpu_ehci_int = 2;
	const unsigned int cpu_uart_int = 4;
	const unsigned int cpu_eth_int = 6;
	int gic_off, cpu_off, uart_off, eth_off, ehci_off, err;
	uint32_t cfg, cpu_phandle;

	/* leave the GIC node intact if a GIC is present */
	cfg = __raw_readl((uint32_t *)SEAD_CONFIG);
	if (cfg & SEAD_CONFIG_GIC_PRESENT)
		return 0;

	gic_off = fdt_node_offset_by_compatible(fdt, -1, "mti,gic");
	if (gic_off < 0) {
		pr_err("unable to find DT GIC node: %d\n", gic_off);
		return gic_off;
	}

	err = fdt_nop_node(fdt, gic_off);
	if (err) {
		pr_err("unable to nop GIC node\n");
		return err;
	}

	cpu_off = fdt_node_offset_by_compatible(fdt, -1,
			"mti,cpu-interrupt-controller");
	if (cpu_off < 0) {
		pr_err("unable to find CPU intc node: %d\n", cpu_off);
		return cpu_off;
	}

	cpu_phandle = fdt_get_phandle(fdt, cpu_off);
	if (!cpu_phandle) {
		pr_err("unable to get CPU intc phandle\n");
		return -EINVAL;
	}

	uart_off = fdt_node_offset_by_compatible(fdt, -1, "ns16550a");
	while (uart_off >= 0) {
		err = fdt_setprop_u32(fdt, uart_off, "interrupt-parent",
				      cpu_phandle);
		if (err) {
			pr_warn("unable to set UART interrupt-parent: %d\n",
				err);
			return err;
		}

		err = fdt_setprop_u32(fdt, uart_off, "interrupts",
				      cpu_uart_int);
		if (err) {
			pr_err("unable to set UART interrupts property: %d\n",
			       err);
			return err;
		}

		uart_off = fdt_node_offset_by_compatible(fdt, uart_off,
							 "ns16550a");
	}
	if (uart_off != -FDT_ERR_NOTFOUND) {
		pr_err("error searching for UART DT node: %d\n", uart_off);
		return uart_off;
	}

	eth_off = fdt_node_offset_by_compatible(fdt, -1, "smsc,lan9115");
	if (eth_off < 0) {
		pr_err("unable to find ethernet DT node: %d\n", eth_off);
		return eth_off;
	}

	err = fdt_setprop_u32(fdt, eth_off, "interrupt-parent", cpu_phandle);
	if (err) {
		pr_err("unable to set ethernet interrupt-parent: %d\n", err);
		return err;
	}

	err = fdt_setprop_u32(fdt, eth_off, "interrupts", cpu_eth_int);
	if (err) {
		pr_err("unable to set ethernet interrupts property: %d\n", err);
		return err;
	}

	ehci_off = fdt_node_offset_by_compatible(fdt, -1, "generic-ehci");
	if (ehci_off < 0) {
		pr_err("unable to find EHCI DT node: %d\n", ehci_off);
		return ehci_off;
	}

	err = fdt_setprop_u32(fdt, ehci_off, "interrupt-parent", cpu_phandle);
	if (err) {
		pr_err("unable to set EHCI interrupt-parent: %d\n", err);
		return err;
	}

	err = fdt_setprop_u32(fdt, ehci_off, "interrupts", cpu_ehci_int);
	if (err) {
		pr_err("unable to set EHCI interrupts property: %d\n", err);
		return err;
	}

	return 0;
}
Example #12
0
int main(int argc, char *argv[])
{
	void *fdt;
	void *buf;
	const uint32_t *intp;
	const char *strp;
	int err;

	test_init(argc, argv);
	fdt = load_blob_arg(argc, argv);

	buf = xmalloc(SPACE);

	err = fdt_open_into(fdt, buf, SPACE);
	if (err)
		FAIL("fdt_open_into(): %s", fdt_strerror(err));

	fdt = buf;

	intp = check_getprop_cell(fdt, 0, "prop-int", TEST_VALUE_1);

	verbose_printf("Old int value was 0x%08x\n", *intp);
	err = fdt_setprop_string(fdt, 0, "prop-int", NEW_STRING);
	if (err)
		FAIL("Failed to set \"prop-int\" to \"%s\": %s",
		     NEW_STRING, fdt_strerror(err));

	strp = check_getprop_string(fdt, 0, "prop-int", NEW_STRING);
	verbose_printf("New value is \"%s\"\n", strp);

	strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1,
			     TEST_STRING_1);

	verbose_printf("Old string value was \"%s\"\n", strp);
	err = fdt_setprop(fdt, 0, "prop-str", NULL, 0);
	if (err)
		FAIL("Failed to empty \"prop-str\": %s",
		     fdt_strerror(err));

	check_getprop(fdt, 0, "prop-str", 0, NULL);

	err = fdt_setprop_u32(fdt, 0, "prop-u32", TEST_VALUE_2);
	if (err)
		FAIL("Failed to set \"prop-u32\" to 0x%08x: %s",
		     TEST_VALUE_2, fdt_strerror(err));
	check_getprop_cell(fdt, 0, "prop-u32", TEST_VALUE_2);

	err = fdt_setprop_cell(fdt, 0, "prop-cell", TEST_VALUE_2);
	if (err)
		FAIL("Failed to set \"prop-cell\" to 0x%08x: %s",
		     TEST_VALUE_2, fdt_strerror(err));
	check_getprop_cell(fdt, 0, "prop-cell", TEST_VALUE_2);

	err = fdt_setprop_u64(fdt, 0, "prop-u64", TEST_VALUE64_1);
	if (err)
		FAIL("Failed to set \"prop-u64\" to 0x%016llx: %s",
		     TEST_VALUE64_1, fdt_strerror(err));
	check_getprop_64(fdt, 0, "prop-u64", TEST_VALUE64_1);
	
	PASS();
}
/* Top level function that updates the device tree. */
int update_device_tree(void *fdt, const char *cmdline,
					   void *ramdisk, uint32_t ramdisk_size)
{
	int ret = 0;
	uint32_t offset;

	/* Check the device tree header */
	ret = fdt_check_header(fdt);
	if (ret)
	{
		dprintf(CRITICAL, "Invalid device tree header \n");
		return ret;
	}

	/* Add padding to make space for new nodes and properties. */
	ret = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + DTB_PAD_SIZE);
	if (ret!= 0)
	{
		dprintf(CRITICAL, "Failed to move/resize dtb buffer: %d\n", ret);
		return ret;
	}

	/* Get offset of the memory node */
	ret = fdt_path_offset(fdt, "/memory");
	if (ret < 0)
	{
		dprintf(CRITICAL, "Could not find memory node.\n");
		return ret;
	}

	offset = ret;

	ret = target_dev_tree_mem(fdt, offset);
	if(ret)
	{
		dprintf(CRITICAL, "ERROR: Cannot update memory node\n");
		return ret;
	}

	/* Get offset of the chosen node */
	ret = fdt_path_offset(fdt, "/chosen");
	if (ret < 0)
	{
		dprintf(CRITICAL, "Could not find chosen node.\n");
		return ret;
	}

	offset = ret;
	/* Adding the cmdline to the chosen node */
	ret = fdt_setprop_string(fdt, offset, (const char*)"bootargs", (const void*)cmdline);
	if (ret)
	{
		dprintf(CRITICAL, "ERROR: Cannot update chosen node [bootargs]\n");
		return ret;
	}

	/* Adding the initrd-start to the chosen node */
	ret = fdt_setprop_u32(fdt, offset, "linux,initrd-start", (uint32_t)ramdisk);
	if (ret)
	{
		dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-start]\n");
		return ret;
	}

	/* Adding the initrd-end to the chosen node */
	ret = fdt_setprop_u32(fdt, offset, "linux,initrd-end", ((uint32_t)ramdisk + ramdisk_size));
	if (ret)
	{
		dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-end]\n");
		return ret;
	}

	fdt_pack(fdt);

	return ret;
}
Example #14
0
int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
{
	BIGNUM *modulus, *r_squared;
	uint64_t exponent;
	uint32_t n0_inv;
	int parent, node;
	char name[100];
	int ret;
	int bits;
	RSA *rsa;

	debug("%s: Getting verification data\n", __func__);
	ret = rsa_get_pub_key(info->keydir, info->keyname, &rsa);
	if (ret)
		return ret;
	ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
	if (ret)
		return ret;
	bits = BN_num_bits(modulus);
	parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
	if (parent == -FDT_ERR_NOTFOUND) {
		parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
		if (parent < 0) {
			ret = parent;
			if (ret != -FDT_ERR_NOSPACE) {
				fprintf(stderr, "Couldn't create signature node: %s\n",
					fdt_strerror(parent));
			}
		}
	}
	if (ret)
		goto done;

	/* Either create or overwrite the named key node */
	snprintf(name, sizeof(name), "key-%s", info->keyname);
	node = fdt_subnode_offset(keydest, parent, name);
	if (node == -FDT_ERR_NOTFOUND) {
		node = fdt_add_subnode(keydest, parent, name);
		if (node < 0) {
			ret = node;
			if (ret != -FDT_ERR_NOSPACE) {
				fprintf(stderr, "Could not create key subnode: %s\n",
					fdt_strerror(node));
			}
		}
	} else if (node < 0) {
		fprintf(stderr, "Cannot select keys parent: %s\n",
			fdt_strerror(node));
		ret = node;
	}

	if (!ret) {
		ret = fdt_setprop_string(keydest, node, "key-name-hint",
				 info->keyname);
	}
	if (!ret)
		ret = fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
	if (!ret)
		ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
	if (!ret) {
		ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent);
	}
	if (!ret) {
		ret = fdt_add_bignum(keydest, node, "rsa,modulus", modulus,
				     bits);
	}
	if (!ret) {
		ret = fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared,
				     bits);
	}
	if (!ret) {
		ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
					 info->name);
	}
	if (!ret && info->require_keys) {
		ret = fdt_setprop_string(keydest, node, "required",
					 info->require_keys);
	}
done:
	BN_free(modulus);
	BN_free(r_squared);
	if (ret)
		return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;

	return 0;
}
Example #15
0
/* Top level function that updates the device tree. */
int update_device_tree(void *fdt, const char *cmdline,
					   void *ramdisk, uint32_t ramdisk_size)
{
	int ret = 0;
	uint32_t offset;

	/* Check the device tree header */
	ret = fdt_check_header(fdt);
	if (ret)
	{
		dprintf(CRITICAL, "Invalid device tree header \n");
		return ret;
	}

	/* Get offset of the memory node */
	ret = fdt_path_offset(fdt, "/memory");
	if (ret < 0)
	{
		dprintf(CRITICAL, "Could not find memory node.\n");
		return ret;
	}

	offset = ret;

	ret = target_dev_tree_mem(fdt, offset);
	if(ret)
	{
		dprintf(CRITICAL, "ERROR: Cannot update memory node\n");
		return ret;
	}

	/* Get offset of the chosen node */
	ret = fdt_path_offset(fdt, "/chosen");
	if (ret < 0)
	{
		dprintf(CRITICAL, "Could not find chosen node.\n");
		return ret;
	}

	offset = ret;
	/* Adding the cmdline to the chosen node */
	ret = fdt_setprop_string(fdt, offset, (const char*)"bootargs", (const void*)cmdline);
	if (ret)
	{
		dprintf(CRITICAL, "ERROR: Cannot update chosen node [bootargs]\n");
		return ret;
	}

	/* Adding the initrd-start to the chosen node */
	ret = fdt_setprop_u32(fdt, offset, "linux,initrd-start", (uint32_t)ramdisk);
	if (ret)
	{
		dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-start]\n");
		return ret;
	}

	/* Adding the initrd-end to the chosen node */
	ret = fdt_setprop_u32(fdt, offset, "linux,initrd-end", ((uint32_t)ramdisk + ramdisk_size));
	if (ret)
	{
		dprintf(CRITICAL, "ERROR: Cannot update chosen node [linux,initrd-end]\n");
		return ret;
	}

	fdt_pack(fdt);

	return ret;
}
Example #16
0
int fdt_psci(void *fdt)
{
#if defined(CONFIG_ARMV7_PSCI) || defined(CONFIG_ARMV8_PSCI) || \
	defined(CONFIG_SEC_FIRMWARE_ARMV8_PSCI)
	int nodeoff;
	unsigned int psci_ver = 0;
	int tmp;

	nodeoff = fdt_path_offset(fdt, "/cpus");
	if (nodeoff < 0) {
		printf("couldn't find /cpus\n");
		return nodeoff;
	}

	/* add 'enable-method = "psci"' to each cpu node */
	for (tmp = fdt_first_subnode(fdt, nodeoff);
	     tmp >= 0;
	     tmp = fdt_next_subnode(fdt, tmp)) {
		const struct fdt_property *prop;
		int len;

		prop = fdt_get_property(fdt, tmp, "device_type", &len);
		if (!prop)
			continue;
		if (len < 4)
			continue;
		if (strcmp(prop->data, "cpu"))
			continue;

		/*
		 * Not checking rv here, our approach is to skip over errors in
		 * individual cpu nodes, hopefully some of the nodes are
		 * processed correctly and those will boot
		 */
		fdt_setprop_string(fdt, tmp, "enable-method", "psci");
	}

	nodeoff = fdt_path_offset(fdt, "/psci");
	if (nodeoff >= 0)
		goto init_psci_node;

	nodeoff = fdt_path_offset(fdt, "/");
	if (nodeoff < 0)
		return nodeoff;

	nodeoff = fdt_add_subnode(fdt, nodeoff, "psci");
	if (nodeoff < 0)
		return nodeoff;

init_psci_node:
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
	psci_ver = sec_firmware_support_psci_version();
#elif defined(CONFIG_ARMV7_PSCI_1_0) || defined(CONFIG_ARMV8_PSCI)
	psci_ver = ARM_PSCI_VER_1_0;
#endif
	if (psci_ver >= ARM_PSCI_VER_1_0) {
		tmp = fdt_setprop_string(fdt, nodeoff,
				"compatible", "arm,psci-1.0");
		if (tmp)
			return tmp;
	}

	if (psci_ver >= ARM_PSCI_VER_0_2) {
		tmp = fdt_appendprop_string(fdt, nodeoff,
				"compatible", "arm,psci-0.2");
		if (tmp)
			return tmp;
	}

#ifndef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
	/*
	 * The Secure firmware framework isn't able to support PSCI version 0.1.
	 */
	if (psci_ver < ARM_PSCI_VER_0_2) {
		tmp = fdt_appendprop_string(fdt, nodeoff,
				"compatible", "arm,psci");
		if (tmp)
			return tmp;
		tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_suspend",
				ARM_PSCI_FN_CPU_SUSPEND);
		if (tmp)
			return tmp;
		tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_off",
				ARM_PSCI_FN_CPU_OFF);
		if (tmp)
			return tmp;
		tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_on",
				ARM_PSCI_FN_CPU_ON);
		if (tmp)
			return tmp;
		tmp = fdt_setprop_u32(fdt, nodeoff, "migrate",
				ARM_PSCI_FN_MIGRATE);
		if (tmp)
			return tmp;
	}
#endif

	tmp = fdt_setprop_string(fdt, nodeoff, "method", "smc");
	if (tmp)
		return tmp;

#endif
	return 0;
}