Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 153811
b: refs/heads/master
c: 143070e
h: refs/heads/master
i:
  153809: 75cc7b7
  153807: 277dfaf
v: v3
  • Loading branch information
Stefan Roese authored and David Woodhouse committed Jun 6, 2009
1 parent 30ad780 commit 55399e5
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 57 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 43950a605dc76677f0c74dcd818a57d4df040e12
refs/heads/master: 143070e74630b9557e1bb64d899ff2cc5a1dcb48
199 changes: 143 additions & 56 deletions trunk/drivers/mtd/maps/physmap_of.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,23 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/concat.h>
#include <linux/of.h>
#include <linux/of_platform.h>

struct of_flash_list {
struct mtd_info *mtd;
struct map_info map;
struct resource *res;
};

struct of_flash {
struct mtd_info *mtd;
struct map_info map;
struct resource *res;
struct mtd_info *cmtd;
#ifdef CONFIG_MTD_PARTITIONS
struct mtd_partition *parts;
#endif
int list_size; /* number of elements in of_flash_list */
struct of_flash_list list[0];
};

#ifdef CONFIG_MTD_PARTITIONS
Expand Down Expand Up @@ -88,30 +95,44 @@ static int parse_obsolete_partitions(struct of_device *dev,
static int of_flash_remove(struct of_device *dev)
{
struct of_flash *info;
int i;

info = dev_get_drvdata(&dev->dev);
if (!info)
return 0;
dev_set_drvdata(&dev->dev, NULL);

if (info->mtd) {
#ifdef CONFIG_MTD_CONCAT
if (info->cmtd != info->list[0].mtd) {
del_mtd_device(info->cmtd);
mtd_concat_destroy(info->cmtd);
}
#endif

if (info->cmtd) {
if (OF_FLASH_PARTS(info)) {
del_mtd_partitions(info->mtd);
del_mtd_partitions(info->cmtd);
kfree(OF_FLASH_PARTS(info));
} else {
del_mtd_device(info->mtd);
del_mtd_device(info->cmtd);
}
map_destroy(info->mtd);
}

if (info->map.virt)
iounmap(info->map.virt);
for (i = 0; i < info->list_size; i++) {
if (info->list[i].mtd)
map_destroy(info->list[i].mtd);

if (info->res) {
release_resource(info->res);
kfree(info->res);
if (info->list[i].map.virt)
iounmap(info->list[i].map.virt);

if (info->list[i].res) {
release_resource(info->list[i].res);
kfree(info->list[i].res);
}
}

kfree(info);

return 0;
}

Expand Down Expand Up @@ -164,68 +185,130 @@ static int __devinit of_flash_probe(struct of_device *dev,
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");
int i;
int count;
const u32 *p;
int reg_tuple_size;
struct mtd_info **mtd_list = NULL;

reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);

/*
* Get number of "reg" tuples. Scan for MTD devices on area's
* described by each "reg" region. This makes it possible (including
* the concat support) to support the Intel P30 48F4400 chips which
* consists internally of 2 non-identical NOR chips on one die.
*/
p = of_get_property(dp, "reg", &count);
if (count % reg_tuple_size != 0) {
dev_err(&dev->dev, "Malformed reg property on %s\n",
dev->node->full_name);
err = -EINVAL;
goto err_out;
}

dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
(unsigned long long)res.start, (unsigned long long)res.end);
count /= reg_tuple_size;

err = -ENOMEM;
info = kzalloc(sizeof(*info), GFP_KERNEL);
info = kzalloc(sizeof(struct of_flash) +
sizeof(struct of_flash_list) * count, GFP_KERNEL);
if (!info)
goto err_out;

mtd_list = kzalloc(sizeof(struct mtd_info) * count, 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_name(&dev->dev));
if (!info->res)
goto err_out;
for (i = 0; i < count; i++) {
err = -ENXIO;
if (of_address_to_resource(dp, i, &res)) {
dev_err(&dev->dev, "Can't get IO address from device"
" tree\n");
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;
}
dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
(unsigned long long)res.start,
(unsigned long long)res.end);

err = -EBUSY;
info->list[i].res = request_mem_region(res.start, res.end -
res.start + 1,
dev_name(&dev->dev));
if (!info->list[i].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_name(&dev->dev);
info->map.phys = res.start;
info->map.size = res.end - res.start + 1;
info->map.bankwidth = *width;
info->list[i].map.name = dev_name(&dev->dev);
info->list[i].map.phys = res.start;
info->list[i].map.size = res.end - res.start + 1;
info->list[i].map.bankwidth = *width;

err = -ENOMEM;
info->list[i].map.virt = ioremap(info->list[i].map.phys,
info->list[i].map.size);
if (!info->list[i].map.virt) {
dev_err(&dev->dev, "Failed to ioremap() flash"
" region\n");
goto err_out;
}

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->list[i].map);

simple_map_init(&info->map);
if (probe_type) {
info->list[i].mtd = do_map_probe(probe_type,
&info->list[i].map);
} else {
info->list[i].mtd = obsolete_probe(dev,
&info->list[i].map);
}
mtd_list[i] = info->list[i].mtd;

if (probe_type)
info->mtd = do_map_probe(probe_type, &info->map);
else
info->mtd = obsolete_probe(dev, &info->map);
err = -ENXIO;
if (!info->list[i].mtd) {
dev_err(&dev->dev, "do_map_probe() failed\n");
goto err_out;
} else {
info->list_size++;
}
info->list[i].mtd->owner = THIS_MODULE;
info->list[i].mtd->dev.parent = &dev->dev;
}

err = -ENXIO;
if (!info->mtd) {
dev_err(&dev->dev, "do_map_probe() failed\n");
goto err_out;
err = 0;
if (info->list_size == 1) {
info->cmtd = info->list[0].mtd;
} else if (info->list_size > 1) {
/*
* We detected multiple devices. Concatenate them together.
*/
#ifdef CONFIG_MTD_CONCAT
info->cmtd = mtd_concat_create(mtd_list, info->list_size,
dev_name(&dev->dev));
if (info->cmtd == NULL)
err = -ENXIO;
#else
printk(KERN_ERR "physmap_of: multiple devices "
"found but MTD concat support disabled.\n");
err = -ENXIO;
#endif
}
info->mtd->owner = THIS_MODULE;
info->mtd->dev.parent = &dev->dev;
if (err)
goto err_out;

#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);
err = parse_mtd_partitions(info->cmtd, part_probe_types,
&info->parts, 0);
if (err < 0)
return err;

Expand All @@ -244,15 +327,19 @@ static int __devinit of_flash_probe(struct of_device *dev,
}

if (err > 0)
add_mtd_partitions(info->mtd, info->parts, err);
add_mtd_partitions(info->cmtd, info->parts, err);
else
#endif
add_mtd_device(info->mtd);
add_mtd_device(info->cmtd);

kfree(mtd_list);

return 0;

err_out:
kfree(mtd_list);
of_flash_remove(dev);

return err;
}

Expand Down

0 comments on commit 55399e5

Please sign in to comment.