Esempio n. 1
0
static int
fsl_nand_attach(device_t dev)
{
    struct fsl_nand_softc *sc;
    struct nand_id id;
    struct nand_params *param;
    uint32_t num_pages;

    sc = device_get_softc(dev);
    sc->dev = dev;
    sc->dinfo = device_get_ivars(dev);

    sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
                                     RF_ACTIVE);
    if (sc->res == NULL) {
        device_printf(dev, "could not allocate resources!\n");
        return (ENXIO);
    }

    bzero(&sc->fcm, sizeof(sc->fcm));

    /* Init register and check if HW ECC turned on */
    fsl_nand_init_regs(sc);

    /* Chip is probed, so determine number of row address cycles */
    fsl_nand_chip_preprobe(dev, &id);
    param = nand_get_params(&id);
    if (param != NULL) {
        num_pages = (param->chip_size << 20) / param->page_size;
        while(num_pages) {
            sc->row_cycles++;
            num_pages >>= 8;
        }

        sc->fcm.reg_fmr &= ~(FMR_AL);
        sc->fcm.reg_fmr |= (sc->row_cycles - 2) << FMR_AL_SHIFT;
    }
Esempio n. 2
0
static int
nandbus_attach(device_t dev)
{
	device_t child, nfc;
	struct nand_id chip_id;
	struct nandbus_softc *sc;
	struct nandbus_ivar *ivar;
	struct nand_softc *nfc_sc;
	struct nand_params *chip_params;
	uint8_t cs, onfi;

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

	nfc = device_get_parent(dev);
	nfc_sc = device_get_softc(nfc);

	mtx_init(&sc->nandbus_mtx, "nandbus lock", NULL, MTX_DEF);
	cv_init(&sc->nandbus_cv, "nandbus cv");

	/* Check each possible CS for existing nand devices */
	for (cs = 0; cs < NAND_NCS; cs++) {
		nand_debug(NDBG_BUS,"probe chip select %x", cs);

		/* Select & reset chip */
		if (nandbus_select_cs(dev, cs))
			break;

		if (nand_reset(dev))
			continue;

		/* Read manufacturer and device id */
		if (nand_readid(dev, &chip_id.man_id, &chip_id.dev_id))
			continue;

		if (chip_id.man_id == 0xff)
			continue;

		/*
		 * First try to get info from the table.  If that fails, see if
		 * the chip can provide ONFI info.  We check the table first to
		 * allow table entries to override info from chips that are
		 * known to provide bad ONFI data.
		 */
		onfi = 0;
		chip_params = nand_get_params(&chip_id);
		if (chip_params == NULL) {
			nand_probe_onfi(dev, &onfi);
		}

		/*
		 * At this point it appears there is a chip at this chipselect,
		 * so if we can't work with it, whine about it.
		 */
		if (chip_params == NULL && onfi == 0) {
			if (bootverbose || (nand_debug_flag & NDBG_BUS))
				printf("Chip params not found, chipsel: %d "
				    "(manuf: 0x%0x, chipid: 0x%0x, onfi: %d)\n",
				    cs, chip_id.man_id, chip_id.dev_id, onfi);
			continue;
		}

		ivar = malloc(sizeof(struct nandbus_ivar),
		    M_NAND, M_WAITOK);

		if (onfi == 1) {
			ivar->cs = cs;
			ivar->cols = 0;
			ivar->rows = 0;
			ivar->params = NULL;
			ivar->man_id = chip_id.man_id;
			ivar->dev_id = chip_id.dev_id;
			ivar->is_onfi = onfi;
			ivar->chip_cdev_name = nfc_sc->chip_cdev_name;

			child = device_add_child(dev, NULL, -1);
			device_set_ivars(child, ivar);
			continue;
		}

		ivar->cs = cs;
		ivar->cols = 1;
		ivar->rows = 2;
		ivar->params = chip_params;
		ivar->man_id = chip_id.man_id;
		ivar->dev_id = chip_id.dev_id;
		ivar->is_onfi = onfi;
		ivar->chip_cdev_name = nfc_sc->chip_cdev_name;

		/*
		 * Check what type of device we have.
		 * devices bigger than 32MiB have on more row (3)
		 */
		if (chip_params->chip_size > 32)
			ivar->rows++;
		/* Large page devices have one more col (2) */
		if (chip_params->chip_size >= 128 &&
		    chip_params->page_size > 512)
			ivar->cols++;

		child = device_add_child(dev, NULL, -1);
		device_set_ivars(child, ivar);
	}

	bus_generic_attach(dev);
	return (0);
}