コード例 #1
0
ファイル: pwm.c プロジェクト: Adrizcorp/ARM_SOC_FPGA
int pwm_request(const void *blob, int node, const char *prop_name)
{
	int pwm_node;
	u32 data[3];

	if (fdtdec_get_int_array(blob, node, prop_name, data,
			ARRAY_SIZE(data))) {
		debug("%s: Cannot decode PWM property '%s'\n", __func__,
		      prop_name);
		return -1;
	}

	pwm_node = fdt_node_offset_by_phandle(blob, data[0]);
	if (pwm_node != local.pwm_node) {
		debug("%s: PWM property '%s' phandle %d not recognised"
		      "- expecting %d\n", __func__, prop_name, data[0],
		      local.pwm_node);
		return -1;
	}
	if (data[1] >= PWM_NUM_CHANNELS) {
		debug("%s: PWM property '%s': invalid channel %u\n", __func__,
		      prop_name, data[1]);
		return -1;
	}

	/*
	 * TODO: We could maintain a list of requests, but it might not be
	 * worth it for U-Boot.
	 */
	return data[1];
}
コード例 #2
0
ファイル: fdtparse.c プロジェクト: JamesHyunKim/F4OS
int fdtparse_get_interrupt_parent(const void *fdt, int nodeoffset) {
    int len;
    const struct fdt_property *interrupt_parent;
    fdt32_t *cell;
    uint32_t parent_phandle;
    int parent_offset;

    /* Use "interrupt-parent" from node, or node's parent */
    do {
        interrupt_parent = fdt_get_property(fdt, nodeoffset,
                                            "interrupt-parent", &len);
    } while ((len < 0) &&
             (nodeoffset = fdt_parent_offset(fdt, nodeoffset)) >= 0);

    if (len < 0) {
        return len;
    }

    /* Cell must be big enough to hold phandle */
    if (len < sizeof(fdt32_t)) {
        return -FDT_ERR_BADPHANDLE;
    }

    cell = (fdt32_t *) interrupt_parent->data;
    parent_phandle = fdt32_to_cpu(cell[0]);
    parent_offset = fdt_node_offset_by_phandle(fdt, parent_phandle);
    if (parent_offset < 0) {
        return parent_offset;
    }

    return parent_offset;
}
コード例 #3
0
static int mvneta_probe(struct udevice *dev)
{
	struct eth_pdata *pdata = dev_get_platdata(dev);
	struct mvneta_port *pp = dev_get_priv(dev);
	void *blob = (void *)gd->fdt_blob;
	int node = dev->of_offset;
	struct mii_dev *bus;
	unsigned long addr;
	void *bd_space;

	/*
	 * Allocate buffer area for descs and rx_buffers. This is only
	 * done once for all interfaces. As only one interface can
	 * be active. Make this area DMA save by disabling the D-cache
	 */
	if (!buffer_loc.tx_descs) {
		/* Align buffer area for descs and rx_buffers to 1MiB */
		bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);
		mmu_set_region_dcache_behaviour((phys_addr_t)bd_space, BD_SPACE,
						DCACHE_OFF);
		buffer_loc.tx_descs = (struct mvneta_tx_desc *)bd_space;
		buffer_loc.rx_descs = (struct mvneta_rx_desc *)
			((phys_addr_t)bd_space +
			 MVNETA_MAX_TXD * sizeof(struct mvneta_tx_desc));
		buffer_loc.rx_buffers = (phys_addr_t)
			(bd_space +
			 MVNETA_MAX_TXD * sizeof(struct mvneta_tx_desc) +
			 MVNETA_MAX_RXD * sizeof(struct mvneta_rx_desc));
	}

	pp->base = (void __iomem *)pdata->iobase;

	/* Configure MBUS address windows */
	if (of_device_is_compatible(dev, "marvell,armada-3700-neta"))
		mvneta_bypass_mbus_windows(pp);
	else
		mvneta_conf_mbus_windows(pp);

	/* PHY interface is already decoded in mvneta_ofdata_to_platdata() */
	pp->phy_interface = pdata->phy_interface;

	/* Now read phyaddr from DT */
	addr = fdtdec_get_int(blob, node, "phy", 0);
	addr = fdt_node_offset_by_phandle(blob, addr);
	pp->phyaddr = fdtdec_get_int(blob, addr, "reg", 0);

	bus = mdio_alloc();
	if (!bus) {
		printf("Failed to allocate MDIO bus\n");
		return -ENOMEM;
	}

	bus->read = mvneta_mdio_read;
	bus->write = mvneta_mdio_write;
	snprintf(bus->name, sizeof(bus->name), dev->name);
	bus->priv = (void *)pp;
	pp->bus = bus;

	return mdio_register(bus);
}
コード例 #4
0
ファイル: pinctrl_rk3288.c プロジェクト: ahedlund/u-boot-xlnx
static int rk3288_pinctrl_set_state(struct udevice *dev, struct udevice *config)
{
	const void *blob = gd->fdt_blob;
	int pcfg_node, ret, flags, count, i;
	u32 cell[60], *ptr;

	debug("%s: %s %s\n", __func__, dev->name, config->name);
	ret = fdtdec_get_int_array_count(blob, config->of_offset,
					 "rockchip,pins", cell,
					 ARRAY_SIZE(cell));
	if (ret < 0) {
		debug("%s: bad array %d\n", __func__, ret);
		return -EINVAL;
	}
	count = ret;
	for (i = 0, ptr = cell; i < count; i += 4, ptr += 4) {
		pcfg_node = fdt_node_offset_by_phandle(blob, ptr[3]);
		if (pcfg_node < 0)
			return -EINVAL;
		flags = pinctrl_decode_pin_config(blob, pcfg_node);
		if (flags < 0)
			return flags;

		ret = rk3288_pinctrl_set_pins(dev, ptr[0], ptr[1], ptr[2],
					      flags);
		if (ret)
			return ret;
	}

	return 0;
}
コード例 #5
0
void fsl_sgmii_riser_fdt_fixup(void *fdt)
{
	struct eth_device *dev;
	int node;
	int i = -1;
	int etsec_num = 0;

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

	while ((dev = eth_get_dev_by_index(++i)) != NULL) {
		struct tsec_private *priv;
		int enet_node;
		char enet[16];
		const u32 *phyh;
		int phynode;
		const char *model;
		const char *path;

		if (!strstr(dev->name, "eTSEC"))
			continue;

		sprintf(enet, "ethernet%d", etsec_num++);
		path = fdt_getprop(fdt, node, enet, NULL);
		if (!path) {
			debug("No alias for %s\n", enet);
			continue;
		}

		enet_node = fdt_path_offset(fdt, path);
		if (enet_node < 0)
			continue;

		model = fdt_getprop(fdt, enet_node, "model", NULL);

		/*
		 * We only want to do this to eTSECs.  On some platforms
		 * there are more than one type of gianfar-style ethernet
		 * controller, and as we are creating an implicit connection
		 * between ethernet nodes and eTSEC devices, it is best to
		 * make the connection use as much explicit information
		 * as exists.
		 */
		if (!strstr(model, "TSEC"))
			continue;

		phyh = fdt_getprop(fdt, enet_node, "phy-handle", NULL);
		if (!phyh)
			continue;

		phynode = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*phyh));

		priv = dev->priv;

		if (priv->flags & TSEC_SGMII)
			fdt_setprop_cell(fdt, phynode, "reg", priv->phyaddr);
	}
}
コード例 #6
0
static void check_search(void *fdt, uint32_t phandle, int target)
{
	int offset;

	offset = fdt_node_offset_by_phandle(fdt, phandle);

	if (offset != target)
		FAIL("fdt_node_offset_by_phandle(0x%x) returns %d "
		     "instead of %d", phandle, offset, target);
}
コード例 #7
0
ファイル: fdt_decode.c プロジェクト: sncn-private/u-boot-t30
/**
 * Look up a phandle and follow it to its node. Then return the offset
 * of that node.
 *
 * @param blob		FDT blob
 * @param node		node to examine
 * @param prop_name	name of property to find
 * @return node offset if found, -ve error code on error
 */
static int lookup_phandle(const void *blob, int node, const char *prop_name)
{
	const u32 *phandle;
	int lookup;

	phandle = fdt_getprop(blob, node, prop_name, NULL);
	if (!phandle)
		return -FDT_ERR_NOTFOUND;

	lookup = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*phandle));
	return lookup;
}
コード例 #8
0
ファイル: cds_pci_ft.c プロジェクト: 01hyang/u-boot
static void cds_pci_fixup(void *blob)
{
	int node;
	const char *path;
	int len, slot, i;
	u32 *map = NULL, *piccells = NULL;
	int off, cells;

	node = fdt_path_offset(blob, "/aliases");
	if (node >= 0) {
		path = fdt_getprop(blob, node, "pci0", NULL);
		if (path) {
			node = fdt_path_offset(blob, path);
			if (node >= 0) {
				map = fdt_getprop_w(blob, node, "interrupt-map", &len);
			}
			/* Each item in "interrupt-map" property is translated with
			 * following cells:
			 * PCI #address-cells, PCI #interrupt-cells,
			 * PIC address, PIC #address-cells, PIC #interrupt-cells.
			 */
			cells = fdt_getprop_u32_default(blob, path, "#address-cells", 1);
			cells += fdt_getprop_u32_default(blob, path, "#interrupt-cells", 1);
			off = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*(map+cells)));
			if (off <= 0)
				return;
			cells += 1;
			piccells = (u32 *)fdt_getprop(blob, off, "#address-cells", NULL);
			if (piccells == NULL)
				return;
			cells += *piccells;
			piccells = (u32 *)fdt_getprop(blob, off, "#interrupt-cells", NULL);
			if (piccells == NULL)
				return;
			cells += *piccells;
		}
	}

	if (map) {
		len /= sizeof(u32);

		slot = get_pci_slot();

		for (i=0;i<len;i+=cells) {
			/* We rotate the interrupt pins so that the mapping
			 * changes depending on the slot the carrier card is in.
			 */
			map[3] = ((map[3] + slot - 2) % 4) + 1;
			map+=cells;
		}
	}
}
コード例 #9
0
ファイル: fdtdec.c プロジェクト: eliasbakken/u-boot
int fdtdec_lookup_phandle(const void *blob, int node, const char *prop_name)
{
	const u32 *phandle;
	int lookup;

	debug("%s: %s\n", __func__, prop_name);
	phandle = fdt_getprop(blob, node, prop_name, NULL);
	if (!phandle)
		return -FDT_ERR_NOTFOUND;

	lookup = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*phandle));
	return lookup;
}
コード例 #10
0
/**
 * pinctrl_select_state_full() - full implementation of pinctrl_select_state
 *
 * @dev: peripheral device
 * @statename: state name, like "default"
 * @return: 0 on success, or negative error code on failure
 */
static int pinctrl_select_state_full(struct udevice *dev, const char *statename)
{
	const void *fdt = gd->fdt_blob;
	int node = dev->of_offset;
	char propname[32]; /* long enough */
	const fdt32_t *list;
	uint32_t phandle;
	int config_node;
	struct udevice *config;
	int state, size, i, ret;

	state = fdt_find_string(fdt, node, "pinctrl-names", statename);
	if (state < 0) {
		char *end;
		/*
		 * If statename is not found in "pinctrl-names",
		 * assume statename is just the integer state ID.
		 */
		state = simple_strtoul(statename, &end, 10);
		if (*end)
			return -EINVAL;
	}

	snprintf(propname, sizeof(propname), "pinctrl-%d", state);
	list = fdt_getprop(fdt, node, propname, &size);
	if (!list)
		return -EINVAL;

	size /= sizeof(*list);
	for (i = 0; i < size; i++) {
		phandle = fdt32_to_cpu(*list++);

		config_node = fdt_node_offset_by_phandle(fdt, phandle);
		if (config_node < 0) {
			dev_err(dev, "prop %s index %d invalid phandle\n",
				propname, i);
			return -EINVAL;
		}
		ret = uclass_get_device_by_of_offset(UCLASS_PINCONFIG,
						     config_node, &config);
		if (ret)
			return ret;

		ret = pinctrl_config_one(config);
		if (ret)
			return ret;
	}

	return 0;
}
コード例 #11
0
ファイル: fdtdec.c プロジェクト: michalliu/rkchrome_uboot
/**
 * Decode a list of GPIOs from an FDT. This creates a list of GPIOs with no
 * terminating item.
 *
 * @param blob		FDT blob to use
 * @param node		Node to look at
 * @param prop_name	Node property name
 * @param gpio		Array of gpio elements to fill from FDT. This will be
 *			untouched if either 0 or an error is returned
 * @param max_count	Maximum number of elements allowed
 * @return number of GPIOs read if ok, -FDT_ERR_BADLAYOUT if max_count would
 * be exceeded, or -FDT_ERR_NOTFOUND if the property is missing.
 */
int fdtdec_decode_gpios(const void *blob, int node, const char *prop_name,
		struct fdt_gpio_state *gpio, int max_count)
{
	const struct fdt_property *prop;
	const u32 *cell;
	const char *name;
	int len, i;

	debug("%s: %s\n", __func__, prop_name);
	assert(max_count > 0);
	prop = fdt_get_property(blob, node, prop_name, &len);
	if (!prop) {
		debug("%s: property '%s' missing\n", __func__, prop_name);
		return -FDT_ERR_NOTFOUND;
	}

	/* We will use the name to tag the GPIO */
	name = fdt_string(blob, fdt32_to_cpu(prop->nameoff));
	cell = (u32 *)prop->data;
	len /= sizeof(u32) * 3;		/* 3 cells per GPIO record */
	if (len > max_count) {
		debug(" %s: too many GPIOs / cells for "
			"property '%s'\n", __func__, prop_name);
		return -FDT_ERR_BADLAYOUT;
	}
 #ifdef CONFIG_ROCKCHIP
	const struct fdt_property *prop1;
	const u32 *reg;
   
        for (i = 0; i < len; i++, cell += 3) {
		prop1 = fdt_get_property(blob, 
		             fdt_node_offset_by_phandle(blob, fdt32_to_cpu(cell[0])), 
		             "reg", 0);
		reg = (u32 *)prop1->data;
		gpio[i].gpio = fdt32_to_cpu(cell[1]) | fdt32_to_cpu(reg[0]);
		gpio[i].flags = fdt32_to_cpu(cell[2]);
		gpio[i].name = name;
        }
 #else
	/* Read out the GPIO data from the cells */
	for (i = 0; i < len; i++, cell += 3) {
		gpio[i].gpio = fdt32_to_cpu(cell[1]);
		gpio[i].flags = fdt32_to_cpu(cell[2]);
		gpio[i].name = name;
	}
 #endif

	return len;
}
コード例 #12
0
ファイル: ebb7800_board.c プロジェクト: disdi/u-boot-cavium
static void kill_fdt_phy(void *fdt, int offset, void *arg)
{
	int len, phy_offset;
	const fdt32_t *php;
	uint32_t phandle;

	php = fdt_getprop(fdt, offset, "phy-handle", &len);
	if (php && len == sizeof(*php)) {
		phandle = fdt32_to_cpu(*php);
		fdt_nop_property(fdt, offset, "phy-handle");
		phy_offset = fdt_node_offset_by_phandle(fdt, phandle);
		if (phy_offset > 0)
			fdt_nop_node(fdt, phy_offset);
	}
}
コード例 #13
0
static void __ft_tsec_fixup(void *blob, bd_t *bd, const char *alias,
			    int phy_addr)
{
	const char *phy_type = "sgmii";
	const u32 *ph;
	int off;
	int err;

	off = fdt_path_offset(blob, alias);
	if (off < 0) {
		printf("WARNING: could not find %s alias: %s.\n", alias,
			fdt_strerror(off));
		return;
	}

	err = fdt_setprop(blob, off, "phy-connection-type", phy_type,
			  strlen(phy_type) + 1);
	if (err) {
		printf("WARNING: could not set phy-connection-type for %s: "
			"%s.\n", alias, fdt_strerror(err));
		return;
	}

	ph = (u32 *)fdt_getprop(blob, off, "phy-handle", 0);
	if (!ph) {
		printf("WARNING: could not get phy-handle for %s.\n",
			alias);
		return;
	}

	off = fdt_node_offset_by_phandle(blob, *ph);
	if (off < 0) {
		printf("WARNING: could not get phy node for %s: %s\n", alias,
			fdt_strerror(off));
		return;
	}

	phy_addr = cpu_to_fdt32(phy_addr);
	err = fdt_setprop(blob, off, "reg", &phy_addr, sizeof(phy_addr));
	if (err < 0) {
		printf("WARNING: could not set phy node's reg for %s: "
			"%s.\n", alias, fdt_strerror(err));
		return;
	}
}
コード例 #14
0
/* Return the package handle that corresponds to an instance handle. */
static phandle_t
ofw_fdt_instance_to_package(ofw_t ofw, ihandle_t instance)
{
	int offset;

	/*
	 * Note: FDT does not have the notion of instances, but we somewhat
	 * abuse the semantics and let treat as 'instance' the internal
	 * 'phandle' prop, so that ofw I/F consumers have a uniform way of
	 * translation between internal representation (which appear in some
	 * contexts as property values) and effective phandles.
	 */
	offset = fdt_node_offset_by_phandle(fdtp, instance);
	if (offset < 0)
		return (-1);

	return (fdt_offset_phandle(offset));
}
コード例 #15
0
ファイル: fdt_overlay.c プロジェクト: 2asoft/freebsd
/*
 * Apply one overlay fragment
 */
static void
fdt_apply_fragment(void *main_fdtp, void *overlay_fdtp, int fragment_o)
{
	uint32_t target;
	const char *target_path;
	const void *val;
	int target_node_o, overlay_node_o;

	target_node_o = -1;
	val = fdt_getprop(overlay_fdtp, fragment_o, "target", NULL);
	if (val) {
		memcpy(&target, val, sizeof(target));
		target = fdt32_to_cpu(target);
		target_node_o = fdt_node_offset_by_phandle(main_fdtp, target);
		if (target_node_o < 0) {
			printf("failed to find target %04x\n", target);
			return;
		}
	}

	if (target_node_o < 0) {
		target_path = fdt_getprop(overlay_fdtp, fragment_o, "target-path", NULL);
		if (target_path == NULL)
			return;

		target_node_o = fdt_path_offset(main_fdtp, target_path);
		if (target_node_o < 0) {
			printf("failed to find target-path %s\n", target_path);
			return;
		}
	}

	if (target_node_o < 0)
		return;

	overlay_node_o = fdt_subnode_offset(overlay_fdtp, fragment_o, "__overlay__");
	if (overlay_node_o < 0) {
		printf("missing __overlay__ sub-node\n");
		return;
	}

	fdt_overlay_node(main_fdtp, target_node_o, overlay_fdtp, overlay_node_o);
}
コード例 #16
0
ファイル: fdt_overlay.c プロジェクト: dgibson/dtc
/**
 * overlay_get_target - retrieves the offset of a fragment's target
 * @fdt: Base device tree blob
 * @fdto: Device tree overlay blob
 * @fragment: node offset of the fragment in the overlay
 * @pathp: pointer which receives the path of the target (or NULL)
 *
 * overlay_get_target() retrieves the target offset in the base
 * device tree of a fragment, no matter how the actual targetting is
 * done (through a phandle or a path)
 *
 * returns:
 *      the targetted node offset in the base device tree
 *      Negative error code on error
 */
static int overlay_get_target(const void *fdt, const void *fdto,
			      int fragment, char const **pathp)
{
	uint32_t phandle;
	const char *path = NULL;
	int path_len = 0, ret;

	/* Try first to do a phandle based lookup */
	phandle = overlay_get_target_phandle(fdto, fragment);
	if (phandle == (uint32_t)-1)
		return -FDT_ERR_BADPHANDLE;

	/* no phandle, try path */
	if (!phandle) {
		/* And then a path based lookup */
		path = fdt_getprop(fdto, fragment, "target-path", &path_len);
		if (path)
			ret = fdt_path_offset(fdt, path);
		else
			ret = path_len;
	} else
		ret = fdt_node_offset_by_phandle(fdt, phandle);

	/*
	* If we haven't found either a target or a
	* target-path property in a node that contains a
	* __overlay__ subnode (we wouldn't be called
	* otherwise), consider it a improperly written
	* overlay
	*/
	if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
		ret = -FDT_ERR_BADOVERLAY;

	/* return on error */
	if (ret < 0)
		return ret;

	/* return pointer to path (if available) */
	if (pathp)
		*pathp = path ? path : NULL;

	return ret;
}
コード例 #17
0
ファイル: altera_tse.c プロジェクト: 0xFelix/u-boot-edminiv2
static int altera_tse_probe(struct udevice *dev)
{
	struct eth_pdata *pdata = dev_get_platdata(dev);
	struct altera_tse_priv *priv = dev_get_priv(dev);
	void *blob = (void *)gd->fdt_blob;
	int node = dev->of_offset;
	const char *list, *end;
	const fdt32_t *cell;
	void *base, *desc_mem = NULL;
	unsigned long addr, size;
	int parent, addrc, sizec;
	int len, idx;
	int ret;

	priv->dma_type = dev_get_driver_data(dev);
	if (priv->dma_type == ALT_SGDMA)
		priv->ops = &tse_sgdma_ops;
	else
		priv->ops = &tse_msgdma_ops;
	/*
	 * decode regs. there are multiple reg tuples, and they need to
	 * match with reg-names.
	 */
	parent = fdt_parent_offset(blob, node);
	of_bus_default_count_cells(blob, parent, &addrc, &sizec);
	list = fdt_getprop(blob, node, "reg-names", &len);
	if (!list)
		return -ENOENT;
	end = list + len;
	cell = fdt_getprop(blob, node, "reg", &len);
	if (!cell)
		return -ENOENT;
	idx = 0;
	while (list < end) {
		addr = fdt_translate_address((void *)blob,
					     node, cell + idx);
		size = fdt_addr_to_cpu(cell[idx + addrc]);
		base = map_physmem(addr, size, MAP_NOCACHE);
		len = strlen(list);
		if (strcmp(list, "control_port") == 0)
			priv->mac_dev = base;
		else if (strcmp(list, "rx_csr") == 0)
			priv->sgdma_rx = base;
		else if (strcmp(list, "rx_desc") == 0)
			priv->rx_desc = base;
		else if (strcmp(list, "rx_resp") == 0)
			priv->rx_resp = base;
		else if (strcmp(list, "tx_csr") == 0)
			priv->sgdma_tx = base;
		else if (strcmp(list, "tx_desc") == 0)
			priv->tx_desc = base;
		else if (strcmp(list, "s1") == 0)
			desc_mem = base;
		idx += addrc + sizec;
		list += (len + 1);
	}
	/* decode fifo depth */
	priv->rx_fifo_depth = fdtdec_get_int(blob, node,
		"rx-fifo-depth", 0);
	priv->tx_fifo_depth = fdtdec_get_int(blob, node,
		"tx-fifo-depth", 0);
	/* decode phy */
	addr = fdtdec_get_int(blob, node,
			      "phy-handle", 0);
	addr = fdt_node_offset_by_phandle(blob, addr);
	priv->phyaddr = fdtdec_get_int(blob, addr,
		"reg", 0);
	/* init desc */
	if (priv->dma_type == ALT_SGDMA) {
		len = sizeof(struct alt_sgdma_descriptor) * 4;
		if (!desc_mem) {
			desc_mem = dma_alloc_coherent(len, &addr);
			if (!desc_mem)
				return -ENOMEM;
		}
		memset(desc_mem, 0, len);
		priv->tx_desc = desc_mem;
		priv->rx_desc = priv->tx_desc +
			2 * sizeof(struct alt_sgdma_descriptor);
	}
	/* allocate recv packet buffer */
	priv->rx_buf = malloc_cache_aligned(PKTSIZE_ALIGN);
	if (!priv->rx_buf)
		return -ENOMEM;

	/* stop controller */
	debug("Reset TSE & SGDMAs\n");
	altera_tse_stop(dev);

	/* start the phy */
	priv->interface = pdata->phy_interface;
	tse_mdio_init(dev->name, priv);
	priv->bus = miiphy_get_dev_by_name(dev->name);

	ret = tse_phy_init(priv, dev);

	return ret;
}
コード例 #18
0
ファイル: fdtdec.c プロジェクト: eliasbakken/u-boot
int fdtdec_parse_phandle_with_args(const void *blob, int src_node,
				   const char *list_name,
				   const char *cells_name,
				   int cell_count, int index,
				   struct fdtdec_phandle_args *out_args)
{
	const __be32 *list, *list_end;
	int rc = 0, size, cur_index = 0;
	uint32_t count = 0;
	int node = -1;
	int phandle;

	/* Retrieve the phandle list property */
	list = fdt_getprop(blob, src_node, list_name, &size);
	if (!list)
		return -ENOENT;
	list_end = list + size / sizeof(*list);

	/* Loop over the phandles until all the requested entry is found */
	while (list < list_end) {
		rc = -EINVAL;
		count = 0;

		/*
		 * If phandle is 0, then it is an empty entry with no
		 * arguments.  Skip forward to the next entry.
		 */
		phandle = be32_to_cpup(list++);
		if (phandle) {
			/*
			 * Find the provider node and parse the #*-cells
			 * property to determine the argument length.
			 *
			 * This is not needed if the cell count is hard-coded
			 * (i.e. cells_name not set, but cell_count is set),
			 * except when we're going to return the found node
			 * below.
			 */
			if (cells_name || cur_index == index) {
				node = fdt_node_offset_by_phandle(blob,
								  phandle);
				if (!node) {
					debug("%s: could not find phandle\n",
					      fdt_get_name(blob, src_node,
							   NULL));
					goto err;
				}
			}

			if (cells_name) {
				count = fdtdec_get_int(blob, node, cells_name,
						       -1);
				if (count == -1) {
					debug("%s: could not get %s for %s\n",
					      fdt_get_name(blob, src_node,
							   NULL),
					      cells_name,
					      fdt_get_name(blob, node,
							   NULL));
					goto err;
				}
			} else {
				count = cell_count;
			}

			/*
			 * Make sure that the arguments actually fit in the
			 * remaining property data length
			 */
			if (list + count > list_end) {
				debug("%s: arguments longer than property\n",
				      fdt_get_name(blob, src_node, NULL));
				goto err;
			}
		}

		/*
		 * All of the error cases above bail out of the loop, so at
		 * this point, the parsing is successful. If the requested
		 * index matches, then fill the out_args structure and return,
		 * or return -ENOENT for an empty entry.
		 */
		rc = -ENOENT;
		if (cur_index == index) {
			if (!phandle)
				goto err;

			if (out_args) {
				int i;

				if (count > MAX_PHANDLE_ARGS) {
					debug("%s: too many arguments %d\n",
					      fdt_get_name(blob, src_node,
							   NULL), count);
					count = MAX_PHANDLE_ARGS;
				}
				out_args->node = node;
				out_args->args_count = count;
				for (i = 0; i < count; i++) {
					out_args->args[i] =
							be32_to_cpup(list++);
				}
			}

			/* Found it! return success */
			return 0;
		}

		node = -1;
		list += count;
		cur_index++;
	}

	/*
	 * Result will be one of:
	 * -ENOENT : index is for empty phandle
	 * -EINVAL : parsing error on data
	 * [1..n]  : Number of phandle (count mode; when index = -1)
	 */
	rc = index < 0 ? cur_index : -ENOENT;
 err:
	return rc;
}
コード例 #19
0
ファイル: mpc8569mds.c プロジェクト: Aorjoa/bootloader
void ft_board_setup(void *blob, bd_t *bd)
{
#if defined(CONFIG_SYS_UCC_RMII_MODE)
	int nodeoff, off, err;
	unsigned int val;
	const u32 *ph;
	const u32 *index;

	/* fixup device tree for supporting rmii mode */
	nodeoff = -1;
	while ((nodeoff = fdt_node_offset_by_compatible(blob, nodeoff,
				"ucc_geth")) >= 0) {
		err = fdt_setprop_string(blob, nodeoff, "tx-clock-name",
						"clk16");
		if (err < 0) {
			printf("WARNING: could not set tx-clock-name %s.\n",
				fdt_strerror(err));
			break;
		}

		err = fdt_fixup_phy_connection(blob, nodeoff,
				PHY_INTERFACE_MODE_RMII);

		if (err < 0) {
			printf("WARNING: could not set phy-connection-type "
				"%s.\n", fdt_strerror(err));
			break;
		}

		index = fdt_getprop(blob, nodeoff, "cell-index", 0);
		if (index == NULL) {
			printf("WARNING: could not get cell-index of ucc\n");
			break;
		}

		ph = fdt_getprop(blob, nodeoff, "phy-handle", 0);
		if (ph == NULL) {
			printf("WARNING: could not get phy-handle of ucc\n");
			break;
		}

		off = fdt_node_offset_by_phandle(blob, *ph);
		if (off < 0) {
			printf("WARNING: could not get phy node	%s.\n",
				fdt_strerror(err));
			break;
		}

		val = 0x7 + *index; /* RMII phy address starts from 0x8 */

		err = fdt_setprop(blob, off, "reg", &val, sizeof(u32));
		if (err < 0) {
			printf("WARNING: could not set reg for phy-handle "
				"%s.\n", fdt_strerror(err));
			break;
		}
	}
#endif
	ft_cpu_setup(blob, bd);

	FT_FSL_PCI_SETUP;

	fdt_board_fixup_esdhc(blob, bd);
	fdt_board_fixup_qe_uart(blob, bd);
	fdt_board_fixup_qe_usb(blob, bd);
}
コード例 #20
0
ファイル: eth.c プロジェクト: CogSystems/u-boot
void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
			      enum fm_port port, int offset)
{
	struct fixed_link f_link;
	const u32 *handle;
	const char *prop = NULL;
	int off;

	if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) {
		switch (port) {
		case FM1_DTSEC9:
			fdt_set_phy_handle(fdt, compat, addr, "sgmii_s1_p1");
			break;
		case FM1_DTSEC10:
			fdt_set_phy_handle(fdt, compat, addr, "sgmii_s1_p2");
			break;
		case FM1_DTSEC5:
			fdt_set_phy_handle(fdt, compat, addr, "sgmii_s1_p3");
			break;
		case FM1_DTSEC6:
			fdt_set_phy_handle(fdt, compat, addr, "sgmii_s1_p4");
			break;
		case FM1_DTSEC2:
			fdt_set_phy_handle(fdt, compat, addr, "sgmii_s4_p1");
			break;
		default:
			break;
		}
	} else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII_2500) {
		/* 2.5G SGMII interface */
		f_link.phy_id = cpu_to_fdt32(port);
		f_link.duplex = cpu_to_fdt32(1);
		f_link.link_speed = cpu_to_fdt32(1000);
		f_link.pause = 0;
		f_link.asym_pause = 0;
		/* no PHY for 2.5G SGMII on QDS */
		fdt_delprop(fdt, offset, "phy-handle");
		fdt_setprop(fdt, offset, "fixed-link", &f_link, sizeof(f_link));
		fdt_setprop_string(fdt, offset, "phy-connection-type",
				   "sgmii-2500");
	} else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_QSGMII) {
		switch (port) {
		case FM1_DTSEC1:
			fdt_set_phy_handle(fdt, compat, addr, "qsgmii_s2_p4");
			break;
		case FM1_DTSEC5:
			fdt_set_phy_handle(fdt, compat, addr, "qsgmii_s2_p2");
			break;
		case FM1_DTSEC6:
			fdt_set_phy_handle(fdt, compat, addr, "qsgmii_s2_p1");
			break;
		case FM1_DTSEC10:
			fdt_set_phy_handle(fdt, compat, addr, "qsgmii_s2_p3");
			break;
		default:
			break;
		}
		fdt_delprop(fdt, offset, "phy-connection-type");
		fdt_setprop_string(fdt, offset, "phy-connection-type",
				   "qsgmii");
	} else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_XGMII &&
		   (port == FM1_10GEC1 || port == FM1_10GEC2)) {
		handle = fdt_getprop(fdt, offset, "phy-handle", NULL);
		prop = NULL;
		if (handle) {
			off = fdt_node_offset_by_phandle(fdt,
							 fdt32_to_cpu(*handle));
			prop = fdt_getprop(fdt, off, "backplane-mode", NULL);
		}
		if (!prop || strcmp(prop, "10gbase-kr")) {
			/* XFI interface */
			f_link.phy_id = cpu_to_fdt32(port);
			f_link.duplex = cpu_to_fdt32(1);
			f_link.link_speed = cpu_to_fdt32(10000);
			f_link.pause = 0;
			f_link.asym_pause = 0;
			/* no PHY for XFI */
			fdt_delprop(fdt, offset, "phy-handle");
			fdt_setprop(fdt, offset, "fixed-link", &f_link,
				    sizeof(f_link));
			fdt_setprop_string(fdt, offset, "phy-connection-type",
					   "xgmii");
		}
	}
}
コード例 #21
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;
}