Example #1
0
static void
fsl_nand_init_regs(struct fsl_nand_softc *sc)
{
    uint32_t or_v, br_v;
    device_t dev;

    dev = sc->dev;

    sc->fcm.reg_fmr = (15 << FMR_CWTO_SHIFT);

    /*
     * Setup 4 row cycles and hope that chip ignores superfluous address
     * bytes.
     */
    sc->fcm.reg_fmr |= (2 << FMR_AL_SHIFT);

    /* Reprogram BR(x) */
    br_v = lbc_read_reg(dev, LBC85XX_BR(sc->dinfo->di_bank));
    br_v &= 0xffff8000;
    br_v |= 1 << 11;	/* 8-bit port size */
    br_v |= 0 << 9;		/* No ECC checking and generation */
    br_v |= 1 << 5;		/* FCM machine */
    br_v |= 1;		/* Valid */
    lbc_write_reg(dev, LBC85XX_BR(sc->dinfo->di_bank), br_v);

    /* Reprogram OR(x) */
    or_v = lbc_read_reg(dev, LBC85XX_OR(sc->dinfo->di_bank));
    or_v &= 0xfffffc00;
    or_v |= 0x03AE;		/* Default POR timing */
    lbc_write_reg(dev, LBC85XX_OR(sc->dinfo->di_bank), or_v);

    if (or_v & OR_FCM_PAGESIZE) {
        sc->pgsz = FSL_LARGE_PAGE_SIZE;
        sc->col_cycles = 2;
        nand_debug(NDBG_DRV, "%s: large page NAND device at #%d",
                   device_get_nameunit(dev), sc->dinfo->di_bank);
    } else {
        sc->pgsz = FSL_SMALL_PAGE_SIZE;
        sc->col_cycles = 1;
        nand_debug(NDBG_DRV, "%s: small page NAND device at #%d",
                   device_get_nameunit(dev), sc->dinfo->di_bank);
    }
}
Example #2
0
static int
lbc_banks_enable(struct lbc_softc *sc)
{
	u_long size;
	uint32_t regval;
	int error, i;

	for (i = 0; i < LBC_DEV_MAX; i++) {
		size = sc->sc_banks[i].size;
		if (size == 0)
			continue;
		/*
		 * Compute and program BR value.
		 */
		regval = 0;
		regval |= sc->sc_banks[i].pa;

		switch (sc->sc_banks[i].width) {
		case 8:
			regval |= (1 << 11);
			break;
		case 16:
			regval |= (2 << 11);
			break;
		case 32:
			regval |= (3 << 11);
			break;
		default:
			error = EINVAL;
			goto fail;
		}
		regval |= (sc->sc_banks[i].decc << 9);
		regval |= (sc->sc_banks[i].wp << 8);
		regval |= (sc->sc_banks[i].msel << 5);
		regval |= (sc->sc_banks[i].atom << 2);
		regval |= 1;

		lbc_write_reg(sc, LBC85XX_BR(i), regval);

		/*
		 * Compute and program OR value.
		 */
		regval = 0;
		regval |= lbc_address_mask(size);

		switch (sc->sc_banks[i].msel) {
		case LBCRES_MSEL_GPCM:
			/* TODO Add flag support for option registers */
			regval |= 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(i), regval);
	}

	/*
	 * Initialize configuration register:
	 * - enable Local Bus
	 * - set data buffer control signal function
	 * - disable parity byte select
	 * - set ECC parity type
	 * - set bus monitor timing and timer prescale
	 */
	lbc_write_reg(sc, LBC85XX_LBCR, 0);

	/*
	 * Initialize clock ratio register:
	 * - disable PLL bypass mode
	 * - configure LCLK delay cycles for the assertion of LALE
	 * - set system clock divider
	 */
	lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008);

	return (0);

fail:
	lbc_banks_unmap(sc);
	return (error);
}
Example #3
0
static int
lbc_attach(device_t dev)
{
	struct lbc_softc *sc;
	struct rman *rm;
	const struct lbc_resource *lbcres;
	int error;

	sc = device_get_softc(dev);
	sc->sc_dev = dev;

	sc->sc_rid = 0;
	sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
	    RF_ACTIVE);
	if (sc->sc_res == NULL)
		return (ENXIO);

	sc->sc_bst = rman_get_bustag(sc->sc_res);
	sc->sc_bsh = rman_get_bushandle(sc->sc_res);

	rm = &sc->sc_rman;
	rm->rm_type = RMAN_ARRAY;
	rm->rm_descr = "MPC85XX Local Bus Space";
	rm->rm_start = 0UL;
	rm->rm_end = ~0UL;
	error = rman_init(rm);
	if (error)
		goto fail;

	error = rman_manage_region(rm, rm->rm_start, rm->rm_end);
	if (error) {
		rman_fini(rm);
		goto fail;
	}

	/*
	 * Initialize configuration register:
	 * - enable Local Bus
	 * - set data buffer control signal function
	 * - disable parity byte select
	 * - set ECC parity type
	 * - set bus monitor timing and timer prescale
	 */
	lbc_write_reg(sc, LBC85XX_LBCR, 0x00000000);

	/*
	 * Initialize clock ratio register:
	 * - disable PLL bypass mode
	 * - configure LCLK delay cycles for the assertion of LALE
	 * - set system clock divider
	 */
	lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008);

	lbcres = mpc85xx_lbc_resources;

	for (; lbcres->lbr_devtype; lbcres++)
		if (!lbc_mk_child(dev, lbcres)) {
			error = ENXIO;
			goto fail;
		}

	return (bus_generic_attach(dev));

fail:
	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
	return (error);
}
Example #4
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);
}