Commit 99f2a8aea18c9779c141050c6f95a8f1da63bbe4
Committed by
Thomas Gleixner
1 parent
a4ab4c5d32
Exists in
master
and in
7 other branches
[MTD] Platform RAM Driver
Driver for generic RAM blocks which are exported by an platform_device from the device driver system. Signed-off-by: Ben Dooks <ben@simtec.co.uk> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Showing 4 changed files with 334 additions and 2 deletions Side-by-side Diff
drivers/mtd/maps/Kconfig
1 | 1 | # drivers/mtd/maps/Kconfig |
2 | -# $Id: Kconfig,v 1.42 2005/01/05 16:59:50 dwmw2 Exp $ | |
2 | +# $Id: Kconfig,v 1.43 2005/01/24 00:35:21 bjd Exp $ | |
3 | 3 | |
4 | 4 | menu "Mapping drivers for chip access" |
5 | 5 | depends on MTD!=n |
... | ... | @@ -658,6 +658,16 @@ |
658 | 658 | depends on MTD && ARCH_PXA |
659 | 659 | help |
660 | 660 | This enables access to the flash chip on the Sharp SL Series of PDAs. |
661 | + | |
662 | +config MTD_PLATRAM | |
663 | + tristate "Map driver for platfrom device RAM (mtd-ram)" | |
664 | + depends on MTD | |
665 | + select MTD_RAM | |
666 | + help | |
667 | + Map driver for RAM areas described via the platform device | |
668 | + system. | |
669 | + | |
670 | + This selection automatically selects the map_ram driver. | |
661 | 671 | |
662 | 672 | endmenu |
drivers/mtd/maps/Makefile
1 | 1 | # |
2 | 2 | # linux/drivers/maps/Makefile |
3 | 3 | # |
4 | -# $Id: Makefile.common,v 1.23 2005/01/05 17:06:36 dwmw2 Exp $ | |
4 | +# $Id: Makefile.common,v 1.24 2005/01/24 00:35:21 bjd Exp $ | |
5 | 5 | |
6 | 6 | ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y) |
7 | 7 | obj-$(CONFIG_MTD) += map_funcs.o |
... | ... | @@ -71,4 +71,5 @@ |
71 | 71 | obj-$(CONFIG_MTD_WRSBC8260) += wr_sbc82xx_flash.o |
72 | 72 | obj-$(CONFIG_MTD_DMV182) += dmv182.o |
73 | 73 | obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o |
74 | +obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o |
drivers/mtd/maps/plat-ram.c
1 | +/* drivers/mtd/maps/plat-ram.c | |
2 | + * | |
3 | + * (c) 2004-2005 Simtec Electronics | |
4 | + * http://www.simtec.co.uk/products/SWLINUX/ | |
5 | + * Ben Dooks <ben@simtec.co.uk> | |
6 | + * | |
7 | + * Generic platfrom device based RAM map | |
8 | + * | |
9 | + * $Id: plat-ram.c,v 1.1 2005/01/24 00:37:02 bjd Exp $ | |
10 | + * | |
11 | + * This program is free software; you can redistribute it and/or modify | |
12 | + * it under the terms of the GNU General Public License as published by | |
13 | + * the Free Software Foundation; either version 2 of the License, or | |
14 | + * (at your option) any later version. | |
15 | + * | |
16 | + * This program is distributed in the hope that it will be useful, | |
17 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | + * GNU General Public License for more details. | |
20 | + * | |
21 | + * You should have received a copy of the GNU General Public License | |
22 | + * along with this program; if not, write to the Free Software | |
23 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 | +*/ | |
25 | + | |
26 | +#define DEBUG | |
27 | + | |
28 | +#include <linux/module.h> | |
29 | +#include <linux/types.h> | |
30 | +#include <linux/init.h> | |
31 | +#include <linux/kernel.h> | |
32 | +#include <linux/string.h> | |
33 | +#include <linux/ioport.h> | |
34 | +#include <linux/device.h> | |
35 | + | |
36 | +#include <linux/mtd/mtd.h> | |
37 | +#include <linux/mtd/map.h> | |
38 | +#include <linux/mtd/partitions.h> | |
39 | +#include <linux/mtd/plat-ram.h> | |
40 | + | |
41 | +#include <asm/io.h> | |
42 | + | |
43 | +/* private structure for each mtd platform ram device created */ | |
44 | + | |
45 | +struct platram_info { | |
46 | + struct device *dev; | |
47 | + struct mtd_info *mtd; | |
48 | + struct map_info map; | |
49 | + struct mtd_partition *partitions; | |
50 | + struct resource *area; | |
51 | + struct platdata_mtd_ram *pdata; | |
52 | +}; | |
53 | + | |
54 | +/* to_platram_info() | |
55 | + * | |
56 | + * device private data to struct platram_info conversion | |
57 | +*/ | |
58 | + | |
59 | +static inline struct platram_info *to_platram_info(struct device *dev) | |
60 | +{ | |
61 | + return (struct platram_info *)dev_get_drvdata(dev); | |
62 | +} | |
63 | + | |
64 | +/* platram_setrw | |
65 | + * | |
66 | + * call the platform device's set rw/ro control | |
67 | + * | |
68 | + * to = 0 => read-only | |
69 | + * = 1 => read-write | |
70 | +*/ | |
71 | + | |
72 | +static inline void platram_setrw(struct platram_info *info, int to) | |
73 | +{ | |
74 | + if (info->pdata == NULL) | |
75 | + return; | |
76 | + | |
77 | + if (info->pdata->set_rw != NULL) | |
78 | + (info->pdata->set_rw)(info->dev, to); | |
79 | +} | |
80 | + | |
81 | +/* platram_remove | |
82 | + * | |
83 | + * called to remove the device from the driver's control | |
84 | +*/ | |
85 | + | |
86 | +static int platram_remove(struct device *dev) | |
87 | +{ | |
88 | + struct platram_info *info = to_platram_info(dev); | |
89 | + | |
90 | + dev_set_drvdata(dev, NULL); | |
91 | + | |
92 | + dev_dbg(dev, "removing device\n"); | |
93 | + | |
94 | + if (info == NULL) | |
95 | + return 0; | |
96 | + | |
97 | + if (info->mtd) { | |
98 | +#ifdef CONFIG_MTD_PARTITIONS | |
99 | + if (info->partitions) { | |
100 | + del_mtd_partitions(info->mtd); | |
101 | + kfree(info->partitions); | |
102 | + } | |
103 | +#endif | |
104 | + del_mtd_device(info->mtd); | |
105 | + map_destroy(info->mtd); | |
106 | + } | |
107 | + | |
108 | + /* ensure ram is left read-only */ | |
109 | + | |
110 | + platram_setrw(info, PLATRAM_RO); | |
111 | + | |
112 | + /* release resources */ | |
113 | + | |
114 | + if (info->area) { | |
115 | + release_resource(info->area); | |
116 | + kfree(info->area); | |
117 | + } | |
118 | + | |
119 | + if (info->map.virt != NULL) | |
120 | + iounmap(info->map.virt); | |
121 | + | |
122 | + kfree(info); | |
123 | + | |
124 | + return 0; | |
125 | +} | |
126 | + | |
127 | +/* platram_probe | |
128 | + * | |
129 | + * called from device drive system when a device matching our | |
130 | + * driver is found. | |
131 | +*/ | |
132 | + | |
133 | +static int platram_probe(struct device *dev) | |
134 | +{ | |
135 | + struct platform_device *pd = to_platform_device(dev); | |
136 | + struct platdata_mtd_ram *pdata; | |
137 | + struct platram_info *info; | |
138 | + struct resource *res; | |
139 | + int err = 0; | |
140 | + | |
141 | + dev_dbg(dev, "probe entered\n"); | |
142 | + | |
143 | + if (dev->platform_data == NULL) { | |
144 | + dev_err(dev, "no platform data supplied\n"); | |
145 | + err = -ENOENT; | |
146 | + goto exit_error; | |
147 | + } | |
148 | + | |
149 | + pdata = dev->platform_data; | |
150 | + | |
151 | + info = kmalloc(sizeof(*info), GFP_KERNEL); | |
152 | + if (info == NULL) { | |
153 | + dev_err(dev, "no memory for flash info\n"); | |
154 | + err = -ENOMEM; | |
155 | + goto exit_error; | |
156 | + } | |
157 | + | |
158 | + memzero(info, sizeof(*info)); | |
159 | + dev_set_drvdata(dev, info); | |
160 | + | |
161 | + info->dev = dev; | |
162 | + info->pdata = pdata; | |
163 | + | |
164 | + /* get the resource for the memory mapping */ | |
165 | + | |
166 | + res = platform_get_resource(pd, IORESOURCE_MEM, 0); | |
167 | + | |
168 | + if (res == NULL) { | |
169 | + dev_err(dev, "no memory resource specified\n"); | |
170 | + err = -ENOENT; | |
171 | + goto exit_free; | |
172 | + } | |
173 | + | |
174 | + dev_dbg(dev, "got platform resource %p (0x%lx)\n", res, res->start); | |
175 | + | |
176 | + /* setup map parameters */ | |
177 | + | |
178 | + info->map.phys = res->start; | |
179 | + info->map.size = (res->end - res->start) + 1; | |
180 | + info->map.name = pdata->mapname != NULL ? pdata->mapname : pd->name; | |
181 | + info->map.bankwidth = pdata->bankwidth; | |
182 | + | |
183 | + /* register our usage of the memory area */ | |
184 | + | |
185 | + info->area = request_mem_region(res->start, info->map.size, pd->name); | |
186 | + if (info->area == NULL) { | |
187 | + dev_err(dev, "failed to request memory region\n"); | |
188 | + err = -EIO; | |
189 | + goto exit_free; | |
190 | + } | |
191 | + | |
192 | + /* remap the memory area */ | |
193 | + | |
194 | + info->map.virt = ioremap(res->start, info->map.size); | |
195 | + dev_dbg(dev, "virt %p, %d bytes\n", info->map.virt, info->map.size); | |
196 | + | |
197 | + if (info->map.virt == NULL) { | |
198 | + dev_err(dev, "failed to ioremap() region\n"); | |
199 | + err = -EIO; | |
200 | + goto exit_free; | |
201 | + } | |
202 | + | |
203 | + { | |
204 | + unsigned int *p = (unsigned int *)info->map.virt; | |
205 | + printk("%08x %08x %08x %08x\n", | |
206 | + readl(p), readl(p+1), readl(p+2), readl(p+3)); | |
207 | + } | |
208 | + | |
209 | + simple_map_init(&info->map); | |
210 | + | |
211 | + dev_dbg(dev, "initialised map, probing for mtd\n"); | |
212 | + | |
213 | + /* probe for the right mtd map driver */ | |
214 | + | |
215 | + info->mtd = do_map_probe("map_ram" , &info->map); | |
216 | + if (info->mtd == NULL) { | |
217 | + dev_err(dev, "failed to probe for map_ram\n"); | |
218 | + err = -ENOMEM; | |
219 | + goto exit_free; | |
220 | + } | |
221 | + | |
222 | + info->mtd->owner = THIS_MODULE; | |
223 | + | |
224 | + platram_setrw(info, PLATRAM_RW); | |
225 | + | |
226 | + /* check to see if there are any available partitions, or wether | |
227 | + * to add this device whole */ | |
228 | + | |
229 | +#ifdef CONFIG_MTD_PARTITIONS | |
230 | + if (pdata->nr_partitions > 0) { | |
231 | + const char **probes = { NULL }; | |
232 | + | |
233 | + if (pdata->probes) | |
234 | + probes = (const char **)pdata->probes; | |
235 | + | |
236 | + err = parse_mtd_partitions(info->mtd, probes, | |
237 | + &info->partitions, 0); | |
238 | + if (err > 0) { | |
239 | + err = add_mtd_partitions(info->mtd, info->partitions, | |
240 | + err); | |
241 | + } | |
242 | + } | |
243 | +#endif /* CONFIG_MTD_PARTITIONS */ | |
244 | + | |
245 | + if (add_mtd_device(info->mtd)) { | |
246 | + dev_err(dev, "add_mtd_device() failed\n"); | |
247 | + err = -ENOMEM; | |
248 | + } | |
249 | + | |
250 | + dev_info(dev, "registered mtd device\n"); | |
251 | + return err; | |
252 | + | |
253 | + exit_free: | |
254 | + platram_remove(dev); | |
255 | + exit_error: | |
256 | + return err; | |
257 | +} | |
258 | + | |
259 | +/* device driver info */ | |
260 | + | |
261 | +static struct device_driver platram_driver = { | |
262 | + .name = "mtd-ram", | |
263 | + .bus = &platform_bus_type, | |
264 | + .probe = platram_probe, | |
265 | + .remove = platram_remove, | |
266 | +}; | |
267 | + | |
268 | +/* module init/exit */ | |
269 | + | |
270 | +static int __init platram_init(void) | |
271 | +{ | |
272 | + printk("Generic platform RAM MTD, (c) 2004 Simtec Electronics\n"); | |
273 | + return driver_register(&platram_driver); | |
274 | +} | |
275 | + | |
276 | +static void __exit platram_exit(void) | |
277 | +{ | |
278 | + driver_unregister(&platram_driver); | |
279 | +} | |
280 | + | |
281 | +module_init(platram_init); | |
282 | +module_exit(platram_exit); | |
283 | + | |
284 | +MODULE_LICENSE("GPL"); | |
285 | +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | |
286 | +MODULE_DESCRIPTION("MTD platform RAM map driver"); |
include/linux/mtd/plat-ram.h
1 | +/* linux/include/mtd/plat-ram.h | |
2 | + * | |
3 | + * (c) 2004 Simtec Electronics | |
4 | + * http://www.simtec.co.uk/products/SWLINUX/ | |
5 | + * Ben Dooks <ben@simtec.co.uk> | |
6 | + * | |
7 | + * Generic platform device based RAM map | |
8 | + * | |
9 | + * $Id: plat-ram.h,v 1.2 2005/01/24 00:37:40 bjd Exp $ | |
10 | + * | |
11 | + * This program is free software; you can redistribute it and/or modify | |
12 | + * it under the terms of the GNU General Public License version 2 as | |
13 | + * published by the Free Software Foundation. | |
14 | + * | |
15 | + */ | |
16 | + | |
17 | +#ifndef __LINUX_MTD_PLATRAM_H | |
18 | +#define __LINUX_MTD_PLATRAM_H __FILE__ | |
19 | + | |
20 | +#define PLATRAM_RO (0) | |
21 | +#define PLATRAM_RW (1) | |
22 | + | |
23 | +struct platdata_mtd_ram { | |
24 | + char *mapname; | |
25 | + char **probes; | |
26 | + struct mtd_partition *partitions; | |
27 | + int nr_partitions; | |
28 | + int bankwidth; | |
29 | + | |
30 | + /* control callbacks */ | |
31 | + | |
32 | + void (*set_rw)(struct device *dev, int to); | |
33 | +}; | |
34 | + | |
35 | +#endif /* __LINUX_MTD_PLATRAM_H */ |