Commit ecb5548d authored by Russell King's avatar Russell King

[MTD] sa1100: Obtain flash device location from platform device.

Remove static flash device location definitions since they're now
obsolete.  Additionally, dynamically allocate driver private data
structures.
parent 1b4e119d
...@@ -14,24 +14,18 @@ ...@@ -14,24 +14,18 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/map.h> #include <linux/mtd/map.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <linux/mtd/concat.h> #include <linux/mtd/concat.h>
#include <asm/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/sizes.h> #include <asm/sizes.h>
#include <asm/mach/flash.h> #include <asm/mach/flash.h>
#include <asm/arch/h3600.h>
#ifndef CONFIG_ARCH_SA1100
#error This is for SA1100 architecture only
#endif
#if 0 #if 0
/* /*
* This is here for documentation purposes only - until these people * This is here for documentation purposes only - until these people
...@@ -133,21 +127,17 @@ static void jornada56x_set_vpp(int vpp) ...@@ -133,21 +127,17 @@ static void jornada56x_set_vpp(int vpp)
#endif #endif
struct sa_subdev_info { struct sa_subdev_info {
unsigned long base;
unsigned long size;
char name[16]; char name[16];
struct map_info map; struct map_info map;
struct mtd_info *mtd; struct mtd_info *mtd;
struct flash_platform_data *data; struct flash_platform_data *data;
}; };
#define NR_SUBMTD 4
struct sa_info { struct sa_info {
struct mtd_partition *parts; struct mtd_partition *parts;
struct mtd_info *mtd; struct mtd_info *mtd;
int num_subdev; int num_subdev;
struct sa_subdev_info subdev[NR_SUBMTD]; struct sa_subdev_info subdev[0];
}; };
static void sa1100_set_vpp(struct map_info *map, int on) static void sa1100_set_vpp(struct map_info *map, int on)
...@@ -162,17 +152,17 @@ static void sa1100_destroy_subdev(struct sa_subdev_info *subdev) ...@@ -162,17 +152,17 @@ static void sa1100_destroy_subdev(struct sa_subdev_info *subdev)
map_destroy(subdev->mtd); map_destroy(subdev->mtd);
if (subdev->map.virt) if (subdev->map.virt)
iounmap(subdev->map.virt); iounmap(subdev->map.virt);
release_mem_region(subdev->base, subdev->size); release_mem_region(subdev->map.phys, subdev->map.size);
} }
static int sa1100_probe_subdev(struct sa_subdev_info *subdev) static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *res)
{ {
unsigned long phys; unsigned long phys;
unsigned int size; unsigned int size;
int ret; int ret;
phys = subdev->base; phys = res->start;
size = subdev->size; size = res->end - phys + 1;
/* /*
* Retrieve the bankwidth from the MSC registers. * Retrieve the bankwidth from the MSC registers.
...@@ -251,31 +241,58 @@ static void sa1100_destroy(struct sa_info *info) ...@@ -251,31 +241,58 @@ static void sa1100_destroy(struct sa_info *info)
for (i = info->num_subdev - 1; i >= 0; i--) for (i = info->num_subdev - 1; i >= 0; i--)
sa1100_destroy_subdev(&info->subdev[i]); sa1100_destroy_subdev(&info->subdev[i]);
kfree(info);
} }
static int __init static struct sa_info *__init
sa1100_setup_mtd(struct sa_info *info, int nr, struct flash_platform_data *flash) sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash)
{ {
struct mtd_info *cdev[nr]; struct sa_info *info;
int i, ret = 0; int nr, size, i, ret = 0;
/*
* Count number of devices.
*/
for (nr = 0; ; nr++)
if (!platform_get_resource(pdev, IORESOURCE_MEM, nr))
break;
if (nr == 0) {
ret = -ENODEV;
goto out;
}
size = sizeof(struct sa_info) + sizeof(struct sa_subdev_info) * nr;
/*
* Allocate the map_info structs in one go.
*/
info = kmalloc(size, GFP_KERNEL);
if (!info) {
ret = -ENOMEM;
goto out;
}
memset(info, 0, size);
/* /*
* Claim and then map the memory regions. * Claim and then map the memory regions.
*/ */
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
struct sa_subdev_info *subdev = &info->subdev[i]; struct sa_subdev_info *subdev = &info->subdev[i];
if (subdev->base == (unsigned long)-1) struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
break; break;
subdev->map.name = subdev->name; subdev->map.name = subdev->name;
sprintf(subdev->name, "sa1100-%d", i); sprintf(subdev->name, "sa1100-%d", i);
subdev->data = flash; subdev->data = flash;
ret = sa1100_probe_subdev(subdev); ret = sa1100_probe_subdev(subdev, res);
if (ret) if (ret)
break; break;
cdev[i] = subdev->mtd;
} }
info->num_subdev = i; info->num_subdev = i;
...@@ -296,10 +313,14 @@ sa1100_setup_mtd(struct sa_info *info, int nr, struct flash_platform_data *flash ...@@ -296,10 +313,14 @@ sa1100_setup_mtd(struct sa_info *info, int nr, struct flash_platform_data *flash
info->mtd = info->subdev[0].mtd; info->mtd = info->subdev[0].mtd;
ret = 0; ret = 0;
} else if (info->num_subdev > 1) { } else if (info->num_subdev > 1) {
#ifdef CONFIG_MTD_CONCAT
struct mtd_info *cdev[nr];
/* /*
* We detected multiple devices. Concatenate them together. * We detected multiple devices. Concatenate them together.
*/ */
#ifdef CONFIG_MTD_CONCAT for (i = 0; i < info->num_subdev; i++)
cdev[i] = info->subdev[i].mtd;
info->mtd = mtd_concat_create(cdev, info->num_subdev, info->mtd = mtd_concat_create(cdev, info->num_subdev,
"sa1100"); "sa1100");
if (info->mtd == NULL) if (info->mtd == NULL)
...@@ -312,188 +333,33 @@ sa1100_setup_mtd(struct sa_info *info, int nr, struct flash_platform_data *flash ...@@ -312,188 +333,33 @@ sa1100_setup_mtd(struct sa_info *info, int nr, struct flash_platform_data *flash
} }
if (ret == 0) if (ret == 0)
return 0; return info;
err: err:
sa1100_destroy(info); sa1100_destroy(info);
return ret; out:
} return ERR_PTR(ret);
static int __init sa1100_locate_flash(struct sa_info *info)
{
int i, nr = -ENODEV;
if (machine_is_adsbitsy()) {
info->subdev[0].base = SA1100_CS1_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_assabet()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
info->subdev[1].base = SA1100_CS1_PHYS; /* neponset */
info->subdev[1].size = SZ_32M;
nr = 2;
}
if (machine_is_badge4()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_64M;
nr = 1;
}
if (machine_is_cerf()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_consus()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_flexanet()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_freebird()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_frodo()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_graphicsclient()) {
info->subdev[0].base = SA1100_CS1_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_graphicsmaster()) {
info->subdev[0].base = SA1100_CS1_PHYS;
info->subdev[0].size = SZ_16M;
nr = 1;
}
if (machine_is_h3xxx()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_huw_webpanel()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_16M;
nr = 1;
}
if (machine_is_itsy()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_jornada56x()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_jornada720()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_nanoengine()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[1].size = SZ_32M;
nr = 1;
}
if (machine_is_pangolin()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_64M;
nr = 1;
}
if (machine_is_pfs168()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_pleb()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_4M;
info->subdev[1].base = SA1100_CS1_PHYS;
info->subdev[1].size = SZ_4M;
nr = 2;
}
if (machine_is_pt_system3()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_16M;
nr = 1;
}
if (machine_is_shannon()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_4M;
nr = 1;
}
if (machine_is_sherman()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_simpad()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_16M;
info->subdev[1].base = SA1100_CS1_PHYS;
info->subdev[1].size = SZ_16M;
nr = 2;
}
if (machine_is_stork()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_32M;
nr = 1;
}
if (machine_is_trizeps()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_16M;
nr = 1;
}
if (machine_is_victor()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_2M;
nr = 1;
}
if (machine_is_yopy()) {
info->subdev[0].base = SA1100_CS0_PHYS;
info->subdev[0].size = SZ_64M;
info->subdev[1].base = SA1100_CS1_PHYS;
info->subdev[1].size = SZ_64M;
nr = 2;
}
return nr;
} }
static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
static struct sa_info sa_info;
static int __init sa1100_mtd_probe(struct device *dev) static int __init sa1100_mtd_probe(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct flash_platform_data *flash = pdev->dev.platform_data; struct flash_platform_data *flash = pdev->dev.platform_data;
struct mtd_partition *parts; struct mtd_partition *parts;
const char *part_type = NULL; const char *part_type = NULL;
struct sa_info *info = &sa_info; struct sa_info *info;
int err, nr_parts = 0; int err, nr_parts = 0;
int nr;
if (!flash) if (!flash)
return -ENODEV; return -ENODEV;
nr = sa1100_locate_flash(info); info = sa1100_setup_mtd(pdev, flash);
if (nr < 0) if (IS_ERR(info)) {
return nr; err = PTR_ERR(info);
err = sa1100_setup_mtd(info, nr, flash);
if (err != 0)
goto out; goto out;
}
/* /*
* Partition selection stuff. * Partition selection stuff.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment