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]; }
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; }
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); }
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; }
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); } }
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); }
/** * 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; }
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; } } }
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; }
/** * 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; }
/** * 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; }
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); } }
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; } }
/* 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)); }
/* * 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); }
/** * 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; }
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; }
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; }
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); }
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"); } } }
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; }