drivers/mtd/maps/pxa2xx-flash.c

Source file repositories/reference/linux-study-clean/drivers/mtd/maps/pxa2xx-flash.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/maps/pxa2xx-flash.c
Extension
.c
Size
3428 bytes
Lines
140
Domain
Driver Families
Bucket
drivers/mtd
Inferred role
Driver Families: implementation source
Status
source 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

struct pxa2xx_flash_info {
	struct mtd_info		*mtd;
	struct map_info		map;
};

static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL };

static int pxa2xx_flash_probe(struct platform_device *pdev)
{
	struct flash_platform_data *flash = dev_get_platdata(&pdev->dev);
	struct pxa2xx_flash_info *info;
	struct resource *res;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENODEV;

	info = kzalloc_obj(struct pxa2xx_flash_info);
	if (!info)
		return -ENOMEM;

	info->map.name = flash->name;
	info->map.bankwidth = flash->width;
	info->map.phys = res->start;
	info->map.size = resource_size(res);

	info->map.virt = ioremap(info->map.phys, info->map.size);
	if (!info->map.virt) {
		printk(KERN_WARNING "Failed to ioremap %s\n",
		       info->map.name);
		kfree(info);
		return -ENOMEM;
	}
	info->map.cached = ioremap_cache(info->map.phys, info->map.size);
	if (!info->map.cached)
		printk(KERN_WARNING "Failed to ioremap cached %s\n",
		       info->map.name);
	info->map.inval_cache = pxa2xx_map_inval_cache;
	simple_map_init(&info->map);

	printk(KERN_NOTICE
	       "Probing %s at physical address 0x%08lx"
	       " (%d-bit bankwidth)\n",
	       info->map.name, (unsigned long)info->map.phys,
	       info->map.bankwidth * 8);

	info->mtd = do_map_probe(flash->map_name, &info->map);

	if (!info->mtd) {
		iounmap((void *)info->map.virt);
		if (info->map.cached)
			iounmap(info->map.cached);
		kfree(info);
		return -EIO;
	}
	info->mtd->dev.parent = &pdev->dev;

	mtd_device_parse_register(info->mtd, probes, NULL, flash->parts,
				  flash->nr_parts);

	platform_set_drvdata(pdev, info);
	return 0;
}

static void pxa2xx_flash_remove(struct platform_device *dev)
{
	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);

	mtd_device_unregister(info->mtd);

	map_destroy(info->mtd);
	iounmap(info->map.virt);
	if (info->map.cached)
		iounmap(info->map.cached);
	kfree(info);
}

#ifdef CONFIG_PM
static void pxa2xx_flash_shutdown(struct platform_device *dev)
{
	struct pxa2xx_flash_info *info = platform_get_drvdata(dev);

	if (info && mtd_suspend(info->mtd) == 0)
		mtd_resume(info->mtd);
}
#else
#define pxa2xx_flash_shutdown NULL
#endif

static struct platform_driver pxa2xx_flash_driver = {

Annotation

Implementation Notes