void ft_fixup_enet_phy_connect_type(void *fdt) { struct eth_device *dev; struct tsec_private *priv; const char *enet_path, *phy_path; char enet[16]; char phy[16]; int phy_node; int i = 0; uint32_t ph; char *name[3] = { "eTSEC1", "eTSEC2", "eTSEC3" }; for (; i < ARRAY_SIZE(name); i++) { dev = eth_get_dev_by_name(name[i]); if (dev) { sprintf(enet, "ethernet%d", i); sprintf(phy, "enet%d_rgmii_phy", i); } else { continue; } priv = dev->priv; if (priv->flags & TSEC_SGMII) continue; enet_path = fdt_get_alias(fdt, enet); if (!enet_path) continue; phy_path = fdt_get_alias(fdt, phy); if (!phy_path) continue; phy_node = fdt_path_offset(fdt, phy_path); if (phy_node < 0) continue; ph = fdt_create_phandle(fdt, phy_node); if (ph) do_fixup_by_path_u32(fdt, enet_path, "phy-handle", ph, 1); do_fixup_by_path(fdt, enet_path, "phy-connection-type", phy_string_for_interface( PHY_INTERFACE_MODE_RGMII_ID), sizeof(phy_string_for_interface( PHY_INTERFACE_MODE_RGMII_ID)), 1); } }
static int ti_musb_get_usb_index(int node) { const void *fdt = gd->fdt_blob; int i = 0; char path[64]; const char *alias_path; char alias[16]; fdt_get_path(fdt, node, path, sizeof(path)); do { snprintf(alias, sizeof(alias), "usb%d", i); alias_path = fdt_get_alias(fdt, alias); if (alias_path == NULL) { debug("USB index not found\n"); return -ENOENT; } if (!strcmp(path, alias_path)) return i; i++; } while (alias_path); return -ENOENT; }
/* * Given the following ... * * 1) A pointer to an Fman Ethernet node (as identified by the 'compat' * compatible string and 'addr' physical address) * * 2) The name of an alias that points to the ethernet-phy node (usually inside * a virtual MDIO node) * * ... update that Ethernet node's phy-handle property to point to the * ethernet-phy node. This is how we link an Ethernet node to its PHY, so each * PHY in a virtual MDIO node must have an alias. * * Returns 0 on success, or a negative FDT error code on error. */ int fdt_set_phy_handle(void *fdt, char *compat, phys_addr_t addr, const char *alias) { int offset; unsigned int ph; const char *path; /* Get a path to the node that 'alias' points to */ path = fdt_get_alias(fdt, alias); if (!path) return -FDT_ERR_BADPATH; /* Get the offset of that node */ offset = fdt_path_offset(fdt, path); if (offset < 0) return offset; ph = fdt_create_phandle(fdt, offset); if (!ph) return -FDT_ERR_BADPHANDLE; offset = fdt_node_offset_by_compat_reg(fdt, compat, addr); if (offset < 0) return offset; return fdt_setprop(fdt, offset, "phy-handle", &ph, sizeof(ph)); }
int of_finddevice(const char *device) { const char *name = device; int node; if (device == NULL) return OF_FAILED; if (device[0] != '/' && fdt_get_alias(gFDT, device)) name = fdt_get_alias(gFDT, device); node = fdt_path_offset(gFDT, name); TRACE(("of_finddevice('%s') name='%s' node=%d ret=%d\n", device, name, node, fdt2of(node))); return fdt2of(node); }
int fdtparse_alias_offset(const void *fdt, const char *name) { const char *path; path = fdt_get_alias(fdt, name); if (!path) { return -FDT_ERR_NOTFOUND; } return fdt_path_offset(fdt, path); }
/* * Given an alias or a path for a node, set the mux value of that node. * * If 'alias' is not a valid alias, then it is treated as a full path to the * node. No error checking is performed. * * This function is normally called to set the fsl,hydra-mdio-muxval property * of a virtual MDIO node. */ static void fdt_set_mdio_mux(void *fdt, const char *alias, u32 mux) { const char *path = fdt_get_alias(fdt, alias); if (!path) path = alias; do_fixup_by_path(fdt, path, "fsl,hydra-mdio-muxval", &mux, sizeof(mux), 1); }
phys_addr_t fdt_get_device_reg_byalias(const void* fdt, const char* alias) { const char* name = fdt_get_alias(fdt, alias); if (name == NULL) { dprintf("%s: No alias found for %s!\n", __func__, alias); return 0; } phys_addr_t deviceReg = fdt_get_device_reg_byname(fdt, name); return deviceReg; }
int i2c_bus_register_imx(const char *bus_path, const char *alias_or_path) { const void *fdt; const char *path; int node; imx_i2c_bus *bus; int eno; fdt = bsp_fdt_get(); path = fdt_get_alias(fdt, alias_or_path); if (path == NULL) { path = alias_or_path; } node = fdt_path_offset(fdt, path); if (node < 0) { rtems_set_errno_and_return_minus_one(ENXIO); } bus = (imx_i2c_bus *) i2c_bus_alloc_and_init(sizeof(*bus)); if (bus == NULL){ return -1; } bus->regs = imx_get_reg_of_node(fdt, node); bus->irq = imx_get_irq_of_node(fdt, node, 0); eno = imx_i2c_init(bus); if (eno != 0) { (*bus->base.destroy)(&bus->base); rtems_set_errno_and_return_minus_one(eno); } bus->base.transfer = imx_i2c_transfer; bus->base.set_clock = imx_i2c_set_clock; bus->base.destroy = imx_i2c_destroy; return i2c_bus_register(&bus->base, bus_path); }
void ft_cpu_setup(void *blob, bd_t *bd) { int off; int val; const char *sysclk_path; struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); unsigned int svr; svr = in_be32(&gur->svr); unsigned long busclk = get_bus_freq(0); /* delete crypto node if not on an E-processor */ if (!IS_E_PROCESSOR(svr)) fdt_fixup_crypto_node(blob, 0); #if CONFIG_SYS_FSL_SEC_COMPAT >= 4 else { ccsr_sec_t __iomem *sec; sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR; fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms)); } #endif off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); while (off != -FDT_ERR_NOTFOUND) { val = gd->cpu_clk; fdt_setprop(blob, off, "clock-frequency", &val, 4); off = fdt_node_offset_by_prop_value(blob, off, "device_type", "cpu", 4); } do_fixup_by_prop_u32(blob, "device_type", "soc", 4, "bus-frequency", busclk, 1); ft_fixup_enet_phy_connect_type(blob); #ifdef CONFIG_SYS_NS16550 do_fixup_by_compat_u32(blob, "fsl,16550-FIFO64", "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); #endif sysclk_path = fdt_get_alias(blob, "sysclk"); if (sysclk_path) do_fixup_by_path_u32(blob, sysclk_path, "clock-frequency", CONFIG_SYS_CLK_FREQ, 1); do_fixup_by_compat_u32(blob, "fsl,qoriq-sysclk-2.0", "clock-frequency", CONFIG_SYS_CLK_FREQ, 1); #if defined(CONFIG_DEEP_SLEEP) && defined(CONFIG_SD_BOOT) #define UBOOT_HEAD_LEN 0x1000 /* * Reserved memory in SD boot deep sleep case. * Second stage uboot binary and malloc space should be reserved. * If the memory they occupied has not been reserved, then this * space would be used by kernel and overwritten in uboot when * deep sleep resume, which cause deep sleep failed. * Since second uboot binary has a head, that space need to be * reserved either(assuming its size is less than 0x1000). */ off = fdt_add_mem_rsv(blob, CONFIG_SYS_TEXT_BASE - UBOOT_HEAD_LEN, CONFIG_SYS_MONITOR_LEN + CONFIG_SYS_SPL_MALLOC_SIZE + UBOOT_HEAD_LEN); if (off < 0) printf("Failed to reserve memory for SD boot deep sleep: %s\n", fdt_strerror(off)); #endif #if defined(CONFIG_FSL_ESDHC) fdt_fixup_esdhc(blob, bd); #endif /* * platform bus clock = system bus clock/2 * Here busclk = system bus clock * We are using the platform bus clock as 1588 Timer reference * clock source select */ do_fixup_by_compat_u32(blob, "fsl, gianfar-ptp-timer", "timer-frequency", busclk / 2, 1); /* * clock-freq should change to clock-frequency and * flexcan-v1.0 should change to p1010-flexcan respectively * in the future. */ do_fixup_by_compat_u32(blob, "fsl, flexcan-v1.0", "clock_freq", busclk / 2, 1); do_fixup_by_compat_u32(blob, "fsl, flexcan-v1.0", "clock-frequency", busclk / 2, 1); do_fixup_by_compat_u32(blob, "fsl, ls1021a-flexcan", "clock-frequency", busclk / 2, 1); #if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI) off = fdt_node_offset_by_compat_reg(blob, FSL_IFC_COMPAT, CONFIG_SYS_IFC_ADDR); fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); #else off = fdt_node_offset_by_compat_reg(blob, FSL_QSPI_COMPAT, QSPI0_BASE_ADDR); fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); off = fdt_node_offset_by_compat_reg(blob, FSL_DSPI_COMPAT, DSPI1_BASE_ADDR); fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); #endif }
/* * 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); }
DebugUART * debug_uart_from_fdt(const void *fdt) { const char *name; const char *type; int node; int len; phys_addr_t regs; int32 clock = 0; int32 speed = 0; const void *prop; DebugUART *uart = NULL; if (fdt == NULL) return NULL; name = fdt_get_alias(fdt, "serial"); if (name == NULL) name = fdt_get_alias(fdt, "serial0"); if (name == NULL) name = fdt_get_alias(fdt, "serial1"); // TODO: else use /chosen linux,stdout-path if (name == NULL) return NULL; node = fdt_path_offset(fdt, name); //dprintf("serial: using '%s', node %d\n", name, node); if (node < 0) return NULL; type = (const char *)fdt_getprop(fdt, node, "device_type", &len); //dprintf("serial: type: '%s'\n", type); if (type == NULL || strcmp(type, "serial")) return NULL; // determine the MMIO address // TODO: ppc460 use 64bit addressing, but U-Boot seems to map it below 4G, // and the FDT is not very clear. libfdt is also getting 64bit addr support. // so FIXME someday. prop = fdt_getprop(fdt, node, "virtual-reg", &len); if (prop && len == 4) { regs = fdt32_to_cpu(*(uint32_t *)prop); //dprintf("serial: virtual-reg 0x%08llx\n", (int64)regs); } else { prop = fdt_getprop(fdt, node, "reg", &len); if (prop && len >= 4) { regs = fdt32_to_cpu(*(uint32_t *)prop); //dprintf("serial: reg 0x%08llx\n", (int64)regs); } else return NULL; } // get the UART clock rate prop = fdt_getprop(fdt, node, "clock-frequency", &len); if (prop && len == 4) { clock = fdt32_to_cpu(*(uint32_t *)prop); //dprintf("serial: clock %ld\n", clock); } // get current speed (XXX: not yet passed over) prop = fdt_getprop(fdt, node, "current-speed", &len); if (prop && len == 4) { speed = fdt32_to_cpu(*(uint32_t *)prop); //dprintf("serial: speed %ld\n", speed); } if (fdt_node_check_compatible(fdt, node, "ns16550a") == 1 || fdt_node_check_compatible(fdt, node, "ns16550") == 1) { uart = arch_get_uart_8250(regs, clock); //dprintf("serial: using 8250\n"); // XXX:assume speed is already set (void)speed; } else { // TODO: handle more UART types // for when we can use U-Boot's console panic("Unknown UART type %s", type); } return uart; }
static void process_boot_dtb(void *boot_dtb) { const u32 *na, *ns, *reg, *val32; const char *path; u64 memsize64; int node, size, i; /* Make sure FDT blob is sane */ if (fdt_check_header(boot_dtb) != 0) fatal("Invalid device tree blob\n"); /* Find the #address-cells and #size-cells properties */ node = fdt_path_offset(boot_dtb, "/"); if (node < 0) fatal("Cannot find root node\n"); na = fdt_getprop(boot_dtb, node, "#address-cells", &size); if (!na || (size != 4)) fatal("Cannot find #address-cells property"); ns = fdt_getprop(boot_dtb, node, "#size-cells", &size); if (!ns || (size != 4)) fatal("Cannot find #size-cells property"); /* Find the memory range */ node = fdt_node_offset_by_prop_value(boot_dtb, -1, "device_type", "memory", sizeof("memory")); if (node < 0) fatal("Cannot find memory node\n"); reg = fdt_getprop(boot_dtb, node, "reg", &size); if (size < (*na+*ns) * sizeof(u32)) fatal("cannot get memory range\n"); /* Only interested in memory based at 0 */ for (i = 0; i < *na; i++) if (*reg++ != 0) fatal("Memory range is not based at address 0\n"); /* get the memsize and trucate it to under 4G on 32 bit machines */ memsize64 = 0; for (i = 0; i < *ns; i++) memsize64 = (memsize64 << 32) | *reg++; if (sizeof(void *) == 4 && memsize64 >= 0x100000000ULL) memsize64 = 0xffffffff; mem_size = memsize64; /* get clock frequencies */ node = fdt_node_offset_by_prop_value(boot_dtb, -1, "device_type", "cpu", sizeof("cpu")); if (!node) fatal("Cannot find cpu node\n"); val32 = fdt_getprop(boot_dtb, node, "clock-frequency", &size); if (!val32 || (size != 4)) fatal("Cannot get clock frequency"); int_freq = *val32; val32 = fdt_getprop(boot_dtb, node, "bus-frequency", &size); if (!val32 || (size != 4)) fatal("Cannot get bus frequency"); bus_freq = *val32; path = fdt_get_alias(boot_dtb, "ethernet0"); if (path) { const void *p; node = fdt_path_offset(boot_dtb, path); if (node < 0) fatal("Cannot find ethernet0 node"); p = fdt_getprop(boot_dtb, node, "mac-address", &size); if (!p || (size < 6)) { printf("no mac-address property, finding local\n\r"); p = fdt_getprop(boot_dtb, node, "local-mac-address", &size); } if (!p || (size < 6)) fatal("cannot get MAC addres"); memcpy(enetaddr, p, sizeof(enetaddr)); } }