[MTD] Factor out OF partition support from the NOR driver.
Signed-off-by: Scott Wood <scottwood@freescale.com> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
This commit is contained in:
parent
c0d2a48a65
commit
9a310d2119
|
@ -150,6 +150,14 @@ config MTD_AFS_PARTS
|
||||||
for your particular device. It won't happen automatically. The
|
for your particular device. It won't happen automatically. The
|
||||||
'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
|
'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
|
||||||
|
|
||||||
|
config MTD_OF_PARTS
|
||||||
|
tristate "Flash partition map based on OF description"
|
||||||
|
depends on PPC_OF && MTD_PARTITIONS
|
||||||
|
help
|
||||||
|
This provides a partition parsing function which derives
|
||||||
|
the partition map from the children of the flash node,
|
||||||
|
as described in Documentation/powerpc/booting-without-of.txt.
|
||||||
|
|
||||||
comment "User Modules And Translation Layers"
|
comment "User Modules And Translation Layers"
|
||||||
|
|
||||||
config MTD_CHAR
|
config MTD_CHAR
|
||||||
|
|
|
@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
|
||||||
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
|
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
|
||||||
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
|
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
|
||||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||||
|
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||||
|
|
||||||
# 'Users' - code which presents functionality to userspace.
|
# 'Users' - code which presents functionality to userspace.
|
||||||
obj-$(CONFIG_MTD_CHAR) += mtdchar.o
|
obj-$(CONFIG_MTD_CHAR) += mtdchar.o
|
||||||
|
|
|
@ -80,65 +80,6 @@ static int parse_obsolete_partitions(struct of_device *dev,
|
||||||
|
|
||||||
return nr_parts;
|
return nr_parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devinit parse_partitions(struct of_flash *info,
|
|
||||||
struct of_device *dev)
|
|
||||||
{
|
|
||||||
const char *partname;
|
|
||||||
static const char *part_probe_types[]
|
|
||||||
= { "cmdlinepart", "RedBoot", NULL };
|
|
||||||
struct device_node *dp = dev->node, *pp;
|
|
||||||
int nr_parts, i;
|
|
||||||
|
|
||||||
/* First look for RedBoot table or partitions on the command
|
|
||||||
* line, these take precedence over device tree information */
|
|
||||||
nr_parts = parse_mtd_partitions(info->mtd, part_probe_types,
|
|
||||||
&info->parts, 0);
|
|
||||||
if (nr_parts > 0)
|
|
||||||
return nr_parts;
|
|
||||||
|
|
||||||
/* First count the subnodes */
|
|
||||||
nr_parts = 0;
|
|
||||||
for (pp = of_get_next_child(dp, NULL); pp;
|
|
||||||
pp = of_get_next_child(dp, pp))
|
|
||||||
nr_parts++;
|
|
||||||
|
|
||||||
if (nr_parts == 0)
|
|
||||||
return parse_obsolete_partitions(dev, info, dp);
|
|
||||||
|
|
||||||
info->parts = kzalloc(nr_parts * sizeof(*info->parts),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!info->parts)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
for (pp = of_get_next_child(dp, NULL), i = 0; pp;
|
|
||||||
pp = of_get_next_child(dp, pp), i++) {
|
|
||||||
const u32 *reg;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
reg = of_get_property(pp, "reg", &len);
|
|
||||||
if (!reg || (len != 2*sizeof(u32))) {
|
|
||||||
of_node_put(pp);
|
|
||||||
dev_err(&dev->dev, "Invalid 'reg' on %s\n",
|
|
||||||
dp->full_name);
|
|
||||||
kfree(info->parts);
|
|
||||||
info->parts = NULL;
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
info->parts[i].offset = reg[0];
|
|
||||||
info->parts[i].size = reg[1];
|
|
||||||
|
|
||||||
partname = of_get_property(pp, "label", &len);
|
|
||||||
if (!partname)
|
|
||||||
partname = of_get_property(pp, "name", &len);
|
|
||||||
info->parts[i].name = (char *)partname;
|
|
||||||
|
|
||||||
if (of_get_property(pp, "read-only", &len))
|
|
||||||
info->parts[i].mask_flags = MTD_WRITEABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nr_parts;
|
|
||||||
}
|
|
||||||
#else /* MTD_PARTITIONS */
|
#else /* MTD_PARTITIONS */
|
||||||
#define OF_FLASH_PARTS(info) (0)
|
#define OF_FLASH_PARTS(info) (0)
|
||||||
#define parse_partitions(info, dev) (0)
|
#define parse_partitions(info, dev) (0)
|
||||||
|
@ -213,6 +154,10 @@ static struct mtd_info * __devinit obsolete_probe(struct of_device *dev,
|
||||||
static int __devinit of_flash_probe(struct of_device *dev,
|
static int __devinit of_flash_probe(struct of_device *dev,
|
||||||
const struct of_device_id *match)
|
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 device_node *dp = dev->node;
|
||||||
struct resource res;
|
struct resource res;
|
||||||
struct of_flash *info;
|
struct of_flash *info;
|
||||||
|
@ -275,13 +220,33 @@ static int __devinit of_flash_probe(struct of_device *dev,
|
||||||
}
|
}
|
||||||
info->mtd->owner = THIS_MODULE;
|
info->mtd->owner = THIS_MODULE;
|
||||||
|
|
||||||
err = parse_partitions(info, dev);
|
#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)
|
if (err < 0)
|
||||||
goto err_out;
|
return err;
|
||||||
|
|
||||||
|
#ifdef CONFIG_MTD_OF_PARTS
|
||||||
|
if (err == 0) {
|
||||||
|
err = of_mtd_parse_partitions(&dev->dev, info->mtd,
|
||||||
|
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)
|
if (err > 0)
|
||||||
add_mtd_partitions(info->mtd, OF_FLASH_PARTS(info), err);
|
add_mtd_partitions(info->mtd, info->parts, err);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
add_mtd_device(info->mtd);
|
add_mtd_device(info->mtd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Flash partitions 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/init.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/mtd/mtd.h>
|
||||||
|
#include <linux/mtd/partitions.h>
|
||||||
|
|
||||||
|
int __devinit of_mtd_parse_partitions(struct device *dev,
|
||||||
|
struct mtd_info *mtd,
|
||||||
|
struct device_node *node,
|
||||||
|
struct mtd_partition **pparts)
|
||||||
|
{
|
||||||
|
const char *partname;
|
||||||
|
struct device_node *pp;
|
||||||
|
int nr_parts, i;
|
||||||
|
|
||||||
|
/* First count the subnodes */
|
||||||
|
pp = NULL;
|
||||||
|
nr_parts = 0;
|
||||||
|
while ((pp = of_get_next_child(node, pp)))
|
||||||
|
nr_parts++;
|
||||||
|
|
||||||
|
if (nr_parts == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*pparts = kzalloc(nr_parts * sizeof(**pparts), GFP_KERNEL);
|
||||||
|
if (!*pparts)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
pp = NULL;
|
||||||
|
i = 0;
|
||||||
|
while ((pp = of_get_next_child(node, pp))) {
|
||||||
|
const u32 *reg;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
reg = of_get_property(pp, "reg", &len);
|
||||||
|
if (!reg || (len != 2 * sizeof(u32))) {
|
||||||
|
of_node_put(pp);
|
||||||
|
dev_err(dev, "Invalid 'reg' on %s\n", node->full_name);
|
||||||
|
kfree(*pparts);
|
||||||
|
*pparts = NULL;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
(*pparts)[i].offset = reg[0];
|
||||||
|
(*pparts)[i].size = reg[1];
|
||||||
|
|
||||||
|
partname = of_get_property(pp, "label", &len);
|
||||||
|
if (!partname)
|
||||||
|
partname = of_get_property(pp, "name", &len);
|
||||||
|
(*pparts)[i].name = (char *)partname;
|
||||||
|
|
||||||
|
if (of_get_property(pp, "read-only", &len))
|
||||||
|
(*pparts)[i].mask_flags = MTD_WRITEABLE;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nr_parts;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(of_mtd_parse_partitions);
|
|
@ -71,5 +71,12 @@ extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
|
||||||
|
|
||||||
#define put_partition_parser(p) do { module_put((p)->owner); } while(0)
|
#define put_partition_parser(p) do { module_put((p)->owner); } while(0)
|
||||||
|
|
||||||
#endif
|
struct device;
|
||||||
|
struct device_node;
|
||||||
|
|
||||||
|
int __devinit of_mtd_parse_partitions(struct device *dev,
|
||||||
|
struct mtd_info *mtd,
|
||||||
|
struct device_node *node,
|
||||||
|
struct mtd_partition **pparts);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue