fdt_addr_t fdtdec_get_addr_size(const void *blob, int node, const char *prop_name, fdt_size_t *sizep) { const fdt_addr_t *cell; int len; debug("%s: %s: ", __func__, prop_name); cell = fdt_getprop(blob, node, prop_name, &len); if (cell && ((!sizep && len == sizeof(fdt_addr_t)) || len == sizeof(fdt_addr_t) * 2)) { fdt_addr_t addr = fdt_addr_to_cpu(*cell); if (sizep) { const fdt_size_t *size; size = (fdt_size_t *)((char *)cell + sizeof(fdt_addr_t)); *sizep = fdt_size_to_cpu(*size); debug("addr=%p, size=%p\n", (void *)addr, (void *)*sizep); } else { debug("%p\n", (void *)addr); } return addr; } debug("(not found)\n"); return FDT_ADDR_T_NONE; }
int fdtdec_decode_memory(const void *blob, struct fdt_memory *config) { int node, len; const fdt_addr_t *cell; node = fdt_path_offset(blob, "/memory"); if (node < 0) { debug("Could not find the path /memory\n"); return node; } cell = fdt_getprop(blob, node, "reg", &len); if (cell && len == sizeof(fdt_addr_t) * 2) { config->start = fdt_addr_to_cpu(cell[0]); config->end = fdt_addr_to_cpu(cell[1]); } else { return -FDT_ERR_BADLAYOUT; } return 0; }
fdt_addr_t fdtdec_get_addr(const void *blob, int node, const char *prop_name) { const fdt_addr_t *cell; int len; debug("get_addr: %s\n", prop_name); cell = fdt_getprop(blob, node, prop_name, &len); if (cell && (len == sizeof(fdt_addr_t) || len == sizeof(fdt_addr_t) * 2)) return fdt_addr_to_cpu(*cell); return FDT_ADDR_T_NONE; }
int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type, const char *prop_name, struct fdt_pci_addr *addr) { const u32 *cell; int len; int ret = -ENOENT; debug("%s: %s: ", __func__, prop_name); /* * If we follow the pci bus bindings strictly, we should check * the value of the node's parent node's #address-cells and * #size-cells. They need to be 3 and 2 accordingly. However, * for simplicity we skip the check here. */ cell = fdt_getprop(blob, node, prop_name, &len); if (!cell) goto fail; if ((len % FDT_PCI_REG_SIZE) == 0) { int num = len / FDT_PCI_REG_SIZE; int i; for (i = 0; i < num; i++) { debug("pci address #%d: %08lx %08lx %08lx\n", i, (ulong)fdt_addr_to_cpu(cell[0]), (ulong)fdt_addr_to_cpu(cell[1]), (ulong)fdt_addr_to_cpu(cell[2])); if ((fdt_addr_to_cpu(*cell) & type) == type) { addr->phys_hi = fdt_addr_to_cpu(cell[0]); addr->phys_mid = fdt_addr_to_cpu(cell[1]); addr->phys_lo = fdt_addr_to_cpu(cell[2]); break; } else { cell += (FDT_PCI_ADDR_CELLS + FDT_PCI_SIZE_CELLS); } } if (i == num) { ret = -ENXIO; goto fail; } return 0; } else { ret = -EINVAL; } fail: debug("(not found)\n"); return ret; }
int fdtdec_decode_region(const void *blob, int node, const char *prop_name, void **ptrp, size_t *size) { const fdt_addr_t *cell; int len; debug("%s: %s\n", __func__, prop_name); cell = fdt_getprop(blob, node, prop_name, &len); if (!cell || (len != sizeof(fdt_addr_t) * 2)) return -1; *ptrp = (void *)fdt_addr_to_cpu(*cell); *size = fdt_size_to_cpu(cell[1]); debug("%s: size=%zx\n", __func__, *size); return 0; }
fdt_addr_t fdtdec_get_addr(const void *blob, int node, const char *prop_name) { const fdt_addr_t *cell; int len; //debug("%s: %s\n", __func__, prop_name); cell = fdt_getprop(blob, node, prop_name, &len); if (cell && (len == sizeof(fdt_addr_t) || len == sizeof(fdt_addr_t) * 2)) { fdt_addr_t addr = fdt_addr_to_cpu(*cell); //debug("%p\n", (void *)addr); return addr; } //debug("(not found)\n"); return FDT_ADDR_T_NONE; }
int ofnode_decode_region(ofnode node, const char *prop_name, fdt_addr_t *basep, fdt_size_t *sizep) { const fdt_addr_t *cell; int len; debug("%s: %s: %s\n", __func__, ofnode_get_name(node), prop_name); cell = ofnode_get_property(node, prop_name, &len); if (!cell || (len < sizeof(fdt_addr_t) * 2)) { debug("cell=%p, len=%d\n", cell, len); return -1; } *basep = fdt_addr_to_cpu(*cell); *sizep = fdt_size_to_cpu(cell[1]); debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep, (ulong)*sizep); return 0; }
int fdtdec_decode_region(const void *blob, int node, const char *prop_name, fdt_addr_t *basep, fdt_size_t *sizep) { const fdt_addr_t *cell; int len; debug("%s: %s: %s\n", __func__, fdt_get_name(blob, node, NULL), prop_name); cell = fdt_getprop(blob, node, prop_name, &len); if (!cell || (len < sizeof(fdt_addr_t) * 2)) { debug("cell=%p, len=%d\n", cell, len); return -1; } *basep = fdt_addr_to_cpu(*cell); *sizep = fdt_size_to_cpu(cell[1]); debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep, (ulong)*sizep); return 0; }
static int create_pirq_routing_table(void) { const void *blob = gd->fdt_blob; struct fdt_pci_addr addr; int node; int len, count; const u32 *cell; struct irq_routing_table *rt; struct irq_info *slot, *slot_base; int irq_entries = 0; int i; int ret; node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_IRQ_ROUTER); if (node < 0) { debug("%s: Cannot find irq router node\n", __func__); return -EINVAL; } ret = fdtdec_get_pci_addr(blob, node, FDT_PCI_SPACE_CONFIG, "reg", &addr); if (ret) return ret; /* extract the bdf from fdt_pci_addr */ irq_router.bdf = addr.phys_hi & 0xffff00; ret = fdt_find_string(blob, node, "intel,pirq-config", "pci"); if (!ret) { irq_router.config = PIRQ_VIA_PCI; } else { ret = fdt_find_string(blob, node, "intel,pirq-config", "ibase"); if (!ret) irq_router.config = PIRQ_VIA_IBASE; else return -EINVAL; } ret = fdtdec_get_int(blob, node, "intel,pirq-link", -1); if (ret == -1) return ret; irq_router.link_base = ret; irq_router.irq_mask = fdtdec_get_int(blob, node, "intel,pirq-mask", PIRQ_BITMAP); if (irq_router.config == PIRQ_VIA_IBASE) { int ibase_off; ibase_off = fdtdec_get_int(blob, node, "intel,ibase-offset", 0); if (!ibase_off) return -EINVAL; /* * Here we assume that the IBASE register has already been * properly configured by U-Boot before. * * By 'valid' we mean: * 1) a valid memory space carved within system memory space * assigned to IBASE register block. * 2) memory range decoding is enabled. * Hence we don't do any santify test here. */ irq_router.ibase = x86_pci_read_config32(irq_router.bdf, ibase_off); irq_router.ibase &= ~0xf; } cell = fdt_getprop(blob, node, "intel,pirq-routing", &len); if (!cell || len % sizeof(struct pirq_routing)) return -EINVAL; count = len / sizeof(struct pirq_routing); rt = calloc(1, sizeof(struct irq_routing_table)); if (!rt) return -ENOMEM; /* Populate the PIRQ table fields */ rt->signature = PIRQ_SIGNATURE; rt->version = PIRQ_VERSION; rt->rtr_bus = PCI_BUS(irq_router.bdf); rt->rtr_devfn = (PCI_DEV(irq_router.bdf) << 3) | PCI_FUNC(irq_router.bdf); rt->rtr_vendor = PCI_VENDOR_ID_INTEL; rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31; slot_base = rt->slots; /* Now fill in the irq_info entries in the PIRQ table */ for (i = 0; i < count; i++, cell += sizeof(struct pirq_routing) / sizeof(u32)) { struct pirq_routing pr; pr.bdf = fdt_addr_to_cpu(cell[0]); pr.pin = fdt_addr_to_cpu(cell[1]); pr.pirq = fdt_addr_to_cpu(cell[2]); debug("irq_info %d: b.d.f %x.%x.%x INT%c PIRQ%c\n", i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), PCI_FUNC(pr.bdf), 'A' + pr.pin - 1, 'A' + pr.pirq); slot = check_dup_entry(slot_base, irq_entries, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); if (slot) { debug("found entry for bus %d device %d, ", PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); if (slot->irq[pr.pin - 1].link) { debug("skipping\n"); /* * Sanity test on the routed PIRQ pin * * If they don't match, show a warning to tell * there might be something wrong with the PIRQ * routing information in the device tree. */ if (slot->irq[pr.pin - 1].link != LINK_N2V(pr.pirq, irq_router.link_base)) debug("WARNING: Inconsistent PIRQ routing information\n"); continue; } } else { slot = slot_base + irq_entries++; } debug("writing INT%c\n", 'A' + pr.pin - 1); fill_irq_info(slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin, pr.pirq); } rt->size = irq_entries * sizeof(struct irq_info) + 32; pirq_routing_table = rt; return 0; }
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; }
static int create_pirq_routing_table(struct udevice *dev) { struct irq_router *priv = dev_get_priv(dev); const void *blob = gd->fdt_blob; int node; int len, count; const u32 *cell; struct irq_routing_table *rt; struct irq_info *slot, *slot_base; int irq_entries = 0; int i; int ret; node = dev->of_offset; /* extract the bdf from fdt_pci_addr */ priv->bdf = dm_pci_get_bdf(dev->parent); ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "pci"); if (!ret) { priv->config = PIRQ_VIA_PCI; } else { ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "ibase"); if (!ret) priv->config = PIRQ_VIA_IBASE; else return -EINVAL; } ret = fdtdec_get_int(blob, node, "intel,pirq-link", -1); if (ret == -1) return ret; priv->link_base = ret; priv->irq_mask = fdtdec_get_int(blob, node, "intel,pirq-mask", PIRQ_BITMAP); if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { /* Reserve IRQ9 for SCI */ priv->irq_mask &= ~(1 << 9); } if (priv->config == PIRQ_VIA_IBASE) { int ibase_off; ibase_off = fdtdec_get_int(blob, node, "intel,ibase-offset", 0); if (!ibase_off) return -EINVAL; /* * Here we assume that the IBASE register has already been * properly configured by U-Boot before. * * By 'valid' we mean: * 1) a valid memory space carved within system memory space * assigned to IBASE register block. * 2) memory range decoding is enabled. * Hence we don't do any santify test here. */ dm_pci_read_config32(dev->parent, ibase_off, &priv->ibase); priv->ibase &= ~0xf; } priv->actl_8bit = fdtdec_get_bool(blob, node, "intel,actl-8bit"); priv->actl_addr = fdtdec_get_int(blob, node, "intel,actl-addr", 0); cell = fdt_getprop(blob, node, "intel,pirq-routing", &len); if (!cell || len % sizeof(struct pirq_routing)) return -EINVAL; count = len / sizeof(struct pirq_routing); rt = calloc(1, sizeof(struct irq_routing_table)); if (!rt) return -ENOMEM; /* Populate the PIRQ table fields */ rt->signature = PIRQ_SIGNATURE; rt->version = PIRQ_VERSION; rt->rtr_bus = PCI_BUS(priv->bdf); rt->rtr_devfn = (PCI_DEV(priv->bdf) << 3) | PCI_FUNC(priv->bdf); rt->rtr_vendor = PCI_VENDOR_ID_INTEL; rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31; slot_base = rt->slots; /* Now fill in the irq_info entries in the PIRQ table */ for (i = 0; i < count; i++, cell += sizeof(struct pirq_routing) / sizeof(u32)) { struct pirq_routing pr; pr.bdf = fdt_addr_to_cpu(cell[0]); pr.pin = fdt_addr_to_cpu(cell[1]); pr.pirq = fdt_addr_to_cpu(cell[2]); debug("irq_info %d: b.d.f %x.%x.%x INT%c PIRQ%c\n", i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), PCI_FUNC(pr.bdf), 'A' + pr.pin - 1, 'A' + pr.pirq); slot = check_dup_entry(slot_base, irq_entries, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); if (slot) { debug("found entry for bus %d device %d, ", PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); if (slot->irq[pr.pin - 1].link) { debug("skipping\n"); /* * Sanity test on the routed PIRQ pin * * If they don't match, show a warning to tell * there might be something wrong with the PIRQ * routing information in the device tree. */ if (slot->irq[pr.pin - 1].link != LINK_N2V(pr.pirq, priv->link_base)) debug("WARNING: Inconsistent PIRQ routing information\n"); continue; } } else { slot = slot_base + irq_entries++; } debug("writing INT%c\n", 'A' + pr.pin - 1); fill_irq_info(priv, slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin, pr.pirq); } rt->size = irq_entries * sizeof(struct irq_info) + 32; /* Fix up the table checksum */ rt->checksum = table_compute_checksum(rt, rt->size); pirq_routing_table = rt; return 0; }
static int pic32_flash_probe(struct udevice *dev) { void *blob = (void *)gd->fdt_blob; int node = dev_of_offset(dev); const char *list, *end; const fdt32_t *cell; unsigned long addr, size; int parent, addrc, sizec; flash_info_t *info; int len, idx; /* * 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; for (idx = 0, info = &flash_info[0]; list < end;) { addr = fdt_translate_address((void *)blob, node, cell + idx); size = fdt_addr_to_cpu(cell[idx + addrc]); len = strlen(list); if (!strncmp(list, "nvm", len)) { /* NVM controller */ nvm_regs_p = ioremap(addr, size); } else if (!strncmp(list, "bank", 4)) { /* Flash bank: use kseg0 cached address */ pic32_flash_bank_init(info, CKSEG0ADDR(addr), size); info++; } idx += addrc + sizec; list += len + 1; } /* disable flash write/erase operations */ writel(NVM_WREN, &nvm_regs_p->ctrl.clr); #if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) /* monitor protection ON by default */ flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_MONITOR_BASE, CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]); #endif #ifdef CONFIG_ENV_IS_IN_FLASH /* ENV protection ON by default */ flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR, CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1, &flash_info[0]); #endif return 0; }