/* * board specific setup should have ensured the SPI clock used here * matches what the READ command supports, at least until this driver * understands FAST_READ (for clocks over 25 MHz). */ static int __devinit m25p_probe(struct spi_device *spi) { struct flash_platform_data *data; struct m25p *flash; struct flash_info *info; unsigned i; uint64_t tmpdiv; /* Platform data helps sort out which chip type we have, as * well as how this board partitions it. If we don't have * a chip ID, try the JEDEC id commands; they'll work for most * newer chips, even if we don't recognize the particular chip. */ data = spi->dev.platform_data; if (data && data->type) { for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) { if (strcmp(data->type, info->name) == 0) break; } /* unrecognized chip? */ if (i == ARRAY_SIZE(m25p_data)) { DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n", spi->dev.bus_id, data->type); info = NULL; /* recognized; is that chip really what's there? */ } else if (info->jedec_id) { struct flash_info *chip = jedec_probe(spi); if (!chip || chip != info) { dev_warn(&spi->dev, "found %s, expected %s\n", chip ? chip->name : "UNKNOWN", info->name); info = NULL; } } } else info = jedec_probe(spi); if (!info) return -ENODEV; flash = kzalloc(sizeof *flash, GFP_KERNEL); if (!flash) return -ENOMEM; flash->spi = spi; mutex_init(&flash->lock); dev_set_drvdata(&spi->dev, flash); if (data && data->name) flash->mtd.name = data->name; else flash->mtd.name = spi->dev.bus_id; flash->mtd.type = MTD_NORFLASH; flash->mtd.writesize = 1; flash->mtd.flags = MTD_CAP_NORFLASH; flash->mtd.size = info->sector_size * info->n_sectors; flash->mtd.erase = m25p80_erase; flash->mtd.read = m25p80_read; flash->mtd.write = m25p80_write; /* prefer "small sector" erase if possible */ if (info->flags & SECT_4K) { flash->erase_opcode = OPCODE_BE_4K; flash->mtd.erasesize = 4096; } else { flash->erase_opcode = OPCODE_SE; flash->mtd.erasesize = info->sector_size; } tmpdiv = (uint64_t) info->sector_size * info->n_sectors; do_div(tmpdiv, flash->mtd.erasesize); flash->mtd.num_eraseblocks = tmpdiv; dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name, device_size(&(flash->mtd)) >> (ffs(1024)-1)); DEBUG(MTD_DEBUG_LEVEL2, "mtd .name = %s, .size = 0x%.8x (%uMiB) " ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", flash->mtd.name, flash->mtd.size, flash->mtd.size / (1024*1024), flash->mtd.erasesize, flash->mtd.erasesize / 1024, flash->mtd.numeraseregions); if (flash->mtd.numeraseregions) for (i = 0; i < flash->mtd.numeraseregions; i++) DEBUG(MTD_DEBUG_LEVEL2, "mtd.eraseregions[%d] = { .offset = 0x%.8x, " ".erasesize = 0x%.8x (%uKiB), " ".numblocks = %d }\n", i, flash->mtd.eraseregions[i].offset, flash->mtd.eraseregions[i].erasesize, flash->mtd.eraseregions[i].erasesize / 1024, flash->mtd.eraseregions[i].numblocks); /* partitions should match sector boundaries; and it may be good to * use readonly partitions for writeprotected sectors (BP2..BP0). */ if (mtd_has_partitions()) { struct mtd_partition *parts = NULL; int nr_parts = 0; #ifdef CONFIG_MTD_CMDLINE_PARTS static const char *part_probes[] = { "cmdlinepart", NULL, }; nr_parts = parse_mtd_partitions(&flash->mtd, part_probes, &parts, 0); #endif if (nr_parts <= 0 && data && data->parts) { parts = data->parts; nr_parts = data->nr_parts; } if (nr_parts > 0) { for (i = 0; i < nr_parts; i++) { DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " "{.name = %s, .offset = 0x%.8x, " ".size = 0x%.8x (%uKiB) }\n", i, parts[i].name, parts[i].offset, parts[i].size, parts[i].size / 1024); } flash->partitioned = 1; return add_mtd_partitions(&flash->mtd, parts, nr_parts); } } else if (data->nr_parts) dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", data->nr_parts, data->name); return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0; }
int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, enum read_mode mode) { struct flash_info *info; struct flash_platform_data *data; struct device *dev = nor->dev; struct mtd_info *mtd = nor->mtd; struct device_node *np = dev->of_node; int ret; int i; ret = spi_nor_check(nor); if (ret) return ret; /* Platform data helps sort out which chip type we have, as * well as how this board partitions it. If we don't have * a chip ID, try the JEDEC id commands; they'll work for most * newer chips, even if we don't recognize the particular chip. */ data = dev_get_platdata(dev); if (data && data->type) { const struct spi_device_id *plat_id; for (i = 0; i < ARRAY_SIZE(spi_nor_ids) - 1; i++) { plat_id = &spi_nor_ids[i]; if (strcmp(data->type, plat_id->name)) continue; break; } if (i < ARRAY_SIZE(spi_nor_ids) - 1) id = plat_id; else dev_warn(dev, "unrecognized id %s\n", data->type); } info = (void *)id->driver_data; if (info->jedec_id) { const struct spi_device_id *jid; jid = jedec_probe(nor); if (IS_ERR(jid)) { return PTR_ERR(jid); } else if (jid != id) { /* * JEDEC knows better, so overwrite platform ID. We * can't trust partitions any longer, but we'll let * mtd apply them anyway, since some partitions may be * marked read-only, and we don't want to lose that * information, even if it's not 100% accurate. */ dev_warn(dev, "found %s, expected %s\n", jid->name, id->name); id = jid; info = (void *)jid->driver_data; } } mutex_init(&nor->lock); /* * Atmel, SST and Intel/Numonyx serial nor tend to power * up with the software protection bits set */ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL || JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL || JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) { write_enable(nor); write_sr(nor, 0); } if (data && data->name) mtd->name = data->name; else mtd->name = dev_name(dev); mtd->type = MTD_NORFLASH; mtd->writesize = 1; mtd->flags = MTD_CAP_NORFLASH; mtd->size = info->sector_size * info->n_sectors; mtd->_erase = spi_nor_erase; mtd->_read = spi_nor_read; /* nor protection support for STmicro chips */ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { mtd->_lock = spi_nor_lock; mtd->_unlock = spi_nor_unlock; } /* sst nor chips use AAI word program */ if (info->flags & SST_WRITE) mtd->_write = sst_write; else mtd->_write = spi_nor_write; /* prefer "small sector" erase if possible */ if (info->flags & SECT_4K) { nor->erase_opcode = SPINOR_OP_BE_4K; mtd->erasesize = 4096; } else if (info->flags & SECT_4K_PMC) { nor->erase_opcode = SPINOR_OP_BE_4K_PMC; mtd->erasesize = 4096; } else { nor->erase_opcode = SPINOR_OP_SE; mtd->erasesize = info->sector_size; } if (info->flags & SPI_NOR_NO_ERASE) mtd->flags |= MTD_NO_ERASE; mtd->dev.parent = dev; nor->page_size = info->page_size; mtd->writebufsize = nor->page_size; if (np) { /* If we were instantiated by DT, use it */ if (of_property_read_bool(np, "m25p,fast-read")) nor->flash_read = SPI_NOR_FAST; else nor->flash_read = SPI_NOR_NORMAL; } else { /* If we weren't instantiated by DT, default to fast-read */ nor->flash_read = SPI_NOR_FAST; } /* Some devices cannot do fast-read, no matter what DT tells us */ if (info->flags & SPI_NOR_NO_FR) nor->flash_read = SPI_NOR_NORMAL; /* Quad/Dual-read mode takes precedence over fast/normal */ if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { ret = set_quad_mode(nor, info->jedec_id); if (ret) { dev_err(dev, "quad mode not supported\n"); return ret; } nor->flash_read = SPI_NOR_QUAD; } else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) { nor->flash_read = SPI_NOR_DUAL; } /* Default commands */ switch (nor->flash_read) { case SPI_NOR_QUAD: nor->read_opcode = SPINOR_OP_READ_1_1_4; break; case SPI_NOR_DUAL: nor->read_opcode = SPINOR_OP_READ_1_1_2; break; case SPI_NOR_FAST: nor->read_opcode = SPINOR_OP_READ_FAST; break; case SPI_NOR_NORMAL: nor->read_opcode = SPINOR_OP_READ; break; default: dev_err(dev, "No Read opcode defined\n"); return -EINVAL; } nor->program_opcode = SPINOR_OP_PP; if (info->addr_width) nor->addr_width = info->addr_width; else if (mtd->size > 0x1000000) { /* enable 4-byte addressing if the device exceeds 16MiB */ nor->addr_width = 4; if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { /* Dedicated 4-byte command set */ switch (nor->flash_read) { case SPI_NOR_QUAD: nor->read_opcode = SPINOR_OP_READ4_1_1_4; break; case SPI_NOR_DUAL: nor->read_opcode = SPINOR_OP_READ4_1_1_2; break; case SPI_NOR_FAST: nor->read_opcode = SPINOR_OP_READ4_FAST; break; case SPI_NOR_NORMAL: nor->read_opcode = SPINOR_OP_READ4; break; } nor->program_opcode = SPINOR_OP_PP_4B; /* No small sector erase for 4-byte command set */ nor->erase_opcode = SPINOR_OP_SE_4B; mtd->erasesize = info->sector_size; } else set_4byte(nor, info->jedec_id, 1); } else { nor->addr_width = 3; } nor->read_dummy = spi_nor_read_dummy_cycles(nor); dev_info(dev, "%s (%lld Kbytes)\n", id->name, (long long)mtd->size >> 10); dev_dbg(dev, "mtd .name = %s, .size = 0x%llx (%lldMiB), " ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20), mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions); if (mtd->numeraseregions) for (i = 0; i < mtd->numeraseregions; i++) dev_dbg(dev, "mtd.eraseregions[%d] = { .offset = 0x%llx, " ".erasesize = 0x%.8x (%uKiB), " ".numblocks = %d }\n", i, (long long)mtd->eraseregions[i].offset, mtd->eraseregions[i].erasesize, mtd->eraseregions[i].erasesize / 1024, mtd->eraseregions[i].numblocks); return 0; }