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; }
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); }