aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/maps/Kconfig2
-rw-r--r--drivers/mtd/maps/physmap.c256
-rw-r--r--include/linux/mtd/physmap.h21
3 files changed, 196 insertions, 83 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>");
diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
index c7b8bcdef013..50f954461aa8 100644
--- a/include/linux/mtd/physmap.h
+++ b/include/linux/mtd/physmap.h
@@ -24,22 +24,18 @@
24#include <linux/mtd/map.h> 24#include <linux/mtd/map.h>
25#include <linux/mtd/partitions.h> 25#include <linux/mtd/partitions.h>
26 26
27/* 27struct physmap_flash_data {
28 * The map_info for physmap. Board can override size, buswidth, phys, 28 unsigned int width;
29 * (*set_vpp)(), etc in their initial setup routine. 29 void (*set_vpp)(struct map_info *, int);
30 */ 30 unsigned int nr_parts;
31extern struct map_info physmap_map; 31 struct mtd_partition *parts;
32};
32 33
33/* 34/*
34 * Board needs to specify the exact mapping during their setup time. 35 * Board needs to specify the exact mapping during their setup time.
35 */ 36 */
36static inline void physmap_configure(unsigned long addr, unsigned long size, int bankwidth, void (*set_vpp)(struct map_info *, int) ) 37void physmap_configure(unsigned long addr, unsigned long size,
37{ 38 int bankwidth, void (*set_vpp)(struct map_info *, int) );
38 physmap_map.phys = addr;
39 physmap_map.size = size;
40 physmap_map.bankwidth = bankwidth;
41 physmap_map.set_vpp = set_vpp;
42}
43 39
44#if defined(CONFIG_MTD_PARTITIONS) 40#if defined(CONFIG_MTD_PARTITIONS)
45 41
@@ -58,4 +54,3 @@ void physmap_set_partitions(struct mtd_partition *parts, int num_parts);
58#endif /* defined(CONFIG_MTD) */ 54#endif /* defined(CONFIG_MTD) */
59 55
60#endif /* __LINUX_MTD_PHYSMAP__ */ 56#endif /* __LINUX_MTD_PHYSMAP__ */
61