static int lbc_banks_map(struct lbc_softc *sc) { u_long start, size; int error, i; for (i = 0; i < LBC_DEV_MAX; i++) { if (sc->sc_banks[i].size == 0) continue; /* Physical address start/size. */ start = sc->sc_banks[i].pa; size = sc->sc_banks[i].size; /* * Configure LAW for this LBC bank (CS) and map its physical * memory region into KVA. */ error = law_enable(OCP85XX_TGTIF_LBC, start, size); if (error) return (error); sc->sc_banks[i].va = (vm_offset_t)pmap_mapdev(start, size); if (sc->sc_banks[i].va == 0) { lbc_banks_unmap(sc); return (ENOSPC); } } return (0); }
static int ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp) { u_long addr, size; switch (type) { case SYS_RES_MEMORY: switch (trgt) { case OCP85XX_TGTIF_PCI0: addr = 0x80000000; size = 0x10000000; break; case OCP85XX_TGTIF_PCI1: addr = 0x90000000; size = 0x10000000; break; case OCP85XX_TGTIF_PCI2: addr = 0xA0000000; size = 0x10000000; break; default: return (EINVAL); } break; case SYS_RES_IOPORT: switch (trgt) { case OCP85XX_TGTIF_PCI0: addr = 0xfee00000; size = 0x00010000; break; case OCP85XX_TGTIF_PCI1: addr = 0xfee10000; size = 0x00010000; break; case OCP85XX_TGTIF_PCI2: addr = 0xfee20000; size = 0x00010000; break; default: return (EINVAL); } break; default: return (EINVAL); } *startp = addr; *countp = size; return (law_enable(trgt, *startp, *countp)); }
int bman_portals_attach(device_t dev) { struct dpaa_portals_softc *sc; sc = bp_sc = device_get_softc(dev); /* Map bman portal to physical address space */ if (law_enable(OCP85XX_TGTIF_BMAN, sc->sc_dp_pa, sc->sc_dp_size)) { bman_portals_detach(dev); return (ENXIO); } /* Set portal properties for XX_VirtToPhys() */ XX_PortalSetInfo(dev); return (bus_generic_attach(dev)); }
static int lbc_banks_map(struct lbc_softc *sc) { vm_paddr_t end, start; vm_size_t size; u_int i, r, ranges, s; int error; bzero(sc->sc_range, sizeof(sc->sc_range)); /* * Determine number of discontiguous address ranges to program. */ ranges = 0; for (i = 0; i < LBC_DEV_MAX; i++) { size = sc->sc_banks[i].size; if (size == 0) continue; start = sc->sc_banks[i].addr; for (r = 0; r < ranges; r++) { /* Avoid wrap-around bugs. */ end = sc->sc_range[r].addr - 1 + sc->sc_range[r].size; if (start > 0 && end == start - 1) { sc->sc_range[r].size += size; break; } /* Avoid wrap-around bugs. */ end = start - 1 + size; if (sc->sc_range[r].addr > 0 && end == sc->sc_range[r].addr - 1) { sc->sc_range[r].addr = start; sc->sc_range[r].size += size; break; } } if (r == ranges) { /* New range; add using insertion sort */ r = 0; while (r < ranges && sc->sc_range[r].addr < start) r++; for (s = ranges; s > r; s--) sc->sc_range[s] = sc->sc_range[s-1]; sc->sc_range[r].addr = start; sc->sc_range[r].size = size; ranges++; } } /* * Ranges are sorted so quickly go over the list to merge ranges * that grew toward each other while building the ranges. */ r = 0; while (r < ranges - 1) { end = sc->sc_range[r].addr + sc->sc_range[r].size; if (end != sc->sc_range[r+1].addr) { r++; continue; } sc->sc_range[r].size += sc->sc_range[r+1].size; for (s = r + 1; s < ranges - 1; s++) sc->sc_range[s] = sc->sc_range[s+1]; bzero(&sc->sc_range[s], sizeof(sc->sc_range[s])); ranges--; } /* * Configure LAW for the LBC ranges and map the physical memory * range into KVA. */ for (r = 0; r < ranges; r++) { start = sc->sc_range[r].addr; size = sc->sc_range[r].size; error = law_enable(OCP85XX_TGTIF_LBC, start, size); if (error) return (error); sc->sc_range[r].kva = (vm_offset_t)pmap_mapdev(start, size); } /* XXX: need something better here? */ if (ranges == 0) return (EINVAL); /* Assign KVA to banks based on the enclosing range. */ for (i = 0; i < LBC_DEV_MAX; i++) { size = sc->sc_banks[i].size; if (size == 0) continue; start = sc->sc_banks[i].addr; for (r = 0; r < ranges; r++) { end = sc->sc_range[r].addr - 1 + sc->sc_range[r].size; if (start >= sc->sc_range[r].addr && start - 1 + size <= end) break; } if (r < ranges) { sc->sc_banks[i].kva = sc->sc_range[r].kva + (start - sc->sc_range[r].addr); } } return (0); }
static int lbc_init_child(device_t dev, device_t child) { struct lbc_softc *sc; struct lbc_devinfo *dinfo; const struct lbc_resource *res; u_long start, size; uint32_t regbuff; int error, unit; sc = device_get_softc(dev); dinfo = device_get_ivars(child); res = mpc85xx_lbc_resources; regbuff = 0; unit = -1; for (; res->lbr_devtype; res++) { if (res->lbr_unit != dinfo->lbc_unit) continue; start = res->lbr_base_addr; size = res->lbr_size; unit = res->lbr_unit; /* * Configure LAW for this LBC device and map its physical * memory region into KVA */ error = law_enable(OCP85XX_TGTIF_LBC, start, size); if (error) return (error); sc->sc_kva[unit] = (vm_offset_t)pmap_mapdev(start, size); if (sc->sc_kva[unit] == 0) { law_disable(OCP85XX_TGTIF_LBC, start, size); return (ENOSPC); } /* * Compute and program BR value */ regbuff |= start; switch (res->lbr_port_size) { case 8: regbuff |= (1 << 11); break; case 16: regbuff |= (2 << 11); break; case 32: regbuff |= (3 << 11); break; default: error = EINVAL; goto fail; } regbuff |= (res->lbr_decc << 9); regbuff |= (res->lbr_wp << 8); regbuff |= (res->lbr_msel << 5); regbuff |= (res->lbr_atom << 2); regbuff |= 1; lbc_write_reg(sc, LBC85XX_BR(unit), regbuff); /* * Compute and program OR value */ regbuff = 0; regbuff |= lbc_address_mask(size); switch (res->lbr_msel) { case LBCRES_MSEL_GPCM: /* TODO Add flag support for option registers */ regbuff |= 0x00000ff7; break; case LBCRES_MSEL_FCM: printf("FCM mode not supported yet!"); error = ENOSYS; goto fail; case LBCRES_MSEL_UPMA: case LBCRES_MSEL_UPMB: case LBCRES_MSEL_UPMC: printf("UPM mode not supported yet!"); error = ENOSYS; goto fail; } lbc_write_reg(sc, LBC85XX_OR(unit), regbuff); return (0); } fail: if (unit != -1) { law_disable(OCP85XX_TGTIF_LBC, start, size); pmap_unmapdev(sc->sc_kva[unit], size); return (error); } else return (ENOENT); }
static int rb_nand_attach(device_t dev) { struct rb_nand_softc *sc; phandle_t node; uint32_t ale[2],cle[2],nce[2],rdy[2]; u_long size,start; int err; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); if (OF_getprop(node, "ale", ale, sizeof(ale)) <= 0) { return (ENXIO); } if (OF_getprop(node, "cle", cle, sizeof(cle)) <= 0) { return (ENXIO); } if (OF_getprop(node, "nce", nce, sizeof(nce)) <= 0) { return (ENXIO); } if (OF_getprop(node, "rdy", rdy, sizeof(rdy)) <= 0) { return (ENXIO); } if (ale[0] != cle[0] || ale[0] != nce[0] || ale[0] != rdy[0]) { device_printf(dev, "GPIO handles for signals must match.\n"); return (ENXIO); } sc->sc_ale_pin = ale[1]; sc->sc_cle_pin = cle[1]; sc->sc_nce_pin = nce[1]; sc->sc_rdy_pin = rdy[1]; sc->sc_gpio = OF_device_from_xref(ale[0]); if (sc->sc_gpio == NULL) { device_printf(dev, "No GPIO resource found!\n"); return (ENXIO); } sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid, RF_ACTIVE); if (sc->sc_mem == NULL) { device_printf(dev, "could not allocate resources!\n"); return (ENXIO); } start = rman_get_start(sc->sc_mem); size = rman_get_size(sc->sc_mem); if (law_enable(OCP85XX_TGTIF_LBC, start, size) != 0) { bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->sc_mem); device_printf(dev, "could not allocate local address window.\n"); return (ENXIO); } nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL); err = nandbus_create(dev); return (err); }