Exemplo n.º 1
0
/* Find the I2C buses selected by this mux */
static int i2c_mux_post_bind(struct udevice *mux)
{
	const void *blob = gd->fdt_blob;
	int ret;
	int offset;

	debug("%s: %s\n", __func__, mux->name);
	/*
	 * There is no compatible string in the sub-nodes, so we must manually
	 * bind these
	 */
	for (offset = fdt_first_subnode(blob, mux->of_offset);
	     offset > 0;
	     offset = fdt_next_subnode(blob, offset)) {
		struct udevice *dev;
		const char *name;

		name = fdt_get_name(blob, offset, NULL);
		ret = device_bind_driver_to_node(mux, "i2c_mux_bus_drv", name,
						 offset, &dev);
		debug("   - bind ret=%d, %s\n", ret, dev ? dev->name : NULL);
		if (ret)
			return ret;
	}

	return 0;
}
Exemplo n.º 2
0
static void parse_node(const char *dtb, int node,
		void (*mem_cb)(uint32_t addr, uint32_t length))
{
	int parent = node;
	node = fdt_first_subnode(dtb, node);
	while(node >= 0)
	{
		const void *dt;
		int plen;

		dt = fdt_getprop(dtb, node, "device_type", &plen);

#ifdef DEBUG_DTB
		const char *nn;
		nn = fdt_get_name(dtb, node, NULL);
		if(dt != NULL && nn != NULL)
		{
			printf("DTB: found device_type property for %s: %s\n", nn, (const char *)dt);
		}
		else if(nn != NULL)
			printf("DTB: found node %s\n", nn);
		else
			printf("DTB: unknown node\n");
#endif
		if(dt != NULL && !strcmp((const char *)dt, "memory"))
		{
			parse_reg(dtb, node, parent, mem_cb);
		}

		parse_node(dtb, node, mem_cb);
		
		node = fdt_next_subnode(dtb, node);
	}
}
Exemplo n.º 3
0
/* Get the value of a property of a package. */
static ssize_t
ofw_fdt_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
    size_t buflen)
{
	const void *prop;
	const char *name;
	int len, offset;

	offset = fdt_phandle_offset(package);
	if (offset < 0)
		return (-1);

	if (strcmp(propname, "name") == 0) {
		/* Emulate the 'name' property */
		name = fdt_get_name(fdtp, offset, &len);
		strncpy(buf, name, buflen);
		if (len + 1 > buflen)
			len = buflen;
		return (len + 1);
	}

	prop = fdt_getprop(fdtp, offset, propname, &len);
	if (prop == NULL)
		return (-1);

	if (len > buflen)
		len = buflen;
	bcopy(prop, buf, len);
	return (len);
}
Exemplo n.º 4
0
/*
 * process_usb_nodes() - Process a list of USB nodes, adding them to our list
 *			of USB ports.
 * @blob:	fdt blob
 * @node_list:	list of nodes to process (any <=0 are ignored)
 * @count:	number of nodes to process
 *
 * Return:	0 - ok, -1 - error
 */
static int process_usb_nodes(const void *blob, int node_list[], int count)
{
	struct fdt_usb config;
	int node, i;
	int clk_done = 0;

	port_count = 0;
	for (i = 0; i < count; i++) {
		if (port_count == USB_PORTS_MAX) {
			printf("tegrausb: Cannot register more than %d ports\n",
				USB_PORTS_MAX);
			return -1;
		}

		debug("USB %d: ", i);
		node = node_list[i];
		if (!node)
			continue;
		if (fdt_decode_usb(blob, node, &config)) {
			debug("Cannot decode USB node %s\n",
			      fdt_get_name(blob, node, NULL));
			return -1;
		}
		if (!clk_done) {
			config_clock(get_pll_timing());
			clk_done = 1;
		}
		config.initialized = 0;

		/* add new USB port to the list of available ports */
		port[port_count++] = config;
	}

	return 0;
}
Exemplo n.º 5
0
int state_setprop(int node, const char *prop_name, const void *data, int size)
{
	void *blob;
	int len;
	int ret;

	fdt_getprop(state->state_fdt, node, prop_name, &len);

	/* Add space for the new property, its name and some overhead */
	ret = state_ensure_space(size - len + strlen(prop_name) + 32);
	if (ret)
		return ret;

	/* This should succeed, barring a mutiny */
	blob = state->state_fdt;
	ret = fdt_setprop(blob, node, prop_name, data, size);
	if (ret) {
		printf("%s: Unable to set property '%s' in node '%s': %s\n",
		       __func__, prop_name, fdt_get_name(blob, node, NULL),
			fdt_strerror(ret));
		return -ENOSPC;
	}

	return 0;
}
Exemplo n.º 6
0
/* Get the length of a property of a package. */
static ssize_t
ofw_fdt_getproplen(ofw_t ofw, phandle_t package, const char *propname)
{
	const struct fdt_property *prop;
	int offset, len;

	offset = fdt_phandle_offset(package);
	if (offset < 0)
		return (-1);

	len = -1;
	prop = fdt_get_property(fdtp, offset, propname, &len);

	if (prop == NULL && strcmp(propname, "name") == 0) {
		/* Emulate the 'name' property */
		fdt_get_name(fdtp, offset, &len);
		return (len + 1);
	}

	if (prop == NULL && offset == fdt_path_offset(fdtp, "/chosen")) {
		if (strcmp(propname, "fdtbootcpu") == 0)
			return (sizeof(cell_t));
		if (strcmp(propname, "fdtmemreserv") == 0)
			return (sizeof(uint64_t)*2*fdt_num_mem_rsv(fdtp));
	}

	if (prop == NULL)
		return (-1);

	return (len);
}
Exemplo n.º 7
0
int dm_check_devices(struct dm_test_state *dms, int num_devices)
{
	struct udevice *dev;
	int ret;
	int i;

	/*
	 * Now check that the ping adds are what we expect. This is using the
	 * ping-add property in each node.
	 */
	for (i = 0; i < num_devices; i++) {
		uint32_t base;

		ret = uclass_get_device(UCLASS_TEST_FDT, i, &dev);
		ut_assert(!ret);

		/*
		 * Get the 'ping-expect' property, which tells us what the
		 * ping add should be. We don't use the platdata because we
		 * want to test the code that sets that up
		 * (testfdt_drv_probe()).
		 */
		base = fdtdec_get_addr(gd->fdt_blob, dev->of_offset,
				       "ping-expect");
		debug("dev=%d, base=%d: %s\n", i, base,
		      fdt_get_name(gd->fdt_blob, dev->of_offset, NULL));

		ut_assert(!dm_check_operations(dms, dev, base,
					       dev_get_priv(dev)));
	}

	return 0;
}
Exemplo n.º 8
0
int board_usb_init(const void *blob)
{
	struct fdt_usb config;
	unsigned osc_freq = clock_get_rate(CLOCK_ID_OSC);
	enum clock_osc_freq freq;
	int node_list[USB_PORTS_MAX];
	int node, count, i;

	/* Set up the USB clocks correctly based on our oscillator frequency */
	freq = clock_get_osc_freq();
	config_clock(usb_pll[freq]);

	/* count may return <0 on error */
	count = fdtdec_find_aliases_for_id(blob, "usb",
			COMPAT_NVIDIA_TEGRA20_USB, node_list, USB_PORTS_MAX);
	for (i = 0; i < count; i++) {
		debug("USB %d: ", i);
		node = node_list[i];
		if (!node)
			continue;
		if (fdt_decode_usb(blob, node, osc_freq, &config)) {
			debug("Cannot decode USB node %s\n",
			      fdt_get_name(blob, node, NULL));
			return -1;
		}

		if (add_port(&config, usb_pll[freq]))
			return -1;
		set_host_mode(&config);
	}
	port_current = -1;

	return 0;
}
Exemplo n.º 9
0
static int sopc_device_probe(FDTMachineInfo *fdti, const char *node_path, int pass, uint32_t offset)
{
    DevInfo **dev = &(devices[0]);

    while (*dev) {
        const char **compat = &((*dev)->compat[0]);
        while (*compat) {
            if (0 == fdt_node_check_compatible(fdti->fdt, fdt_path_offset(fdti->fdt, node_path), *compat)) {
                if (pass == (*dev)->pass) {
                    printf("Adding a device for node %s\n",
                           fdt_get_name(fdti->fdt, fdt_path_offset(fdti->fdt, node_path), NULL));

                    (*dev)->probe(fdti, node_path, offset);
                    return 0;
                }

                if (pass < (*dev)->pass) {
                    /* Probe again on the next pass */
                    return 1;
                }
            }

            compat++;
        }

        dev++;
    }

    return 0;
}
Exemplo n.º 10
0
static int
tegra_xusb_padctl_config_parse_dt(struct tegra_xusb_padctl *padctl,
				  struct tegra_xusb_padctl_config *config,
				  const void *fdt, int node)
{
	int subnode;

	config->name = fdt_get_name(fdt, node, NULL);

	fdt_for_each_subnode(subnode, fdt, node) {
		struct tegra_xusb_padctl_group *group;
		int err;

		group = &config->groups[config->num_groups];

		err = tegra_xusb_padctl_group_parse_dt(padctl, group, fdt,
						       subnode);
		if (err < 0) {
			error("failed to parse group %s", group->name);
			return err;
		}

		config->num_groups++;
	}

	return 0;
}
Exemplo n.º 11
0
static int _gpio_request_by_name_nodev(const void *blob, int node,
				       const char *list_name, int index,
				       struct gpio_desc *desc, int flags,
				       bool add_index)
{
	struct fdtdec_phandle_args args;
	int ret;

	desc->dev = NULL;
	desc->offset = 0;
	ret = fdtdec_parse_phandle_with_args(blob, node, list_name,
					     "#gpio-cells", 0, index, &args);
	if (ret) {
		debug("%s: fdtdec_parse_phandle_with_args failed\n", __func__);
		goto err;
	}

	ret = uclass_get_device_by_of_offset(UCLASS_GPIO, args.node,
					     &desc->dev);
	if (ret) {
		debug("%s: uclass_get_device_by_of_offset failed\n", __func__);
		goto err;
	}
	ret = gpio_find_and_xlate(desc, &args);
	if (ret) {
		debug("%s: gpio_find_and_xlate failed\n", __func__);
		goto err;
	}
	ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s",
			       fdt_get_name(blob, node, NULL),
			       list_name, index);
	if (ret) {
		debug("%s: dm_gpio_requestf failed\n", __func__);
		goto err;
	}
	ret = dm_gpio_set_dir_flags(desc, flags | desc->flags);
	if (ret) {
		debug("%s: dm_gpio_set_dir failed\n", __func__);
		goto err;
	}

	return 0;
err:
	debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n",
	      __func__, fdt_get_name(blob, node, NULL), list_name, index, ret);
	return ret;
}
Exemplo n.º 12
0
void platform_early_init(void)
{
    /* initialize the interrupt controller */
    arm_gic_init();

    arm_generic_timer_init(ARM_GENERIC_TIMER_PHYSICAL_INT, 0);

    uart_init_early();

    /* look for a flattened device tree just before the kernel */
    const void *fdt = (void *)KERNEL_BASE;
    int err = fdt_check_header(fdt);
    if (err >= 0) {
        /* walk the nodes, looking for 'memory' */
        int depth = 0;
        int offset = 0;
        for (;;) {
            offset = fdt_next_node(fdt, offset, &depth);
            if (offset < 0)
                break;

            /* get the name */
            const char *name = fdt_get_name(fdt, offset, NULL);
            if (!name)
                continue;

            /* look for the 'memory' property */
            if (strcmp(name, "memory") == 0) {
                int lenp;
                const void *prop_ptr = fdt_getprop(fdt, offset, "reg", &lenp);
                if (prop_ptr && lenp == 0x10) {
                    /* we're looking at a memory descriptor */
                    //uint64_t base = fdt64_to_cpu(*(uint64_t *)prop_ptr);
                    uint64_t len = fdt64_to_cpu(*((const uint64_t *)prop_ptr + 1));

                    /* trim size on certain platforms */
#if ARCH_ARM
                    if (len > 1024*1024*1024U) {
                        len = 1024*1024*1024; /* only use the first 1GB on ARM32 */
                        printf("trimming memory to 1GB\n");
                    }
#endif

                    /* set the size in the pmm arena */
                    arena.size = len;
                }
            }
        }
    }

    /* add the main memory arena */
    pmm_add_arena(&arena);

    /* reserve the first 64k of ram, which should be holding the fdt */
    struct list_node list = LIST_INITIAL_VALUE(list);
    pmm_alloc_range(MEMBASE, 0x10000 / PAGE_SIZE, &list);
}
Exemplo n.º 13
0
static void setup_axp803_rails(const void *fdt)
{
	int node;
	bool dc1sw = false;

	/* locate the PMIC DT node, bail out if not found */
	node = fdt_node_offset_by_compatible(fdt, -1, "x-powers,axp803");
	if (node == -FDT_ERR_NOTFOUND) {
		WARN("BL31: PMIC: No AXP803 DT node, skipping initial setup.\n");
		return;
	}

	if (fdt_getprop(fdt, node, "x-powers,drive-vbus-en", NULL)) {
		axp_clrbits(0x8f, BIT(4));
		axp_setbits(0x30, BIT(2));
		INFO("PMIC: AXP803: Enabling DRIVEVBUS\n");
	}

	/* descend into the "regulators" subnode */
	node = fdt_first_subnode(fdt, node);

	/* iterate over all regulators to find used ones */
	for (node = fdt_first_subnode(fdt, node);
	     node != -FDT_ERR_NOTFOUND;
	     node = fdt_next_subnode(fdt, node)) {
		struct axp_regulator *reg;
		const char *name;
		int length;

		/* We only care if it's always on or referenced. */
		if (!should_enable_regulator(fdt, node))
			continue;

		name = fdt_get_name(fdt, node, &length);
		for (reg = regulators; reg->dt_name; reg++) {
			if (!strncmp(name, reg->dt_name, length)) {
				setup_regulator(fdt, node, reg);
				break;
			}
		}

		if (!strncmp(name, "dc1sw", length)) {
			/* Delay DC1SW enablement to avoid overheating. */
			dc1sw = true;
			continue;
		}
	}
	/*
	 * If DLDO2 is enabled after DC1SW, the PMIC overheats and shuts
	 * down. So always enable DC1SW as the very last regulator.
	 */
	if (dc1sw) {
		INFO("PMIC: AXP803: Enabling DC1SW\n");
		axp_setbits(0x12, BIT(7));
	}
}
Exemplo n.º 14
0
void dump_fdt(const void *fdt)
{
	int err;

	dprintf("FDT @ %p:\n", fdt);

	if (!fdt)
		return;

	err = fdt_check_header(fdt);
	if (err) {
		dprintf("fdt error: %s\n", fdt_strerror(err));
		return;
	}

	dprintf("fdt_totalsize: %d\n", fdt_totalsize(fdt));
	dprintf("fdt_off_dt_struct: %d\n", fdt_off_dt_struct(fdt));
	dprintf("fdt_off_dt_strings: %d\n", fdt_off_dt_strings(fdt));
	dprintf("fdt_off_mem_rsvmap: %d\n", fdt_off_mem_rsvmap(fdt));
	dprintf("fdt_version: %d\n", fdt_version(fdt));
	dprintf("fdt_last_comp_version: %d\n", fdt_last_comp_version(fdt));
	dprintf("fdt_boot_cpuid_phys: %d\n", fdt_boot_cpuid_phys(fdt));
	dprintf("fdt_size_dt_strings: %d\n", fdt_size_dt_strings(fdt));
	dprintf("fdt_size_dt_struct: %d\n", fdt_size_dt_struct(fdt));

#ifdef FDT_DUMP_NODES
	dprintf("fdt tree:\n");

	int node = -1;
	int depth = 0;
	while ((node = fdt_next_node(fdt, node, &depth)) >= 0) {
		dprintf(DS"node at %d: '%s'\n", DA, node,
			fdt_get_name(fdt, node, NULL));
#ifdef FDT_DUMP_PROPS
		int prop, len;
		const struct fdt_property *property;
		prop = fdt_first_property_offset(fdt, node);
		while (prop >= 0) {
			property = fdt_get_property_by_offset(fdt, prop, &len);
			if (property == NULL) {
				dprintf("getting prop at %d: %s\n", prop, fdt_strerror(len));
				break;
			}
			dprintf(DS"  prop at %d: '%s', len %d\n", DA, prop,
				fdt_string(fdt, fdt32_to_cpu(property->nameoff)),
				fdt32_to_cpu(property->len));
#ifdef FDT_DUMP_PROP_VALUES
			dump_hex(property->data, fdt32_to_cpu(property->len), depth);
#endif
			prop = fdt_next_property_offset(fdt, prop);
		}
#endif
	}
#endif
}
Exemplo n.º 15
0
/* We currently assume a fixed address/size.  Enforce that here.  */
static void check_cells(const void *dt, int node, int address, int size)
{
    const struct fdt_property *p;
    int parent;
    int len;
    int n;

    parent = fdt_parent_offset(dt, node);
    if (node < 0) {
        fprintf(stderr, "missing parent node for %s\n",
                fdt_get_name(dt, node, NULL));
        exit(1);
    }
    p = fdt_get_property(dt, parent, "#address-cells", &len);
    if (!p || len != 4) {
        fprintf(stderr,
                "Invalid or missing #address-cells for %s\n",
                fdt_get_name(dt, node, NULL));
        exit(1);
    }
    n = fdt32_to_cpu(*(uint32_t *)p->data);
    if (n != address) {
        fprintf(stderr,
                "Incorrect #address-cells for %s (expected %d got %d)\n",
                fdt_get_name(dt, node, NULL), address, n);
        exit(1);
    }
    p = fdt_get_property(dt, parent, "#size-cells", &len);
    if (!p || len != 4) {
        fprintf(stderr,
                "Invalid or missing #size-cells for %s\n",
                fdt_get_name(dt, node, NULL));
        exit(1);
    }
    n = fdt32_to_cpu(*(uint32_t *)p->data);
    if (n != size) {
        fprintf(stderr,
                "Incorrect #size-cells for %s (expected %d got %d)\n",
                fdt_get_name(dt, node, NULL), size, n);
        exit(1);
    }
}
Exemplo n.º 16
0
/**
 * h_include() - Include handler function for fdt_find_regions()
 *
 * This function decides whether to include or exclude a node, property or
 * compatible string. The function is defined by fdt_find_regions().
 *
 * The algorithm is documented in the code - disp->invert is 0 for normal
 * operation, and 1 to invert the sense of all matches.
 *
 * See
 */
static int h_include(void *priv, const void *fdt, int offset, int type,
		     const char *data, int size)
{
	struct display_info *disp = priv;
	int inc, len;

	inc = check_type_include(priv, type, data, size);
	if (disp->include_root && type == FDT_IS_PROP && offset == 0 && inc)
		return 1;

	/*
	 * If the node name does not tell us anything, check the
	 * compatible string
	 */
	if (inc == -1 && type == FDT_IS_NODE) {
		debug("   - checking compatible2\n");
		data = fdt_getprop(fdt, offset, "compatible", &len);
		inc = check_type_include(priv, FDT_IS_COMPAT, data, len);
	}

	/* If we still have no idea, check for properties in the node */
	if (inc != 1 && type == FDT_IS_NODE &&
	    (disp->types_inc & FDT_NODE_HAS_PROP)) {
		debug("   - checking node '%s'\n",
		      fdt_get_name(fdt, offset, NULL));
		for (offset = fdt_first_property_offset(fdt, offset);
		     offset > 0 && inc != 1;
		     offset = fdt_next_property_offset(fdt, offset)) {
			const struct fdt_property *prop;
			const char *str;

			prop = fdt_get_property_by_offset(fdt, offset, NULL);
			if (!prop)
				continue;
			str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
			inc = check_type_include(priv, FDT_NODE_HAS_PROP, str,
						 strlen(str));
		}
		if (inc == -1)
			inc = 0;
	}

	switch (inc) {
	case 1:
		inc = !disp->invert;
		break;
	case 0:
		inc = disp->invert;
		break;
	}
	debug("   - returning %d\n", inc);

	return inc;
}
Exemplo n.º 17
0
static int copy_spd(struct pei_data *peid)
{
    const int gpio_vector[] = {41, 42, 43, 10, -1};
    int spd_index;
    const void *blob = gd->fdt_blob;
    int node, spd_node;
    int ret, i;

    for (i = 0; ; i++) {
        if (gpio_vector[i] == -1)
            break;
        ret = gpio_requestf(gpio_vector[i], "spd_id%d", i);
        if (ret) {
            debug("%s: Could not request gpio %d\n", __func__,
                  gpio_vector[i]);
            return ret;
        }
    }
    spd_index = gpio_get_values_as_int(gpio_vector);
    debug("spd index %d\n", spd_index);
    node = fdtdec_next_compatible(blob, 0, COMPAT_MEMORY_SPD);
    if (node < 0) {
        printf("SPD data not found.\n");
        return -ENOENT;
    }

    for (spd_node = fdt_first_subnode(blob, node);
            spd_node > 0;
            spd_node = fdt_next_subnode(blob, spd_node)) {
        const char *data;
        int len;

        if (fdtdec_get_int(blob, spd_node, "reg", -1) != spd_index)
            continue;
        data = fdt_getprop(blob, spd_node, "data", &len);
        if (len < sizeof(peid->spd_data[0])) {
            printf("Missing SPD data\n");
            return -EINVAL;
        }

        debug("Using SDRAM SPD data for '%s'\n",
              fdt_get_name(blob, spd_node, NULL));
        memcpy(peid->spd_data[0], data, sizeof(peid->spd_data[0]));
        break;
    }

    if (spd_node < 0) {
        printf("No SPD data found for index %d\n", spd_index);
        return -ENOENT;
    }

    return 0;
}
Exemplo n.º 18
0
static void prop_get_fdt(Object *obj, Visitor *v, void *opaque,
                        const char *name, Error **errp)
{
    sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
    int fdt_offset_next, fdt_offset, fdt_depth;
    void *fdt;

    if (!drc->fdt) {
        return;
    }

    fdt = drc->fdt;
    fdt_offset = drc->fdt_start_offset;
    fdt_depth = 0;

    do {
        const char *name = NULL;
        const struct fdt_property *prop = NULL;
        int prop_len = 0, name_len = 0;
        uint32_t tag;

        tag = fdt_next_tag(fdt, fdt_offset, &fdt_offset_next);
        switch (tag) {
        case FDT_BEGIN_NODE:
            fdt_depth++;
            name = fdt_get_name(fdt, fdt_offset, &name_len);
            visit_start_struct(v, NULL, NULL, name, 0, NULL);
            break;
        case FDT_END_NODE:
            /* shouldn't ever see an FDT_END_NODE before FDT_BEGIN_NODE */
            g_assert(fdt_depth > 0);
            visit_end_struct(v, NULL);
            fdt_depth--;
            break;
        case FDT_PROP: {
            int i;
            prop = fdt_get_property_by_offset(fdt, fdt_offset, &prop_len);
            name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
            visit_start_list(v, name, NULL);
            for (i = 0; i < prop_len; i++) {
                visit_type_uint8(v, (uint8_t *)&prop->data[i], NULL, NULL);

            }
            visit_end_list(v, NULL);
            break;
        }
        default:
            error_setg(&error_abort, "device FDT in unexpected state: %d", tag);
        }
        fdt_offset = fdt_offset_next;
    } while (fdt_depth != 0);
}
Exemplo n.º 19
0
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
{
	int pdepth = 0, p = 0;
	int offset, depth, namelen;
	const char *name;

	CHECK_HEADER(fdt);

	if (buflen < 2)
		return -FDT_ERR_NOSPACE;

	for (offset = 0, depth = 0;
	     (offset >= 0) && (offset <= nodeoffset);
	     offset = fdt_next_node(fdt, offset, &depth)) {
		if (pdepth < depth)
			continue; /* overflowed buffer */

		while (pdepth > depth) {
			do {
				p--;
			} while (buf[p-1] != '/');
			pdepth--;
		}

		name = fdt_get_name(fdt, offset, &namelen);
		if (!name)
			return namelen;
		if ((p + namelen + 1) <= buflen) {
			memcpy(buf + p, name, namelen);
			p += namelen;
			buf[p++] = '/';
			pdepth++;
		}

		if (offset == nodeoffset) {
			if (pdepth < (depth + 1))
				return -FDT_ERR_NOSPACE;

			if (p > 1) /* special case so that root path is "/", not "" */
				p--;
			buf[p] = '\0';
			return p;
		}
	}

	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
		return -FDT_ERR_BADOFFSET;
	else if (offset == -FDT_ERR_BADOFFSET)
		return -FDT_ERR_BADSTRUCTURE;

	return offset; /* error from fdt_next_node() */
}
Exemplo n.º 20
0
/* Add RAM.  */
static void create_ram(const void *dt)
{
    int node = -1;
    const struct fdt_property *p;
    int len;
    uint32_t base;
    uint32_t size;
    uint32_t *data;
    ram_addr_t offset;

    while (1) {
        node = fdt_node_offset_by_prop_value(dt, node, "device_type",
                                             "memory", 7);
        if (node < 0)
            break;


        check_cells(dt, node, 1, 1);
        p = fdt_get_property(dt, node, "reg", &len);
        if (!p || (len % 8) != 0) {
            fprintf(stderr, "bad memory section %s\n",
                    fdt_get_name(dt, node, NULL));
            exit(1);
        }
        data = (uint32_t *)p->data;
        while (len) {
            base = fdt32_to_cpu(data[0]);
            size = fdt32_to_cpu(data[1]);
            data += 2;
            len -= 8;
            /* Ignore zero size regions.  */
            if (size == 0)
                continue;
            offset = qemu_ram_alloc(size);
            cpu_register_physical_memory(base, size, offset | IO_MEM_RAM);

            devtree_ram_map_size++;
            devtree_ram_map = qemu_realloc(devtree_ram_map,
                devtree_ram_map_size * sizeof(devtree_ram_region));
            devtree_ram_map[devtree_ram_map_size - 1].base = base;
            devtree_ram_map[devtree_ram_map_size - 1].size = size;
        }
    }
    /* FIXME: Merge and sort memory map entries.  */
    /* Technically there's no reason we have to have RAM.  However in
       practice it indicates a busted machine description.  */
    if (!devtree_ram_map) {
        fprintf(stderr, "No memory regions found\n");
        exit(1);
    }
}
Exemplo n.º 21
0
static bool_t __init device_tree_node_matches(const void *fdt, int node,
                                              const char *match)
{
    const char *name;
    size_t match_len;

    name = fdt_get_name(fdt, node, NULL);
    match_len = strlen(match);

    /* Match both "match" and "match@..." patterns but not
       "match-foo". */
    return strncmp(name, match, match_len) == 0
        && (name[match_len] == '@' || name[match_len] == '\0');
}
Exemplo n.º 22
0
int i2c_chip_ofdata_to_platdata(const void *blob, int node,
				struct dm_i2c_chip *chip)
{
	chip->offset_len = 1;	/* default */
	chip->flags = 0;
	chip->chip_addr = fdtdec_get_int(gd->fdt_blob, node, "reg", -1);
	if (chip->chip_addr == -1) {
		debug("%s: I2C Node '%s' has no 'reg' property\n", __func__,
		      fdt_get_name(blob, node, NULL));
		return -EINVAL;
	}

	return 0;
}
Exemplo n.º 23
0
int cros_ec_decode_ec_flash(const void *blob, struct fdt_cros_ec *config)
{
	int flash_node, node;

	node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC);
	if (node < 0) {
		debug("Failed to find chrome-ec node'\n");
		return -1;
	}

	flash_node = fdt_subnode_offset(blob, node, "flash");
	if (flash_node < 0) {
		debug("Failed to find flash node\n");
		return -1;
	}

	if (fdtdec_read_fmap_entry(blob, flash_node, "flash",
				   &config->flash)) {
		debug("Failed to decode flash node in chrome-ec'\n");
		return -1;
	}

	config->flash_erase_value = fdtdec_get_int(blob, flash_node,
						    "erase-value", -1);
	for (node = fdt_first_subnode(blob, flash_node); node >= 0;
	     node = fdt_next_subnode(blob, node)) {
		const char *name = fdt_get_name(blob, node, NULL);
		enum ec_flash_region region;

		if (0 == strcmp(name, "ro")) {
			region = EC_FLASH_REGION_RO;
		} else if (0 == strcmp(name, "rw")) {
			region = EC_FLASH_REGION_RW;
		} else if (0 == strcmp(name, "wp-ro")) {
			region = EC_FLASH_REGION_WP_RO;
		} else {
			debug("Unknown EC flash region name '%s'\n", name);
			return -1;
		}

		if (fdtdec_read_fmap_entry(blob, node, "reg",
					   &config->region[region])) {
			debug("Failed to decode flash region in chrome-ec'\n");
			return -1;
		}
	}

	return 0;
}
Exemplo n.º 24
0
int lists_bind_fdt(struct udevice *parent, const void *blob, int offset)
{
	struct driver *driver = ll_entry_start(struct driver, driver);
	const int n_ents = ll_entry_count(struct driver, driver);
	struct driver *entry;
	struct udevice *dev;
	const char *name;
	int result = 0;
	int ret;

	dm_dbg("bind node %s\n", fdt_get_name(blob, offset, NULL));
	for (entry = driver; entry != driver + n_ents; entry++) {
		ret = driver_check_compatible(blob, offset, entry->of_match);
		if (ret == -ENOENT) {
			continue;
		} else if (ret == -ENODEV) {
			break;
		} else if (ret) {
			dm_warn("Device tree error at offset %d\n", offset);
			if (!result || ret != -ENOENT)
				result = ret;
			break;
		}

		name = fdt_get_name(blob, offset, NULL);
		dm_dbg("   - found match at '%s'\n", entry->name);
		ret = device_bind(parent, entry, name, NULL, offset, &dev);
		if (ret) {
			dm_warn("No match for driver '%s'\n", entry->name);
			if (!result || ret != -ENOENT)
				result = ret;
		}
	}

	return result;
}
Exemplo n.º 25
0
static int list_subnodes(const void *blob, int node)
{
	int nextoffset;		/*                              */
	uint32_t tag;		/*             */
	int level = 0;		/*                             */
	const char *pathp;
	int depth = 1;		/*                                */

	while (level >= 0) {
		tag = fdt_next_tag(blob, node, &nextoffset);
		switch (tag) {
		case FDT_BEGIN_NODE:
			pathp = fdt_get_name(blob, node, NULL);
			if (level <= depth) {
				if (pathp == NULL)
					pathp = "/* NULL pointer error */";
				if (*pathp == '\0')
					pathp = "/";	/*                  */
				if (level == 1)
					puts(pathp);
			}
			level++;
			if (level >= MAX_LEVEL) {
				printf("Nested too deep, aborting.\n");
				return 1;
			}
			break;
		case FDT_END_NODE:
			level--;
			if (level == 0)
				level = -1;		/*               */
			break;
		case FDT_END:
			return 1;
		case FDT_PROP:
			break;
		default:
			if (level <= depth)
				printf("Unknown tag 0x%08X\n", tag);
			return 1;
		}
		node = nextoffset;
	}
	return 0;
}
Exemplo n.º 26
0
/* Get the value of a property of a package. */
static ssize_t
ofw_fdt_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
    size_t buflen)
{
	const void *prop;
	const char *name;
	int len, offset;
	uint32_t cpuid;

	offset = fdt_phandle_offset(package);
	if (offset < 0)
		return (-1);

	prop = fdt_getprop(fdtp, offset, propname, &len);

	if (prop == NULL && strcmp(propname, "name") == 0) {
		/* Emulate the 'name' property */
		name = fdt_get_name(fdtp, offset, &len);
		strncpy(buf, name, buflen);
		if (len + 1 > buflen)
			len = buflen;
		return (len + 1);
	}

	if (prop == NULL && offset == fdt_path_offset(fdtp, "/chosen")) {
		if (strcmp(propname, "fdtbootcpu") == 0) {
			cpuid = cpu_to_fdt32(fdt_boot_cpuid_phys(fdtp));
			len = sizeof(cpuid);
			prop = &cpuid;
		}
		if (strcmp(propname, "fdtmemreserv") == 0) {
			prop = (char *)fdtp + fdt_off_mem_rsvmap(fdtp);
			len = sizeof(uint64_t)*2*fdt_num_mem_rsv(fdtp);
		}
	}

	if (prop == NULL)
		return (-1);

	if (len > buflen)
		len = buflen;
	bcopy(prop, buf, len);
	return (len);
}
Exemplo n.º 27
0
int fdtdec_get_alias_seq(const void *blob, const char *base, int offset,
			 int *seqp)
{
	int base_len = strlen(base);
	const char *find_name;
	int find_namelen;
	int prop_offset;
	int aliases;

	find_name = fdt_get_name(blob, offset, &find_namelen);
	debug("Looking for '%s' at %d, name %s\n", base, offset, find_name);

	aliases = fdt_path_offset(blob, "/aliases");
	for (prop_offset = fdt_first_property_offset(blob, aliases);
	     prop_offset > 0;
	     prop_offset = fdt_next_property_offset(blob, prop_offset)) {
		const char *prop;
		const char *name;
		const char *slash;
		const char *p;
		int len;

		prop = fdt_getprop_by_offset(blob, prop_offset, &name, &len);
		debug("   - %s, %s\n", name, prop);
		if (len < find_namelen || *prop != '/' || prop[len - 1] ||
		    strncmp(name, base, base_len))
			continue;

		slash = strrchr(prop, '/');
		if (strcmp(slash + 1, find_name))
			continue;
		for (p = name + strlen(name) - 1; p > name; p--) {
			if (!isdigit(*p)) {
				*seqp = simple_strtoul(p + 1, NULL, 10);
				debug("Found seq %d\n", *seqp);
				return 0;
			}
		}
	}

	debug("Not found\n");
	return -ENOENT;
}
Exemplo n.º 28
0
/***
 * sandbox_read_state_nodes() - Read state associated with a driver
 *
 * This looks through all compatible nodes and calls the read function on
 * each one, to read in the state.
 *
 * If nothing is found, it still calls the read function once, to set up a
 * single global state for that driver.
 *
 * @state: Sandbox state
 * @io: Method to use for reading state
 * @blob: FDT containing state
 * @return 0 if OK, -EINVAL if the read function returned failure
 */
int sandbox_read_state_nodes(struct sandbox_state *state,
                             struct sandbox_state_io *io, const void *blob)
{
    int count;
    int node;
    int ret;

    debug("   - read %s\n", io->name);
    if (!io->read)
        return 0;

    node = -1;
    count = 0;
    while (blob) {
        node = fdt_node_offset_by_compatible(blob, node, io->compat);
        if (node < 0)
            return 0;	/* No more */
        debug("   - read node '%s'\n", fdt_get_name(blob, node, NULL));
        ret = io->read(blob, node);
        if (ret) {
            printf("Unable to read state for '%s'\n", io->compat);
            return -EINVAL;
        }
        count++;
    }

    /*
     * If we got no saved state, call the read function once without a
     * node, to set up the global state.
     */
    if (count == 0) {
        debug("   - read global\n");
        ret = io->read(NULL, -1);
        if (ret) {
            printf("Unable to read global state for '%s'\n",
                   io->name);
            return -EINVAL;
        }
    }

    return 0;
}
Exemplo n.º 29
0
/**
 * We have a top-level GPIO device with no actual GPIOs. It has a child
 * device for each Exynos GPIO bank.
 */
static int gpio_exynos_bind(struct udevice *parent)
{
	struct exynos_gpio_platdata *plat = parent->platdata;
	struct s5p_gpio_bank *bank, *base;
	const void *blob = gd->fdt_blob;
	int node;

	/* If this is a child device, there is nothing to do here */
	if (plat)
		return 0;

	base = (struct s5p_gpio_bank *)fdtdec_get_addr(gd->fdt_blob,
						   parent->of_offset, "reg");
	for (node = fdt_first_subnode(blob, parent->of_offset), bank = base;
	     node > 0;
	     node = fdt_next_subnode(blob, node), bank++) {
		struct exynos_gpio_platdata *plat;
		struct udevice *dev;
		fdt_addr_t reg;
		int ret;

		if (!fdtdec_get_bool(blob, node, "gpio-controller"))
			continue;
		plat = calloc(1, sizeof(*plat));
		if (!plat)
			return -ENOMEM;
		reg = fdtdec_get_addr(blob, node, "reg");
		if (reg != FDT_ADDR_T_NONE)
			bank = (struct s5p_gpio_bank *)((ulong)base + reg);
		plat->bank = bank;
		plat->bank_name = fdt_get_name(blob, node, NULL);
		debug("dev at %p: %s\n", bank, plat->bank_name);

		ret = device_bind(parent, parent->driver,
					plat->bank_name, plat, -1, &dev);
		if (ret)
			return ret;
		dev->of_offset = node;
	}

	return 0;
}
Exemplo n.º 30
0
Arquivo: fdt.c Projeto: SonicFrog/OS
/**
 * of_scan_flat_dt - scan flattened tree blob and call callback on each.
 * @it: callback function
 * @data: context data pointer
 *
 * This function is used to scan the flattened device-tree, it is
 * used to extract the memory information at boot before we can
 * unflatten the tree
 */
int __init of_scan_flat_dt(int (*it)(unsigned long node,
				     const char *uname, int depth,
				     void *data),
			   void *data)
{
	const void *blob = initial_boot_params;
	const char *pathp;
	int offset, rc = 0, depth = -1;

        for (offset = fdt_next_node(blob, -1, &depth);
             offset >= 0 && depth >= 0 && !rc;
             offset = fdt_next_node(blob, offset, &depth)) {

		pathp = fdt_get_name(blob, offset, NULL);
		if (*pathp == '/')
			pathp = kbasename(pathp);
		rc = it(offset, pathp, depth, data);
	}
	return rc;
}