Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
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));
}
Ejemplo n.º 3
0
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));
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
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);
}