drivers/mtd/chips/cfi_cmdset_0020.c

Source file repositories/reference/linux-study-clean/drivers/mtd/chips/cfi_cmdset_0020.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/chips/cfi_cmdset_0020.c
Extension
.c
Size
38321 bytes
Lines
1401
Domain
Driver Families
Bucket
drivers/mtd
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (mtd->erasesize < ersize) {
			mtd->erasesize = ersize;
		}
		for (j=0; j<cfi->numchips; j++) {
			mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
			mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
			mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
		}
		offset += (ersize * ernum);
	}

	if (offset != devsize) {
		/* Argh */
		printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
		kfree(mtd->eraseregions);
		goto free_mtd;
	}

	for (i=0; i<mtd->numeraseregions;i++){
		printk(KERN_DEBUG "%d: offset=0x%llx,size=0x%x,blocks=%d\n",
		       i, (unsigned long long)mtd->eraseregions[i].offset,
		       mtd->eraseregions[i].erasesize,
		       mtd->eraseregions[i].numblocks);
	}

	/* Also select the correct geometry setup too */
	mtd->_erase = cfi_staa_erase_varsize;
	mtd->_read = cfi_staa_read;
	mtd->_write = cfi_staa_write_buffers;
	mtd->_writev = cfi_staa_writev;
	mtd->_sync = cfi_staa_sync;
	mtd->_lock = cfi_staa_lock;
	mtd->_unlock = cfi_staa_unlock;
	mtd->_suspend = cfi_staa_suspend;
	mtd->_resume = cfi_staa_resume;
	mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE;
	mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
	mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
	map->fldrv = &cfi_staa_chipdrv;
	__module_get(THIS_MODULE);
	mtd->name = map->name;
	return mtd;

free_mtd:
	kfree(mtd);
free_cmdset_priv:
	kfree(cfi->cmdset_priv);
	return NULL;
}


static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
{
	map_word status, status_OK;
	unsigned long timeo;
	DECLARE_WAITQUEUE(wait, current);
	int suspended = 0;
	unsigned long cmd_addr;
	struct cfi_private *cfi = map->fldrv_priv;

	adr += chip->start;

	/* Ensure cmd read/writes are aligned. */
	cmd_addr = adr & ~(map_bankwidth(map)-1);

	/* Let's determine this according to the interleave only once */
	status_OK = CMD(0x80);

	timeo = jiffies + HZ;
 retry:
	mutex_lock(&chip->mutex);

	/* Check that the chip's ready to talk to us.
	 * If it's in FL_ERASING state, suspend it and make it talk now.
	 */
	switch (chip->state) {
	case FL_ERASING:
		if (!(((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2))
			goto sleep; /* We don't support erase suspend */

		map_write (map, CMD(0xb0), cmd_addr);
		/* If the flash has finished erasing, then 'erase suspend'
		 * appears to make some (28F320) flash devices switch to
		 * 'read' mode.  Make sure that we switch to 'read status'
		 * mode so we get the right data. --rmk
		 */
		map_write(map, CMD(0x70), cmd_addr);
		chip->oldstate = FL_ERASING;
		chip->state = FL_ERASE_SUSPENDING;
		//		printk("Erase suspending at 0x%lx\n", cmd_addr);

Annotation

Implementation Notes