aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2006-05-07 12:16:36 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-05-07 12:16:36 -0400
commit73566edf9b91dd085ddb12033d0ea7288979dd10 (patch)
treeec3810665792713ae97b6bb566f530f77e367586 /drivers
parent422138dd68202fbd8ca9fb0df65e92d733249374 (diff)
[MTD] Convert physmap to platform driver
After dwmw2 let me know it ought to be done, I rewrote the physmap map driver to be a platform driver. I know zilch about the driver model, so I probably botched it in some way, but I've done some tests on an ixp23xx board which uses physmap, and it all seems to work. In order to not break existing physmap users, I've added some compat code that will instantiate a platform device iff CONFIG_MTD_PHYSMAP_LEN is defined and != 0. Also, I've changed the default value for CONFIG_MTD_PHYSMAP_LEN to zero, so that people who inadvertently compile in physmap (or new, platform-style, users of physmap) don't get burned. This works pretty well -- the new physmap driver is a drop-in replacement for the old one, and works on said ixp23xx board without any code changes needed. (This should hold as long as users don't touch 'physmap_map' directly.) Once all physmap users have been converted to instantiate their own platform devices, the compat code can go. (Or we decide that we can change all the in-tree users at the same time, and never merge the compat code.) Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/maps/Kconfig2
-rw-r--r--drivers/mtd/maps/physmap.c256
2 files changed, 188 insertions, 70 deletions
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 80d6810e88ed..b2becd7d4337 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -37,7 +37,7 @@ config MTD_PHYSMAP_START
37config MTD_PHYSMAP_LEN 37config MTD_PHYSMAP_LEN
38 hex "Physical length of flash mapping" 38 hex "Physical length of flash mapping"
39 depends on MTD_PHYSMAP 39 depends on MTD_PHYSMAP
40 default "0x4000000" 40 default "0"
41 help 41 help
42 This is the total length of the mapping of the flash chips on 42 This is the total length of the mapping of the flash chips on
43 your particular board. If there is space, or aliases, in the 43 your particular board. If there is space, or aliases, in the
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index f49ebc3c4606..76ce9bd943aa 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -14,112 +14,230 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <asm/io.h> 17#include <linux/device.h>
18#include <linux/platform_device.h>
18#include <linux/mtd/mtd.h> 19#include <linux/mtd/mtd.h>
19#include <linux/mtd/map.h> 20#include <linux/mtd/map.h>
20#include <linux/config.h> 21#include <linux/config.h>
21#include <linux/mtd/partitions.h> 22#include <linux/mtd/partitions.h>
22#include <linux/mtd/physmap.h> 23#include <linux/mtd/physmap.h>
24#include <asm/io.h>
25#include <asm/mach/flash.h>
23 26
24static struct mtd_info *mymtd; 27struct physmap_flash_info {
25 28 struct mtd_info *mtd;
26struct map_info physmap_map = { 29 struct map_info map;
27 .name = "phys_mapped_flash", 30 struct resource *res;
28 .phys = CONFIG_MTD_PHYSMAP_START, 31#ifdef CONFIG_MTD_PARTITIONS
29 .size = CONFIG_MTD_PHYSMAP_LEN, 32 int nr_parts;
30 .bankwidth = CONFIG_MTD_PHYSMAP_BANKWIDTH, 33 struct mtd_partition *parts;
34#endif
31}; 35};
32 36
37
38static int physmap_flash_remove(struct platform_device *dev)
39{
40 struct physmap_flash_info *info;
41 struct physmap_flash_data *physmap_data;
42
43 info = platform_get_drvdata(dev);
44 if (info == NULL)
45 return 0;
46 platform_set_drvdata(dev, NULL);
47
48 physmap_data = dev->dev.platform_data;
49
50 if (info->mtd != NULL) {
33#ifdef CONFIG_MTD_PARTITIONS 51#ifdef CONFIG_MTD_PARTITIONS
34static struct mtd_partition *mtd_parts; 52 if (info->nr_parts) {
35static int mtd_parts_nb; 53 del_mtd_partitions(info->mtd);
54 kfree(info->parts);
55 } else if (physmap_data->nr_parts) {
56 del_mtd_partitions(info->mtd);
57 } else {
58 del_mtd_device(info->mtd);
59 }
60#else
61 del_mtd_device(info->mtd);
62#endif
63 map_destroy(info->mtd);
64 }
36 65
37static int num_physmap_partitions; 66 if (info->map.virt != NULL)
38static struct mtd_partition *physmap_partitions; 67 iounmap((void *)info->map.virt);
39 68
40static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL}; 69 if (info->res != NULL) {
70 release_resource(info->res);
71 kfree(info->res);
72 }
41 73
42void physmap_set_partitions(struct mtd_partition *parts, int num_parts) 74 return 0;
43{
44 physmap_partitions=parts;
45 num_physmap_partitions=num_parts;
46} 75}
47#endif /* CONFIG_MTD_PARTITIONS */
48 76
49static int __init init_physmap(void) 77static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
78#ifdef CONFIG_MTD_PARTITIONS
79static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
80#endif
81
82static int physmap_flash_probe(struct platform_device *dev)
50{ 83{
51 static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL }; 84 struct physmap_flash_data *physmap_data;
52 const char **type; 85 struct physmap_flash_info *info;
86 const char **probe_type;
87 int err;
88
89 physmap_data = dev->dev.platform_data;
90 if (physmap_data == NULL)
91 return -ENODEV;
92
93 printk(KERN_NOTICE "physmap platform flash device: %.8lx at %.8lx\n",
94 dev->resource->end - dev->resource->start + 1,
95 dev->resource->start);
96
97 info = kmalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
98 if (info == NULL) {
99 err = -ENOMEM;
100 goto err_out;
101 }
102 memset(info, 0, sizeof(*info));
53 103
54 printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys); 104 platform_set_drvdata(dev, info);
55 physmap_map.virt = ioremap(physmap_map.phys, physmap_map.size);
56 105
57 if (!physmap_map.virt) { 106 info->res = request_mem_region(dev->resource->start,
58 printk("Failed to ioremap\n"); 107 dev->resource->end - dev->resource->start + 1,
59 return -EIO; 108 dev->dev.bus_id);
109 if (info->res == NULL) {
110 dev_err(&dev->dev, "Could not reserve memory region\n");
111 err = -ENOMEM;
112 goto err_out;
60 } 113 }
61 114
62 simple_map_init(&physmap_map); 115 info->map.name = dev->dev.bus_id;
116 info->map.phys = dev->resource->start;
117 info->map.size = dev->resource->end - dev->resource->start + 1;
118 info->map.bankwidth = physmap_data->width;
119 info->map.set_vpp = physmap_data->set_vpp;
120
121 info->map.virt = ioremap(info->map.phys, info->map.size);
122 if (info->map.virt == NULL) {
123 dev_err(&dev->dev, "Failed to ioremap flash region\n");
124 err = EIO;
125 goto err_out;
126 }
63 127
64 mymtd = NULL; 128 simple_map_init(&info->map);
65 type = rom_probe_types; 129
66 for(; !mymtd && *type; type++) { 130 probe_type = rom_probe_types;
67 mymtd = do_map_probe(*type, &physmap_map); 131 for (; info->mtd == NULL && *probe_type != NULL; probe_type++)
132 info->mtd = do_map_probe(*probe_type, &info->map);
133 if (info->mtd == NULL) {
134 dev_err(&dev->dev, "map_probe failed\n");
135 err = -ENXIO;
136 goto err_out;
68 } 137 }
69 if (mymtd) { 138 info->mtd->owner = THIS_MODULE;
70 mymtd->owner = THIS_MODULE;
71 139
72#ifdef CONFIG_MTD_PARTITIONS 140#ifdef CONFIG_MTD_PARTITIONS
73 mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes, 141 err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0);
74 &mtd_parts, 0); 142 if (err > 0) {
143 add_mtd_partitions(info->mtd, info->parts, err);
144 return 0;
145 }
75 146
76 if (mtd_parts_nb > 0) 147 if (physmap_data->nr_parts) {
77 { 148 printk(KERN_NOTICE "Using physmap partition information\n");
78 add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb); 149 add_mtd_partitions(info->mtd, physmap_data->parts,
79 return 0; 150 physmap_data->nr_parts);
80 } 151 return 0;
152 }
153#endif
154
155 add_mtd_device(info->mtd);
156 return 0;
157
158err_out:
159 physmap_flash_remove(dev);
160 return err;
161}
162
163static struct platform_driver physmap_flash_driver = {
164 .probe = physmap_flash_probe,
165 .remove = physmap_flash_remove,
166 .driver = {
167 .name = "physmap-flash",
168 },
169};
81 170
82 if (num_physmap_partitions != 0)
83 {
84 printk(KERN_NOTICE
85 "Using physmap partition definition\n");
86 add_mtd_partitions (mymtd, physmap_partitions, num_physmap_partitions);
87 return 0;
88 }
89 171
172#ifdef CONFIG_MTD_PHYSMAP_LEN
173#if CONFIG_MTD_PHYSMAP_LEN != 0
174#warning using PHYSMAP compat code
175#define PHYSMAP_COMPAT
176#endif
90#endif 177#endif
91 add_mtd_device(mymtd);
92 178
93 return 0; 179#ifdef PHYSMAP_COMPAT
94 } 180static struct physmap_flash_data physmap_flash_data = {
181 .width = CONFIG_MTD_PHYSMAP_BANKWIDTH,
182};
95 183
96 iounmap(physmap_map.virt); 184static struct resource physmap_flash_resource = {
97 return -ENXIO; 185 .start = CONFIG_MTD_PHYSMAP_START,
98} 186 .end = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN,
187 .flags = IORESOURCE_MEM,
188};
99 189
100static void __exit cleanup_physmap(void) 190static struct platform_device physmap_flash = {
191 .name = "physmap-flash",
192 .id = 0,
193 .dev = {
194 .platform_data = &physmap_flash_data,
195 },
196 .num_resources = 1,
197 .resource = &physmap_flash_resource,
198};
199
200void physmap_configure(unsigned long addr, unsigned long size,
201 int bankwidth, void (*set_vpp)(struct map_info *, int))
101{ 202{
203 physmap_flash_resource.start = addr;
204 physmap_flash_resource.end = addr + size - 1;
205 physmap_flash_data.width = bankwidth;
206 physmap_flash_data.set_vpp = set_vpp;
207}
208
102#ifdef CONFIG_MTD_PARTITIONS 209#ifdef CONFIG_MTD_PARTITIONS
103 if (mtd_parts_nb) { 210void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
104 del_mtd_partitions(mymtd); 211{
105 kfree(mtd_parts); 212 physmap_flash_data.nr_parts = num_parts;
106 } else if (num_physmap_partitions) { 213 physmap_flash_data.parts = parts;
107 del_mtd_partitions(mymtd); 214}
108 } else { 215#endif
109 del_mtd_device(mymtd);
110 }
111#else
112 del_mtd_device(mymtd);
113#endif 216#endif
114 map_destroy(mymtd);
115 217
116 iounmap(physmap_map.virt); 218static int __init physmap_init(void)
117 physmap_map.virt = NULL; 219{
220 int err;
221
222 err = platform_driver_register(&physmap_flash_driver);
223#ifdef PHYSMAP_COMPAT
224 if (err == 0)
225 platform_device_register(&physmap_flash);
226#endif
227
228 return err;
118} 229}
119 230
120module_init(init_physmap); 231static void __exit physmap_exit(void)
121module_exit(cleanup_physmap); 232{
233#ifdef PHYSMAP_COMPAT
234 platform_device_unregister(&physmap_flash);
235#endif
236 platform_driver_unregister(&physmap_flash_driver);
237}
122 238
239module_init(physmap_init);
240module_exit(physmap_exit);
123 241
124MODULE_LICENSE("GPL"); 242MODULE_LICENSE("GPL");
125MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 243MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");