⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 physmap_of.c

📁 基于linux-2.6.28的mtd驱动
💻 C
字号:
/* * Flash mappings described by the OF (or flattened) device tree * * Copyright (C) 2006 MontaVista Software Inc. * Author: Vitaly Wool <vwool@ru.mvista.com> * * Revised to handle newer style flash binding by: *   Copyright (C) 2007 David Gibson, IBM Corporation. * * This program is free software; you can redistribute  it and/or modify it * under  the terms of  the GNU General  Public License as published by the * Free Software Foundation;  either version 2 of the  License, or (at your * option) any later version. */#include <linux/module.h>#include <linux/types.h>#include <linux/init.h>#include <linux/device.h>#include <linux/mtd/mtd.h>#include <linux/mtd/map.h>#include <linux/mtd/partitions.h>#include <linux/of.h>#include <linux/of_platform.h>struct of_flash {	struct mtd_info		*mtd;	struct map_info		map;	struct resource		*res;#ifdef CONFIG_MTD_PARTITIONS	struct mtd_partition	*parts;#endif};#ifdef CONFIG_MTD_PARTITIONS#define OF_FLASH_PARTS(info)	((info)->parts)static int parse_obsolete_partitions(struct of_device *dev,				     struct of_flash *info,				     struct device_node *dp){	int i, plen, nr_parts;	const struct {		u32 offset, len;	} *part;	const char *names;	part = of_get_property(dp, "partitions", &plen);	if (!part)		return 0; /* No partitions found */	dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");	nr_parts = plen / sizeof(part[0]);	info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);	if (!info->parts)		return -ENOMEM;	names = of_get_property(dp, "partition-names", &plen);	for (i = 0; i < nr_parts; i++) {		info->parts[i].offset = part->offset;		info->parts[i].size   = part->len & ~1;		if (part->len & 1) /* bit 0 set signifies read only partition */			info->parts[i].mask_flags = MTD_WRITEABLE;		if (names && (plen > 0)) {			int len = strlen(names) + 1;			info->parts[i].name = (char *)names;			plen -= len;			names += len;		} else {			info->parts[i].name = "unnamed";		}		part++;	}	return nr_parts;}#else /* MTD_PARTITIONS */#define	OF_FLASH_PARTS(info)		(0)#define parse_partitions(info, dev)	(0)#endif /* MTD_PARTITIONS */static int of_flash_remove(struct of_device *dev){	struct of_flash *info;	info = dev_get_drvdata(&dev->dev);	if (!info)		return 0;	dev_set_drvdata(&dev->dev, NULL);	if (info->mtd) {		if (OF_FLASH_PARTS(info)) {			del_mtd_partitions(info->mtd);			kfree(OF_FLASH_PARTS(info));		} else {			del_mtd_device(info->mtd);		}		map_destroy(info->mtd);	}	if (info->map.virt)		iounmap(info->map.virt);	if (info->res) {		release_resource(info->res);		kfree(info->res);	}	return 0;}/* Helper function to handle probing of the obsolete "direct-mapped" * compatible binding, which has an extra "probe-type" property * describing the type of flash probe necessary. */static struct mtd_info * __devinit obsolete_probe(struct of_device *dev,						  struct map_info *map){	struct device_node *dp = dev->node;	const char *of_probe;	struct mtd_info *mtd;	static const char *rom_probe_types[]		= { "cfi_probe", "jedec_probe", "map_rom"};	int i;	dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "		 "flash binding\n");	of_probe = of_get_property(dp, "probe-type", NULL);	if (!of_probe) {		for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {			mtd = do_map_probe(rom_probe_types[i], map);			if (mtd)				return mtd;		}		return NULL;	} else if (strcmp(of_probe, "CFI") == 0) {		return do_map_probe("cfi_probe", map);	} else if (strcmp(of_probe, "JEDEC") == 0) {		return do_map_probe("jedec_probe", map);	} else {		if (strcmp(of_probe, "ROM") != 0)			dev_warn(&dev->dev, "obsolete_probe: don't know probe "				 "type '%s', mapping as rom\n", of_probe);		return do_map_probe("mtd_rom", map);	}}static int __devinit of_flash_probe(struct of_device *dev,				    const struct of_device_id *match){#ifdef CONFIG_MTD_PARTITIONS	static const char *part_probe_types[]		= { "cmdlinepart", "RedBoot", NULL };#endif	struct device_node *dp = dev->node;	struct resource res;	struct of_flash *info;	const char *probe_type = match->data;	const u32 *width;	int err;	err = -ENXIO;	if (of_address_to_resource(dp, 0, &res)) {		dev_err(&dev->dev, "Can't get IO address from device tree\n");		goto err_out;	}       	dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",		(unsigned long long)res.start, (unsigned long long)res.end);	err = -ENOMEM;	info = kzalloc(sizeof(*info), GFP_KERNEL);	if (!info)		goto err_out;	dev_set_drvdata(&dev->dev, info);	err = -EBUSY;	info->res = request_mem_region(res.start, res.end - res.start + 1,				       dev->dev.bus_id);	if (!info->res)		goto err_out;	err = -ENXIO;	width = of_get_property(dp, "bank-width", NULL);	if (!width) {		dev_err(&dev->dev, "Can't get bank width from device tree\n");		goto err_out;	}	info->map.name = dev->dev.bus_id;	info->map.phys = res.start;	info->map.size = res.end - res.start + 1;	info->map.bankwidth = *width;	err = -ENOMEM;	info->map.virt = ioremap(info->map.phys, info->map.size);	if (!info->map.virt) {		dev_err(&dev->dev, "Failed to ioremap() flash region\n");		goto err_out;	}	simple_map_init(&info->map);	if (probe_type)		info->mtd = do_map_probe(probe_type, &info->map);	else		info->mtd = obsolete_probe(dev, &info->map);	err = -ENXIO;	if (!info->mtd) {		dev_err(&dev->dev, "do_map_probe() failed\n");		goto err_out;	}	info->mtd->owner = THIS_MODULE;#ifdef CONFIG_MTD_PARTITIONS	/* First look for RedBoot table or partitions on the command	 * line, these take precedence over device tree information */	err = parse_mtd_partitions(info->mtd, part_probe_types,	                           &info->parts, 0);	if (err < 0)		return err;#ifdef CONFIG_MTD_OF_PARTS	if (err == 0) {		err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);		if (err < 0)			return err;	}#endif	if (err == 0) {		err = parse_obsolete_partitions(dev, info, dp);		if (err < 0)			return err;	}	if (err > 0)		add_mtd_partitions(info->mtd, info->parts, err);	else#endif		add_mtd_device(info->mtd);	return 0;err_out:	of_flash_remove(dev);	return err;}static struct of_device_id of_flash_match[] = {	{		.compatible	= "cfi-flash",		.data		= (void *)"cfi_probe",	},	{		/* FIXME: JEDEC chips can't be safely and reliably		 * probed, although the mtd code gets it right in		 * practice most of the time.  We should use the		 * vendor and device ids specified by the binding to		 * bypass the heuristic probe code, but the mtd layer		 * provides, at present, no interface for doing so		 * :(. */		.compatible	= "jedec-flash",		.data		= (void *)"jedec_probe",	},	{		.type		= "rom",		.compatible	= "direct-mapped"	},	{ },};MODULE_DEVICE_TABLE(of, of_flash_match);static struct of_platform_driver of_flash_driver = {	.name		= "of-flash",	.match_table	= of_flash_match,	.probe		= of_flash_probe,	.remove		= of_flash_remove,};static int __init of_flash_init(void){	return of_register_platform_driver(&of_flash_driver);}static void __exit of_flash_exit(void){	of_unregister_platform_driver(&of_flash_driver);}module_init(of_flash_init);module_exit(of_flash_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");MODULE_DESCRIPTION("Device tree based MTD map driver");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -