コード例 #1
0
/**
 * Fix-up the kernel device tree so the bridge pd_n and rst_n gpios accurately
 * reflect the current board rev.
 */
static void ft_board_setup_gpios(void *blob, bd_t *bd)
{
	int ret, rev, np, len;
	const struct fdt_property *prop;

	/* Do nothing for newer boards */
	rev = board_get_revision();
	if (rev < 4 || rev == 6)
		return;

	/*
	 * If this is an older board, replace powerdown-gpio contents with that
	 * of reset-gpio and delete reset-gpio from the dt.
	 */
	np = fdtdec_next_compatible(blob, 0, COMPAT_NXP_PTN3460);
	if (np < 0) {
		debug("%s: Could not find COMPAT_NXP_PTN3460\n", __func__);
		return;
	}

	prop = fdt_get_property(blob, np, "reset-gpio", &len);
	if (!prop) {
		debug("%s: Could not get property err=%d\n", __func__, len);
		return;
	}

	ret = fdt_setprop_inplace(blob, np, "powerdown-gpio", prop->data,
			len);
	if (ret) {
		debug("%s: Could not setprop inplace err=%d\n", __func__, ret);
		return;
	}

	ret = fdt_delprop(blob, np, "reset-gpio");
	if (ret) {
		debug("%s: Could not delprop err=%d\n", __func__, ret);
		return;
	}
}
コード例 #2
0
ファイル: bootfdt.c プロジェクト: Chong-Li/xen
static void __init process_memory_node(const void *fdt, int node,
                                       const char *name,
                                       u32 address_cells, u32 size_cells)
{
    const struct fdt_property *prop;
    int i;
    int banks;
    const __be32 *cell;
    paddr_t start, size;
    u32 reg_cells = address_cells + size_cells;

    if ( address_cells < 1 || size_cells < 1 )
    {
        printk("fdt: node `%s': invalid #address-cells or #size-cells",
               name);
        return;
    }

    prop = fdt_get_property(fdt, node, "reg", NULL);
    if ( !prop )
    {
        printk("fdt: node `%s': missing `reg' property\n", name);
        return;
    }

    cell = (const __be32 *)prop->data;
    banks = fdt32_to_cpu(prop->len) / (reg_cells * sizeof (u32));

    for ( i = 0; i < banks && bootinfo.mem.nr_banks < NR_MEM_BANKS; i++ )
    {
        device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
        if ( !size )
            continue;
        bootinfo.mem.bank[bootinfo.mem.nr_banks].start = start;
        bootinfo.mem.bank[bootinfo.mem.nr_banks].size = size;
        bootinfo.mem.nr_banks++;
    }
}
コード例 #3
0
ファイル: fdt_support.c プロジェクト: DavionKnight/uboot-2000
void do_fixup_by_prop(void *fdt,
		      const char *pname, const void *pval, int plen,
		      const char *prop, const void *val, int len,
		      int create)
{
	int off;
#if defined(DEBUG)
	int i;
	debug("Updating property '%s' = ", prop);
	for (i = 0; i < len; i++)
		debug(" %.2x", *(u8*)(val+i));
	debug("\n");
#endif
	off = fdt_node_offset_by_prop_value(fdt, -1, pname, pval, plen);
	while (off != -FDT_ERR_NOTFOUND) {
		if (create || (fdt_get_property(fdt, off, prop, 0) != NULL))
		{	fdt_setprop(fdt, off, prop, val, len);
		//if( strcmp(pname, "cpu_type") == 0)
			printf("find node and set, %s", (char *)pname);
		}
		off = fdt_node_offset_by_prop_value(fdt, off, pname, pval, plen);
	}
}
コード例 #4
0
ファイル: devtree.c プロジェクト: cdaffara/symbian-oss_adapt
static QEMUDevice *find_interrupt_parent(QEMUDevice *dev)
{
    const struct fdt_property *p;
    QEMUDevice *parent;
    uint32_t phandle;
    int len;

    p = fdt_get_property(dev->dt, dev->node_offset, "interrupt-parent", &len);
    if (!p)
        return NULL;
    if (len != 4) {
        invalid_devtree(dev, "bad/missing interrupt-parent");
        return NULL;
    }
    phandle = fdt32_to_cpu(*(uint32_t *)p->data);

    parent = find_device_by_phandle(phandle);
    if (!parent) {
        invalid_devtree(dev, "interrupt-parent not found");
    }
    check_interrupt_cells(parent);
    return parent;
}
コード例 #5
0
ファイル: pmc.c プロジェクト: SunnyBrother/u-boot-at91
/**
 * at91_clk_sub_device_bind() - for the at91 clock driver
 * Recursively bind its children as clk devices.
 *
 * @return: 0 on success, or negative error code on failure
 */
int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name)
{
	const void *fdt = gd->fdt_blob;
	int offset = dev_of_offset(dev);
	bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC);
	const char *name;
	int ret;

	for (offset = fdt_first_subnode(fdt, offset);
	     offset > 0;
	     offset = fdt_next_subnode(fdt, offset)) {
		if (pre_reloc_only &&
		    !fdt_getprop(fdt, offset, "u-boot,dm-pre-reloc", NULL))
			continue;
		/*
		 * If this node has "compatible" property, this is not
		 * a clock sub-node, but a normal device. skip.
		 */
		fdt_get_property(fdt, offset, "compatible", &ret);
		if (ret >= 0)
			continue;

		if (ret != -FDT_ERR_NOTFOUND)
			return ret;

		name = fdt_get_name(fdt, offset, NULL);
		if (!name)
			return -EINVAL;
		ret = device_bind_driver_to_node(dev, drv_name, name,
						 offset, NULL);
		if (ret)
			return ret;
	}

	return 0;
}
コード例 #6
0
ファイル: fdtparse.c プロジェクト: machinaut/F4OS
int fdtparse_get_gpio(const void *fdt, int offset, const char *name,
                      struct fdt_gpio *gpio) {
    const struct fdt_property *prop;
    int len;
    fdt32_t *cell;

    prop = fdt_get_property(fdt, offset, name, &len);
    if (len < 0) {
        return len;
    }

    /* GPIO cells have 3 fields */
    if (len != 3*sizeof(uint32_t)) {
        return -FDT_ERR_BADLAYOUT;
    }

    cell = (fdt32_t *) prop->data;

    /* cell[0] is gpio path, cell[1] is number, cell[2] is flags */
    gpio->gpio = fdt32_to_cpu(cell[1]);
    gpio->flags = fdt32_to_cpu(cell[2]);

    return 0;
}
コード例 #7
0
ファイル: notfound.c プロジェクト: AjayMashi/x-tier
int main(int argc, char *argv[])
{
	const struct fdt_property *prop;
	void *fdt;
	int offset;
	int subnode1_offset;
	const void *val;
	int lenerr;

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

	prop = fdt_get_property(fdt, 0, "nonexistant-property", &lenerr);
	check_error("fdt_get_property(\"nonexistant-property\")", lenerr);

	val = fdt_getprop(fdt, 0, "nonexistant-property", &lenerr);
	check_error("fdt_getprop(\"nonexistant-property\"", lenerr);

	subnode1_offset = fdt_subnode_offset(fdt, 0, "subnode@1");
	if (subnode1_offset < 0)
		FAIL("Couldn't find subnode1: %s", fdt_strerror(subnode1_offset));

	val = fdt_getprop(fdt, subnode1_offset, "prop-str", &lenerr);
	check_error("fdt_getprop(\"prop-str\")", lenerr);

	offset = fdt_subnode_offset(fdt, 0, "nonexistant-subnode");
	check_error("fdt_subnode_offset(\"nonexistant-subnode\")", offset);

	offset = fdt_subnode_offset(fdt, 0, "subsubnode");
	check_error("fdt_subnode_offset(\"subsubnode\")", offset);

	offset = fdt_path_offset(fdt, "/nonexistant-subnode");
	check_error("fdt_path_offset(\"/nonexistant-subnode\")", offset);

	PASS();
}
コード例 #8
0
ファイル: uniphier-sd.c プロジェクト: eesuda/u-boot
static int uniphier_sd_probe(struct udevice *dev)
{
	struct uniphier_sd_priv *priv = dev_get_priv(dev);
	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
	fdt_addr_t base;
	struct clk clk;
	int ret;

	base = dev_get_addr(dev);
	if (base == FDT_ADDR_T_NONE)
		return -EINVAL;

	priv->regbase = devm_ioremap(dev, base, SZ_2K);
	if (!priv->regbase)
		return -ENOMEM;

	ret = clk_get_by_index(dev, 0, &clk);
	if (ret < 0) {
		dev_err(dev, "failed to get host clock\n");
		return ret;
	}

	/* set to max rate */
	priv->mclk = clk_set_rate(&clk, ULONG_MAX);
	if (IS_ERR_VALUE(priv->mclk)) {
		dev_err(dev, "failed to set rate for host clock\n");
		clk_free(&clk);
		return priv->mclk;
	}

	ret = clk_enable(&clk);
	clk_free(&clk);
	if (ret) {
		dev_err(dev, "failed to enable host clock\n");
		return ret;
	}

	priv->cfg.name = dev->name;
	priv->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;

	switch (fdtdec_get_int(gd->fdt_blob, dev->of_offset, "bus-width", 1)) {
	case 8:
		priv->cfg.host_caps |= MMC_MODE_8BIT;
		break;
	case 4:
		priv->cfg.host_caps |= MMC_MODE_4BIT;
		break;
	case 1:
		break;
	default:
		dev_err(dev, "Invalid \"bus-width\" value\n");
		return -EINVAL;
	}

	if (fdt_get_property(gd->fdt_blob, dev->of_offset, "non-removable",
			     NULL))
		priv->caps |= UNIPHIER_SD_CAP_NONREMOVABLE;

	priv->version = readl(priv->regbase + UNIPHIER_SD_VERSION) &
							UNIPHIER_SD_VERSION_IP;
	dev_dbg(dev, "version %x\n", priv->version);
	if (priv->version >= 0x10) {
		priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL;
		priv->caps |= UNIPHIER_SD_CAP_DIV1024;
	}

	uniphier_sd_host_init(priv);

	priv->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
	priv->cfg.f_min = priv->mclk /
			(priv->caps & UNIPHIER_SD_CAP_DIV1024 ? 1024 : 512);
	priv->cfg.f_max = priv->mclk;
	priv->cfg.b_max = U32_MAX; /* max value of UNIPHIER_SD_SECCNT */

	priv->mmc = mmc_create(&priv->cfg, priv);
	if (!priv->mmc)
		return -EIO;

	upriv->mmc = priv->mmc;
	priv->mmc->dev = dev;

	return 0;
}
コード例 #9
0
ファイル: arm_hdlcd.c プロジェクト: CrazyXen/XEN_CODE
void __init video_init(void)
{
    int node, depth;
    u32 address_cells, size_cells;
    struct lfb_prop lfbp;
    unsigned char *lfb;
    paddr_t hdlcd_start, hdlcd_size;
    paddr_t framebuffer_start, framebuffer_size;
    const struct fdt_property *prop;
    const u32 *cell;
    const char *mode_string;
    char _mode_string[16];
    int bytes_per_pixel = 4;
    struct color_masks *c = NULL;
    struct modeline *videomode = NULL;
    int i;

    if ( find_compatible_node("arm,hdlcd", &node, &depth,
                &address_cells, &size_cells) <= 0 )
        return;

    prop = fdt_get_property(device_tree_flattened, node, "reg", NULL);
    if ( !prop )
        return;

    cell = (const u32 *)prop->data;
    device_tree_get_reg(&cell, address_cells, size_cells,
            &hdlcd_start, &hdlcd_size);

    prop = fdt_get_property(device_tree_flattened, node, "framebuffer", NULL);
    if ( !prop )
        return;

    cell = (const u32 *)prop->data;
    device_tree_get_reg(&cell, address_cells, size_cells,
            &framebuffer_start, &framebuffer_size);

    if ( !hdlcd_start )
    {
        printk(KERN_ERR "HDLCD address missing from device tree, disabling driver\n");
        return;
    }

    if ( !hdlcd_start || !framebuffer_start )
    {
        printk(KERN_ERR "HDLCD: framebuffer address missing from device tree, disabling driver\n");
        return;
    }

    mode_string = fdt_getprop(device_tree_flattened, node, "mode", NULL);
    if ( !mode_string )
    {
        get_color_masks("32", &c);
        memcpy(_mode_string, "1280x1024@60", strlen("1280x1024@60") + 1);
        bytes_per_pixel = 4;
    }
    else if ( strlen(mode_string) < strlen("800x600@60") ||
            strlen(mode_string) > sizeof(_mode_string) - 1 )
    {
        printk(KERN_ERR "HDLCD: invalid modeline=%s\n", mode_string);
        return;
    } else {
        char *s = strchr(mode_string, '-');
        if ( !s )
        {
            printk(KERN_INFO "HDLCD: bpp not found in modeline %s, assume 32 bpp\n",
                    mode_string);
            get_color_masks("32", &c);
            memcpy(_mode_string, mode_string, strlen(mode_string) + 1);
            bytes_per_pixel = 4;
        } else {
            if ( strlen(s) < 6 )
            {
                printk(KERN_ERR "HDLCD: invalid mode %s\n", mode_string);
                return;
            }
            s++;
            if ( get_color_masks(s, &c) < 0 )
            {
                printk(KERN_WARNING "HDLCD: unsupported bpp %s\n", s);
                return;
            }
            bytes_per_pixel = simple_strtoll(s, NULL, 10) / 8;
        }
        i = s - mode_string - 1;
        memcpy(_mode_string, mode_string, i);
        memcpy(_mode_string + i, mode_string + i + 3, 4);
    }

    for ( i = 0; i < ARRAY_SIZE(videomodes); i++ ) {
        if ( !strcmp(_mode_string, videomodes[i].mode) )
        {
            videomode = &videomodes[i];
            break;
        }
    }
    if ( !videomode )
    {
        printk(KERN_WARNING "HDLCD: unsupported videomode %s\n", _mode_string);
        return;
    }

    if ( framebuffer_size < bytes_per_pixel * videomode->xres * videomode->yres )
    {
        printk(KERN_ERR "HDLCD: the framebuffer is too small, disabling the HDLCD driver\n");
        return;
    }

    printk(KERN_INFO "Initializing HDLCD driver\n");

    lfb = ioremap_wc(framebuffer_start, framebuffer_size);
    if ( !lfb )
    {
        printk(KERN_ERR "Couldn't map the framebuffer\n");
        return;
    }
    memset(lfb, 0x00, bytes_per_pixel * videomode->xres * videomode->yres);

    /* uses FIXMAP_MISC */
    set_pixclock(videomode->pixclock);

    set_fixmap(FIXMAP_MISC, hdlcd_start >> PAGE_SHIFT, DEV_SHARED);
    HDLCD[HDLCD_COMMAND] = 0;

    HDLCD[HDLCD_LINELENGTH] = videomode->xres * bytes_per_pixel;
    HDLCD[HDLCD_LINECOUNT] = videomode->yres - 1;
    HDLCD[HDLCD_LINEPITCH] = videomode->xres * bytes_per_pixel;
    HDLCD[HDLCD_PF] = ((bytes_per_pixel - 1) << 3);
    HDLCD[HDLCD_INTMASK] = 0;
    HDLCD[HDLCD_FBBASE] = framebuffer_start;
    HDLCD[HDLCD_BUS] = 0xf00 | (1 << 4);
    HDLCD[HDLCD_VBACK] = videomode->vback - 1;
    HDLCD[HDLCD_VSYNC] = videomode->vsync - 1;
    HDLCD[HDLCD_VDATA] = videomode->yres - 1;
    HDLCD[HDLCD_VFRONT] = videomode->vfront - 1;
    HDLCD[HDLCD_HBACK] = videomode->hback - 1;
    HDLCD[HDLCD_HSYNC] = videomode->hsync - 1;
    HDLCD[HDLCD_HDATA] = videomode->xres - 1;
    HDLCD[HDLCD_HFRONT] = videomode->hfront - 1;
    HDLCD[HDLCD_POLARITIES] = (1 << 2) | (1 << 3);
    HDLCD[HDLCD_RED] = (c->red_size << 8) | c->red_shift;
    HDLCD[HDLCD_GREEN] = (c->green_size << 8) | c->green_shift;
    HDLCD[HDLCD_BLUE] = (c->blue_size << 8) | c->blue_shift;
    HDLCD[HDLCD_COMMAND] = 1;
    clear_fixmap(FIXMAP_MISC);

    lfbp.pixel_on = (((1 << c->red_size) - 1) << c->red_shift) |
        (((1 << c->green_size) - 1) << c->green_shift) |
        (((1 << c->blue_size) - 1) << c->blue_shift);
    lfbp.lfb = lfb;
    lfbp.font = &font_vga_8x16;
    lfbp.bits_per_pixel = bytes_per_pixel*8;
    lfbp.bytes_per_line = bytes_per_pixel*videomode->xres;
    lfbp.width = videomode->xres;
    lfbp.height = videomode->yres;
    lfbp.flush = hdlcd_flush;
    lfbp.text_columns = videomode->xres / 8;
    lfbp.text_rows = videomode->yres / 16;
    if ( lfb_init(&lfbp) < 0 )
            return;
    video_puts = lfb_scroll_puts;
}
コード例 #10
0
ファイル: console.c プロジェクト: jforissier/optee_os
/*
 * Check if the /secure-chosen node in the DT contains an stdout-path value
 * for which we have a compatible driver. If so, switch the console to
 * this device.
 */
void configure_console_from_dt(unsigned long phys_fdt)
{
	const struct dt_driver *dt_drv;
	const struct serial_driver *sdrv;
	const struct fdt_property *prop;
	struct serial_chip *dev;
	char *stdout_data;
	const char *uart;
	const char *parms = NULL;
	void *fdt;
	int offs;
	char *p;

	if (!phys_fdt)
		return;
	fdt = phys_to_virt(phys_fdt, MEM_AREA_IO_NSEC);
	if (!fdt)
		panic();

	offs = fdt_path_offset(fdt, "/secure-chosen");
	if (offs < 0)
		return;
	prop = fdt_get_property(fdt, offs, "stdout-path", NULL);
	if (!prop) {
		/*
		 * /secure-chosen node present but no stdout-path property
		 * means we don't want any console output
		 */
		IMSG("Switching off console");
		register_serial_console(NULL);
		return;
	}

	stdout_data = strdup(prop->data);
	if (!stdout_data)
		return;
	p = strchr(stdout_data, ':');
	if (p) {
		*p = '\0';
		parms = p + 1;
	}

	/* stdout-path may refer to an alias */
	uart = fdt_get_alias(fdt, stdout_data);
	if (!uart) {
		/* Not an alias, assume we have a node path */
		uart = stdout_data;
	}
	offs = fdt_path_offset(fdt, uart);
	if (offs < 0)
		goto out;

	dt_drv = dt_find_compatible_driver(fdt, offs);
	if (!dt_drv)
		goto out;

	sdrv = (const struct serial_driver *)dt_drv->driver;
	if (!sdrv)
		goto out;
	dev = sdrv->dev_alloc();
	if (!dev)
		goto out;
	/*
	 * If the console is the same as the early console, dev_init() might
	 * clear pending data. Flush to avoid that.
	 */
	console_flush();
	if (sdrv->dev_init(dev, fdt, offs, parms) < 0) {
		sdrv->dev_free(dev);
		goto out;
	}

	IMSG("Switching console to device: %s", uart);
	register_serial_console(dev);
out:
	free(stdout_data);
}
コード例 #11
0
ファイル: fdt_generic_util.c プロジェクト: dearchap/mb-qemu
static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat)
{
    int err;
    qemu_irq irq;
    hwaddr base;
    int offset;
    DeviceState *dev;
    char *dev_type = NULL;
    int is_intc;
    int i;

    dev = fdt_create_qdev_from_compat(compat, &dev_type);
    if (!dev) {
        DB_PRINT("no match found for %s\n", compat);
        return 1;
    }
    /* FIXME: attach to the sysbus instead */
    object_property_add_child(container_get(qdev_get_machine(), "/unattached"),
                              qemu_fdt_get_node_name(fdti->fdt, node_path),
                              OBJECT(dev), NULL);

    fdt_init_set_opaque(fdti, node_path, dev);

    /* connect nic if appropriate */
    static int nics;
    if (object_property_find(OBJECT(dev), "mac", NULL)) {
        qdev_set_nic_properties(dev, &nd_table[nics]);
        if (nd_table[nics].instantiated) {
            DB_PRINT("NIC instantiated: %s\n", dev_type);
            nics++;
        }
    }

    offset = fdt_path_offset(fdti->fdt, node_path);
    for (offset = fdt_first_property_offset(fdti->fdt, offset);
            offset != -FDT_ERR_NOTFOUND;
            offset = fdt_next_property_offset(fdti->fdt, offset)) {
        const char *propname;
        int len;
        const void *val = fdt_getprop_by_offset(fdti->fdt, offset,
                                                    &propname, &len);

        propname = trim_vendor(propname);
        ObjectProperty *p = object_property_find(OBJECT(dev), propname, NULL);
        if (p) {
            DB_PRINT("matched property: %s of type %s, len %d\n",
                                            propname, p->type, len);
        }
        if (!p) {
            continue;
        }

        /* FIXME: handle generically using accessors and stuff */
        if (!strcmp(p->type, "uint8") || !strcmp(p->type, "uint16") ||
                !strcmp(p->type, "uint32") || !strcmp(p->type, "uint64")) {
            uint64_t offset = (!strcmp(propname, "reg")) ?
                              fdt_get_parent_base(node_path, fdti) : 0;
            object_property_set_int(OBJECT(dev), get_int_be(val, len) + offset,
                                    propname, &error_abort);
            DB_PRINT("set property %s to %#llx\n", propname,
                                            (long long unsigned int)get_int_be(val, len));
        } else if (!strcmp(p->type, "bool")) {
            object_property_set_bool(OBJECT(dev), !!get_int_be(val, len),
                        propname, &error_abort);
            DB_PRINT("set property %s to %#llx\n", propname,
                                            (long long unsigned int)get_int_be(val, len));
        } else if (!strncmp(p->type, "link", 4)) {
            char target_node_path[DT_PATH_LENGTH];
            DeviceState *linked_dev;

            if (qemu_fdt_get_node_by_phandle(fdti->fdt, target_node_path,
                                                get_int_be(val, len))) {
                abort();
            }
            while (!fdt_init_has_opaque(fdti, target_node_path)) {
                fdt_init_yield(fdti);
            }
            linked_dev = fdt_init_get_opaque(fdti, target_node_path);
            object_property_set_link(OBJECT(dev), OBJECT(linked_dev), propname,
                                        &error_abort);
        } else if (!strcmp(p->type, "string")) {
            object_property_set_str(OBJECT(dev), strndup(val, len), propname, &error_abort);
	}
    }

    qdev_init_nofail(dev);
    /* map slave attachment */
    base = qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg", 0, false, &error_abort);

    base += fdt_get_parent_base(node_path, fdti);
    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);

    {
        int len;
        fdt_get_property(fdti->fdt, fdt_path_offset(fdti->fdt, node_path),
                                "interrupt-controller", &len);
        is_intc = len >= 0;
        DB_PRINT("is interrupt controller: %c\n", is_intc ? 'y' : 'n');
    }
    /* connect irq */
    for (i = 0; ; ++i) {
        char irq_info[1024];
        irq = fdt_get_irq_info(fdti, node_path, i, &err, irq_info);
        /* INTCs inferr their top level, if no IRQ connection specified */
        if (err && is_intc) {
            irq = fdti->irq_base;
            sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
            fprintf(stderr, "FDT: (%s) connected top level irq %s\n", dev_type,
                        irq_info);
            break;
        }
        if (!err) {
            sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
            fprintf(stderr, "FDT: (%s) connected irq %s\n", dev_type, irq_info);
        } else {
            break;
        }
    }

    if (dev_type) {
        g_free(dev_type);
    }

    return 0;
}
コード例 #12
0
ファイル: fdt_support.c プロジェクト: OpenNoah/u-boot
void fdt_fixup_ethernet(void *fdt)
{
	int i = 0, j, prop;
	char *tmp, *end;
	char mac[16];
	const char *path;
	unsigned char mac_addr[ARP_HLEN];
	int offset;
#ifdef FDT_SEQ_MACADDR_FROM_ENV
	int nodeoff;
	const struct fdt_property *fdt_prop;
#endif

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

	/* Cycle through all aliases */
	for (prop = 0; ; prop++) {
		const char *name;

		/* FDT might have been edited, recompute the offset */
		offset = fdt_first_property_offset(fdt,
			fdt_path_offset(fdt, "/aliases"));
		/* Select property number 'prop' */
		for (j = 0; j < prop; j++)
			offset = fdt_next_property_offset(fdt, offset);

		if (offset < 0)
			break;

		path = fdt_getprop_by_offset(fdt, offset, &name, NULL);
		if (!strncmp(name, "ethernet", 8)) {
			/* Treat plain "ethernet" same as "ethernet0". */
			if (!strcmp(name, "ethernet")
#ifdef FDT_SEQ_MACADDR_FROM_ENV
			 || !strcmp(name, "ethernet0")
#endif
			)
				i = 0;
#ifndef FDT_SEQ_MACADDR_FROM_ENV
			else
				i = trailing_strtol(name);
#endif
			if (i != -1) {
				if (i == 0)
					strcpy(mac, "ethaddr");
				else
					sprintf(mac, "eth%daddr", i);
			} else {
				continue;
			}
#ifdef FDT_SEQ_MACADDR_FROM_ENV
			nodeoff = fdt_path_offset(fdt, path);
			fdt_prop = fdt_get_property(fdt, nodeoff, "status",
						    NULL);
			if (fdt_prop && !strcmp(fdt_prop->data, "disabled"))
				continue;
			i++;
#endif
			tmp = env_get(mac);
			if (!tmp)
				continue;

			for (j = 0; j < 6; j++) {
				mac_addr[j] = tmp ?
					      simple_strtoul(tmp, &end, 16) : 0;
				if (tmp)
					tmp = (*end) ? end + 1 : end;
			}

			do_fixup_by_path(fdt, path, "mac-address",
					 &mac_addr, 6, 0);
			do_fixup_by_path(fdt, path, "local-mac-address",
					 &mac_addr, 6, 1);
		}
	}
}
コード例 #13
0
static int sun4i_spi_parse_pins(struct udevice *dev)
{
	const void *fdt = gd->fdt_blob;
	const char *pin_name;
	const fdt32_t *list;
	u32 phandle;
	int drive, pull = 0, pin, i;
	int offset;
	int size;

	list = fdt_getprop(fdt, dev_of_offset(dev), "pinctrl-0", &size);
	if (!list) {
		printf("WARNING: sun4i_spi: cannot find pinctrl-0 node\n");
		return -EINVAL;
	}

	while (size) {
		phandle = fdt32_to_cpu(*list++);
		size -= sizeof(*list);

		offset = fdt_node_offset_by_phandle(fdt, phandle);
		if (offset < 0)
			return offset;

		drive = fdt_getprop_u32_default_node(fdt, offset, 0,
						     "drive-strength", 0);
		if (drive) {
			if (drive <= 10)
				drive = 0;
			else if (drive <= 20)
				drive = 1;
			else if (drive <= 30)
				drive = 2;
			else
				drive = 3;
		} else {
			drive = fdt_getprop_u32_default_node(fdt, offset, 0,
							     "allwinner,drive",
							      0);
			drive = min(drive, 3);
		}

		if (fdt_get_property(fdt, offset, "bias-disable", NULL))
			pull = 0;
		else if (fdt_get_property(fdt, offset, "bias-pull-up", NULL))
			pull = 1;
		else if (fdt_get_property(fdt, offset, "bias-pull-down", NULL))
			pull = 2;
		else
			pull = fdt_getprop_u32_default_node(fdt, offset, 0,
							    "allwinner,pull",
							     0);
		pull = min(pull, 2);

		for (i = 0; ; i++) {
			pin_name = fdt_stringlist_get(fdt, offset,
						      "pins", i, NULL);
			if (!pin_name) {
				pin_name = fdt_stringlist_get(fdt, offset,
							      "allwinner,pins",
							       i, NULL);
				if (!pin_name)
					break;
			}

			pin = name_to_gpio(pin_name);
			if (pin < 0)
				break;

			sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
			sunxi_gpio_set_drv(pin, drive);
			sunxi_gpio_set_pull(pin, pull);
		}
	}
	return 0;
}
コード例 #14
0
ファイル: devtree.c プロジェクト: cdaffara/symbian-oss_adapt
static void fixup_irqs(void)
{
    QEMUDevice *dev;
    QEMUDevice *parent;
    const struct fdt_property *prop;
    int len;
    int i;
    qemu_irq parent_irq;
    int is_qemu_irq = 0;
    uint32_t *data;

    for (dev = first_device; dev; dev = dev->next) {
        if (dev->dc->num_irqs) {
            parent = find_interrupt_parent(dev);
            if (!parent) {
                prop = fdt_get_property(dev->dt, dev->node_offset,
                                        "qemu,interrupts", &len);
                if (!prop) {
                    invalid_devtree(dev, "missing interrupt-parent");
                    continue;
                }
                if (len != dev->dc->num_irqs * 8) {
                    invalid_devtree(dev, "bad interrupts");
                    continue;
                }
                is_qemu_irq = 1;
            } else {
                prop = fdt_get_property(dev->dt, dev->node_offset,
                                        "interrupts", &len);
                if (!prop || len != dev->dc->num_irqs * 4) {
                    invalid_devtree(dev, "bad/missing interrupts");
                    continue;
                }
                is_qemu_irq = 0;
            }
            data = (uint32_t *)prop->data;
            /* FIXME: Need to handle interrupt remapping.  */
            for (i = 0; i < dev->dc->num_irqs; i++) {
                uint32_t parent_irq_num;
                if (is_qemu_irq) {
                    parent = find_device_by_phandle(fdt32_to_cpu(*data));
                    data++;
                    if (!parent) {
                        invalid_devtree(dev, "bad qemu,interrupts");
                    }
                    check_interrupt_cells(parent);
                }
                parent_irq_num = fdt32_to_cpu(*data);
                data++;
                if (parent_irq_num >= parent->irq_sink_count) {
                    invalid_devtree(dev, "bad interrupt number");
                    continue;
                }
                parent_irq = parent->irq_sink[parent_irq_num];
                dev->irq[i] = parent_irq;
                if (dev->irqp[i])
                    *(dev->irqp[i]) = parent_irq;
            }
        }
    }
}
コード例 #15
0
ファイル: timer.c プロジェクト: JamesHyunKim/F4OS
void am335x_dmtimer1ms_init_systick(void) {
    const void *fdt = fdtparse_get_blob();
    struct am335x_dmtimer_1ms *regs;
    int offset, len;
    fdt32_t *cell;
    const struct fdt_property *interrupts;
    uint32_t interrupt_num;
    uint32_t tldr_val;

    /* HACK: Simply use the first DMTimer 1ms */
    offset = fdt_node_offset_by_compatible(fdt, -1, AM335X_DMTIMER_1MS_COMPAT);
    if (offset < 0) {
        panic_print("DMTimer 1ms not found");
    }

    regs = fdtparse_get_addr32(fdt, offset, "regs");
    if (!regs) {
        panic_print("DMTimer 1ms registers not found");
    }

    /* Get interrupt number */
    interrupts = fdt_get_property(fdt, offset, "interrupts", &len);
    /* Make sure there is room for one interrupt */
    if (len < 0 || len < sizeof(fdt32_t)) {
        panic_print("Unable to get DMTimer 1ms interrupt number");
    }

    cell = (fdt32_t *) interrupts->data;
    /* There is a single interrupt */
    interrupt_num = fdt32_to_cpu(cell[0]);

    /* Select master oscillator as clock */
    if (clocks_set_param(fdt, offset, "ti,clock-select",
                         AM335X_DMTIMER_1MS_CLK_M_OSC)) {
        panic_print("Unable to set DMTimer 1ms clock source");
    }

    /* Enable module clock */
    if (clocks_enable(fdt, offset, "clocks")) {
        panic_print("Unable to enable DMTimer 1ms module clock");
    }

    if (!TIMER_CNT_PER_SYSTICK) {
        panic_print("Unable to achieve system tick frequency");
    }

    /*
     * We want TIMER_CNT_PER_SYSTICK timer counts between the
     * load value and overflow.
     */
    tldr_val = (1LL << 32) - TIMER_CNT_PER_SYSTICK;
    raw_mem_write(&regs->tldr, tldr_val);

    /* Force reload of counter */
    raw_mem_write(&regs->ttgr, 1);

    /* Enable overflow interrupt */
    raw_mem_set_bits(&regs->tier, AM335X_DMTIMER_TIER_OVF_IT_EN);

    /* Register and enable interrupt.  Pass registers to handler */
    if (am335x_interrupt_register(fdt, offset, interrupt_num,
                                  dmtimer1ms_systick_handler, regs)) {
        panic_print("Unable to register DMTimer 1ms interrupt");
    }

    if (am335x_interrupt_enable(fdt, offset, interrupt_num)) {
        panic_print("Unable to enable DMTimer 1ms interrupt");
    }

    /* Start timer free running */
    raw_mem_write(&regs->tclr, AM335X_DMTIMER_TCLR_ST |
                               AM335X_DMTIMER_TCLR_AR);
}
コード例 #16
0
ファイル: km_dts.c プロジェクト: khadas/u-boot
static int unifykey_item_dt_parse(const void* dt_addr,int nodeoffset,int id,char *item_path)
{
	struct key_item_t *temp_item=NULL;
	char *propdata;
	struct fdt_property *prop;
	int count;

	temp_item = unifykey_item + id;

	propdata = (char*)fdt_getprop(dt_addr, nodeoffset, "key-encrypt", NULL);
	if (propdata) {
		count = strlen(propdata);
        if ( count > KEY_UNIFY_TYPE_LEN_MAX ) {
			KM_ERR("key-encrypt [%s] too long\n", propdata);
			return __LINE__;
		}
		memcpy(temp_item->encType, propdata, count);
	}

	propdata = (char*)fdt_getprop(dt_addr, nodeoffset, "key-name",NULL);
	if (!propdata) {
		printf("%s get key-name fail,%s:%d\n",item_path,__func__,__LINE__);
        return __LINE__;
	}

	count = strlen(propdata);
	if (count >= KEY_UNIFY_NAME_LEN) {
        KM_ERR("key-name strlen (%d) > max(%d) at key_%d\n", count, KEY_UNIFY_NAME_LEN - 1, id);
        return __LINE__;
	}
    memcpy(temp_item->name, propdata, count);
    temp_item->name[count] = 0;

	propdata = (char*)fdt_getprop(dt_addr, nodeoffset, "key-device",NULL);
	if (!propdata) {
		KM_ERR("%s get key-device fail at key_%d\n",item_path, id);
        return __LINE__;
	}

    if (strcmp(propdata,UNIFYKEY_DEVICE_EFUSEKEY) == 0) {
        temp_item->dev = KEY_M_EFUSE_NORMAL;
    }
    else if(strcmp(propdata,UNIFYKEY_DEVICE_SECURESKEY) == 0){
        temp_item->dev = KEY_M_SECURE_KEY;
    }
    else if(strcmp(propdata,UNIFYKEY_DEVICE_NORMAL) == 0){
        temp_item->dev = KEY_M_NORAML_KEY;
    }
    else{
        KM_ERR("key-device %s is unknown at key_%d\n", propdata, id);
        return __LINE__;
    }

	propdata = (char*)fdt_getprop((const void *)dt_addr, nodeoffset, "key-type",NULL);
	if (!propdata) //prop 'key-type' not configured, default to raw except special names
    {
        strcpy(temp_item->keyType, "raw");
	}
    else
    {
        const int keyTypeLen = strlen(propdata);
        if (keyTypeLen > KEY_UNIFY_TYPE_LEN_MAX) {
            KM_ERR("key[%s]cfg key-type[%s] sz %d > max %d\n", temp_item->name, propdata, keyTypeLen, KEY_UNIFY_TYPE_LEN_MAX);
            return __LINE__;
        }
        strcpy(temp_item->keyType, propdata);
    }

#if 0
	propdata = (char*)fdt_getprop((const void *)dt_addr, nodeoffset, "key-dataformat",NULL);
	if (!propdata) {
		KM_ERR("%s get key-dataformat fail at key_%d\n",item_path, id);
        return __LINE__;
	}
#endif

	prop = (struct fdt_property*)fdt_get_property((const void *)dt_addr,nodeoffset,"key-permit",NULL) ;
	if (!prop) {
		KM_ERR("%s get key-permit fail at  key_%d\n",item_path, id);
        return __LINE__;
	}

    temp_item->permit = 0;
    const int propLen = prop->len > 512 ? strnlen(prop->data, 512) : prop->len;
    if (fdt_stringlist_contains(prop->data, propLen, UNIFYKEY_PERMIT_READ)) {
        temp_item->permit |= KEY_M_PERMIT_READ;
    }
    if (fdt_stringlist_contains(prop->data, propLen, UNIFYKEY_PERMIT_WRITE)) {
        temp_item->permit |= KEY_M_PERMIT_WRITE;
    }
    if (fdt_stringlist_contains(prop->data, propLen, UNIFYKEY_PERMIT_DEL)) {
        temp_item->permit |= KEY_M_PERMIT_DEL;
    }

	temp_item->id = id;

    KM_DBG("key[%02d] keyname %s, %d\n", id, temp_item->name, temp_item->dev);

	return 0;
}
コード例 #17
0
ファイル: psci-dt.c プロジェクト: danielschwierzeck/u-boot
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;
}
コード例 #18
0
ファイル: partial_goods.c プロジェクト: KortanZ/linux
void update_partial_goods_dtb_nodes(void *fdt)
{
	int i;
	int tbl_sz = sizeof(table) / sizeof(struct partial_goods);
	int parent_offset = 0;
	int subnode_offset = 0;
	int ret = 0;
	int prop_len = 0;
	uint32_t reg = readl(QFPROM_PTE_PART_ADDR);
	uint32_t prop_type = 0;
	struct subnode_list *subnode_lst = NULL;
	const struct fdt_property *prop = NULL;
	const char *replace_str = NULL;

	/*
	 * The PTE register bits 23 to 27 have the partial goods
	 * info, extract the partial goods value before using
	 */
	reg = (reg & 0x0f800000) >> 23;

	/* If none of the DTB needs update */
	if (!reg)
		return;

	ret = fdt_open_into(fdt, fdt, fdt_totalsize(fdt));
	if (ret != 0)
	{
		dprintf(CRITICAL, "Failed to move/resize dtb buffer: %d\n", ret);
		ASSERT(0);
	}

	for (i = 0; i < tbl_sz; i++)
	{
		if (reg == table[i].val)
		{
			/* Find the Parent node */
			ret = fdt_path_offset(fdt, table[i].parent_node);
			if (ret < 0)
			{
				dprintf(CRITICAL, "Failed to get parent node: %s\terrno:%d\n", table[i].parent_node, ret);
				ASSERT(0);
			}
			parent_offset = ret;

			/* Find the subnode */
			subnode_lst = table[i].subnode;

			while (subnode_lst->subnode)
			{
				ret = fdt_subnode_offset(fdt, parent_offset, subnode_lst->subnode);
				if (ret < 0)
				{
					dprintf(CRITICAL, "Failed to get subnode: %s\terrno:%d\n", subnode_lst->subnode, ret);
					ASSERT(0);
				}
				subnode_offset = ret;

				/* Find the property node and its length */
				prop = fdt_get_property(fdt, subnode_offset, subnode_lst->property, &prop_len);
				if (!prop)
				{
					dprintf(CRITICAL, "Failed to get property: %s\terrno: %d\n", subnode_lst->property, prop_len);
					ASSERT(0);
				}

				/*
				 * Replace the property value based on the property
				 * length and type
				 */
				if (!(strncmp(subnode_lst->property, "device_type", sizeof(subnode_lst->property))))
					prop_type = DEVICE_TYPE;
				else if ((!strncmp(subnode_lst->property, "status", sizeof(subnode_lst->property))))
					prop_type = STATUS_TYPE;
				else
				{
					dprintf(CRITICAL, "%s: Property type is not supported\n", subnode_lst->property);
					ASSERT(0);
				}

				switch (prop_type)
				{
					case DEVICE_TYPE:
						replace_str = "nak";
						break;
					case STATUS_TYPE:
						if (prop_len == sizeof("ok"))
							replace_str = "no";
						else if (prop_len == sizeof("okay"))
							replace_str = "dsbl";
						else
						{
							dprintf(CRITICAL, "Property value length: %u is invalid for property: %s\n", prop_len, subnode_lst->property);
							ASSERT(0);
						}
						break;
					default:
						/* Control would not come here, as this gets taken care while setting property type */
						break;
				};

				/* Replace the property with new value */
				ret = fdt_setprop_inplace(fdt, subnode_offset, subnode_lst->property, (const void *)replace_str, prop_len);
				if (!ret)
					dprintf(INFO, "Updated device tree property: %s @ %s node\n", subnode_lst->property, subnode_lst->subnode);
				else
				{
					dprintf(CRITICAL, "Failed to update property: %s: error no: %d\n", subnode_lst->property, ret);
					ASSERT(0);
				}

				subnode_lst++;
			}
		}
	}

	fdt_pack(fdt);
}
コード例 #19
0
ファイル: kernel_start.cpp プロジェクト: hioa-cs/IncludeOS
//__attribute__((no_sanitize("all")))
void kernel_start(uintptr_t magic, uintptr_t addrin)
{
  kprintf("Magic %zx addrin %zx\n",magic,addrin);

  __init_sanity_checks();

  cpu_print_current_el();
  //its a "RAM address 0"
  const struct fdt_property *prop;
  int addr_cells = 0, size_cells = 0;
  int proplen;

  //TODO find this somewhere ?.. although it is at memory 0x00
  uint64_t fdt_addr=0x40000000;
  char *fdt=(char*)fdt_addr;


  //OK so these get overidden in the for loop which should return a map of memory and not just a single one
  uint64_t addr = 0;
  uint64_t size = 0;

  //checks both magic and version
  if ( fdt_check_header(fdt) != 0 )
  {
    kprint("FDT Header check failed\r\n");
    return;
  }

  size_cells = fdt_size_cells(fdt,0);
  print_le_named32("size_cells :",(char *)&size_cells);
  addr_cells = fdt_address_cells(fdt, 0);//fdt32_ld((const fdt32_t *)prop->data);
  print_le_named32("addr_cells :",(char *)&addr_cells);

  const int mem_offset = fdt_path_offset(fdt, "/memory");
  if (mem_offset < 0)
    return;

  print_le_named32("mem_offset :",(char *)&mem_offset);

  prop = fdt_get_property(fdt, mem_offset, "reg", &proplen);
  int cellslen = (int)sizeof(uint32_t) * (addr_cells + size_cells);

  for (int i = 0; i < proplen / cellslen; ++i) {

  	for (int j = 0; j < addr_cells; ++j) {
  		int offset = (cellslen * i) + (sizeof(uint32_t) * j);

  		addr |= (uint64_t)fdt32_ld((const fdt32_t *)((char *)prop->data + offset)) <<
  			((addr_cells - j - 1) * 32);
  	}
  	for (int j = 0; j < size_cells; ++j) {
  		int offset = (cellslen * i) +
  			(sizeof(uint32_t) * (j + addr_cells));

  		size |= (uint64_t)fdt32_ld((const fdt32_t *)((char *)prop->data + offset)) <<
  			((size_cells - j - 1) * 32);
  	}
	}

  print_le_named64("RAM BASE :",(char *)&addr);
  print_le_named64("RAM SIZE :",(char *)&size);

  uint64_t mem_end=addr+size;

  extern char _end;
  uintptr_t free_mem_begin = reinterpret_cast<uintptr_t>(&_end);

    //ok now its sane
  free_mem_begin += _move_symbols(free_mem_begin);

  // Initialize .bss
  _init_bss();

  // Instantiate machine
  size_t memsize = mem_end - free_mem_begin;
  __machine = os::Machine::create((void*)free_mem_begin, memsize);

  _init_elf_parser();
  // Begin portable HAL initialization
  __machine->init();

  // Initialize system calls
  _init_syscalls();

  //probably not very sane!
  cpu_debug_enable();
  cpu_fiq_enable();
  cpu_irq_enable();
  cpu_serror_enable();

  aarch64::init_libc((uintptr_t)fdt_addr);

}