xref: /linux/drivers/mtd/maps/sa1100-flash.c (revision 54a8a2220c936a47840c9a3d74910c5a56fae2ed)
1 /*
2  * Flash memory access on SA11x0 based devices
3  *
4  * (C) 2000 Nicolas Pitre <nico@cam.org>
5  *
6  * $Id: sa1100-flash.c,v 1.47 2004/11/01 13:44:36 rmk Exp $
7  */
8 #include <linux/config.h>
9 #include <linux/module.h>
10 #include <linux/types.h>
11 #include <linux/ioport.h>
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/errno.h>
15 #include <linux/slab.h>
16 #include <linux/device.h>
17 #include <linux/err.h>
18 
19 #include <linux/mtd/mtd.h>
20 #include <linux/mtd/map.h>
21 #include <linux/mtd/partitions.h>
22 #include <linux/mtd/concat.h>
23 
24 #include <asm/io.h>
25 #include <asm/sizes.h>
26 #include <asm/mach/flash.h>
27 
28 #if 0
29 /*
30  * This is here for documentation purposes only - until these people
31  * submit their machine types.  It will be gone January 2005.
32  */
33 static struct mtd_partition consus_partitions[] = {
34 	{
35 		.name		= "Consus boot firmware",
36 		.offset		= 0,
37 		.size		= 0x00040000,
38 		.mask_flags	= MTD_WRITABLE, /* force read-only */
39 	}, {
40 		.name		= "Consus kernel",
41 		.offset		= 0x00040000,
42 		.size		= 0x00100000,
43 		.mask_flags	= 0,
44 	}, {
45 		.name		= "Consus disk",
46 		.offset		= 0x00140000,
47 		/* The rest (up to 16M) for jffs.  We could put 0 and
48 		   make it find the size automatically, but right now
49 		   i have 32 megs.  jffs will use all 32 megs if given
50 		   the chance, and this leads to horrible problems
51 		   when you try to re-flash the image because blob
52 		   won't erase the whole partition. */
53 		.size		= 0x01000000 - 0x00140000,
54 		.mask_flags	= 0,
55 	}, {
56 		/* this disk is a secondary disk, which can be used as
57 		   needed, for simplicity, make it the size of the other
58 		   consus partition, although realistically it could be
59 		   the remainder of the disk (depending on the file
60 		   system used) */
61 		 .name		= "Consus disk2",
62 		 .offset	= 0x01000000,
63 		 .size		= 0x01000000 - 0x00140000,
64 		 .mask_flags	= 0,
65 	}
66 };
67 
68 /* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */
69 static struct mtd_partition frodo_partitions[] =
70 {
71 	{
72 		.name		= "bootloader",
73 		.size		= 0x00040000,
74 		.offset		= 0x00000000,
75 		.mask_flags	= MTD_WRITEABLE
76 	}, {
77 		.name		= "bootloader params",
78 		.size		= 0x00040000,
79 		.offset		= MTDPART_OFS_APPEND,
80 		.mask_flags	= MTD_WRITEABLE
81 	}, {
82 		.name		= "kernel",
83 		.size		= 0x00100000,
84 		.offset		= MTDPART_OFS_APPEND,
85 		.mask_flags	= MTD_WRITEABLE
86 	}, {
87 		.name		= "ramdisk",
88 		.size		= 0x00400000,
89 		.offset		= MTDPART_OFS_APPEND,
90 		.mask_flags	= MTD_WRITEABLE
91 	}, {
92 		.name		= "file system",
93 		.size		= MTDPART_SIZ_FULL,
94 		.offset		= MTDPART_OFS_APPEND
95 	}
96 };
97 
98 static struct mtd_partition jornada56x_partitions[] = {
99 	{
100 		.name		= "bootldr",
101 		.size		= 0x00040000,
102 		.offset		= 0,
103 		.mask_flags	= MTD_WRITEABLE,
104 	}, {
105 		.name		= "rootfs",
106 		.size		= MTDPART_SIZ_FULL,
107 		.offset		= MTDPART_OFS_APPEND,
108 	}
109 };
110 
111 static void jornada56x_set_vpp(int vpp)
112 {
113 	if (vpp)
114 		GPSR = GPIO_GPIO26;
115 	else
116 		GPCR = GPIO_GPIO26;
117 	GPDR |= GPIO_GPIO26;
118 }
119 
120 /*
121  * Machine        Phys          Size    set_vpp
122  * Consus    : SA1100_CS0_PHYS SZ_32M
123  * Frodo     : SA1100_CS0_PHYS SZ_32M
124  * Jornada56x: SA1100_CS0_PHYS SZ_32M jornada56x_set_vpp
125  */
126 #endif
127 
128 struct sa_subdev_info {
129 	char name[16];
130 	struct map_info map;
131 	struct mtd_info *mtd;
132 	struct flash_platform_data *data;
133 };
134 
135 struct sa_info {
136 	struct mtd_partition	*parts;
137 	struct mtd_info		*mtd;
138 	int			num_subdev;
139 	struct sa_subdev_info	subdev[0];
140 };
141 
142 static void sa1100_set_vpp(struct map_info *map, int on)
143 {
144 	struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map);
145 	subdev->data->set_vpp(on);
146 }
147 
148 static void sa1100_destroy_subdev(struct sa_subdev_info *subdev)
149 {
150 	if (subdev->mtd)
151 		map_destroy(subdev->mtd);
152 	if (subdev->map.virt)
153 		iounmap(subdev->map.virt);
154 	release_mem_region(subdev->map.phys, subdev->map.size);
155 }
156 
157 static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *res)
158 {
159 	unsigned long phys;
160 	unsigned int size;
161 	int ret;
162 
163 	phys = res->start;
164 	size = res->end - phys + 1;
165 
166 	/*
167 	 * Retrieve the bankwidth from the MSC registers.
168 	 * We currently only implement CS0 and CS1 here.
169 	 */
170 	switch (phys) {
171 	default:
172 		printk(KERN_WARNING "SA1100 flash: unknown base address "
173 		       "0x%08lx, assuming CS0\n", phys);
174 
175 	case SA1100_CS0_PHYS:
176 		subdev->map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
177 		break;
178 
179 	case SA1100_CS1_PHYS:
180 		subdev->map.bankwidth = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4;
181 		break;
182 	}
183 
184 	if (!request_mem_region(phys, size, subdev->name)) {
185 		ret = -EBUSY;
186 		goto out;
187 	}
188 
189 	if (subdev->data->set_vpp)
190 		subdev->map.set_vpp = sa1100_set_vpp;
191 
192 	subdev->map.phys = phys;
193 	subdev->map.size = size;
194 	subdev->map.virt = ioremap(phys, size);
195 	if (!subdev->map.virt) {
196 		ret = -ENOMEM;
197 		goto err;
198 	}
199 
200 	simple_map_init(&subdev->map);
201 
202 	/*
203 	 * Now let's probe for the actual flash.  Do it here since
204 	 * specific machine settings might have been set above.
205 	 */
206 	subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map);
207 	if (subdev->mtd == NULL) {
208 		ret = -ENXIO;
209 		goto err;
210 	}
211 	subdev->mtd->owner = THIS_MODULE;
212 
213 	printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
214 		"%d-bit\n", phys, subdev->mtd->size >> 20,
215 		subdev->map.bankwidth * 8);
216 
217 	return 0;
218 
219  err:
220 	sa1100_destroy_subdev(subdev);
221  out:
222 	return ret;
223 }
224 
225 static void sa1100_destroy(struct sa_info *info)
226 {
227 	int i;
228 
229 	if (info->mtd) {
230 		del_mtd_partitions(info->mtd);
231 
232 #ifdef CONFIG_MTD_CONCAT
233 		if (info->mtd != info->subdev[0].mtd)
234 			mtd_concat_destroy(info->mtd);
235 #endif
236 	}
237 
238 	if (info->parts)
239 		kfree(info->parts);
240 
241 	for (i = info->num_subdev - 1; i >= 0; i--)
242 		sa1100_destroy_subdev(&info->subdev[i]);
243 	kfree(info);
244 }
245 
246 static struct sa_info *__init
247 sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash)
248 {
249 	struct sa_info *info;
250 	int nr, size, i, ret = 0;
251 
252 	/*
253 	 * Count number of devices.
254 	 */
255 	for (nr = 0; ; nr++)
256 		if (!platform_get_resource(pdev, IORESOURCE_MEM, nr))
257 			break;
258 
259 	if (nr == 0) {
260 		ret = -ENODEV;
261 		goto out;
262 	}
263 
264 	size = sizeof(struct sa_info) + sizeof(struct sa_subdev_info) * nr;
265 
266 	/*
267 	 * Allocate the map_info structs in one go.
268 	 */
269 	info = kmalloc(size, GFP_KERNEL);
270 	if (!info) {
271 		ret = -ENOMEM;
272 		goto out;
273 	}
274 
275 	memset(info, 0, size);
276 
277 	/*
278 	 * Claim and then map the memory regions.
279 	 */
280 	for (i = 0; i < nr; i++) {
281 		struct sa_subdev_info *subdev = &info->subdev[i];
282 		struct resource *res;
283 
284 		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
285 		if (!res)
286 			break;
287 
288 		subdev->map.name = subdev->name;
289 		sprintf(subdev->name, "sa1100-%d", i);
290 		subdev->data = flash;
291 
292 		ret = sa1100_probe_subdev(subdev, res);
293 		if (ret)
294 			break;
295 	}
296 
297 	info->num_subdev = i;
298 
299 	/*
300 	 * ENXIO is special.  It means we didn't find a chip when we probed.
301 	 */
302 	if (ret != 0 && !(ret == -ENXIO && info->num_subdev > 0))
303 		goto err;
304 
305 	/*
306 	 * If we found one device, don't bother with concat support.  If
307 	 * we found multiple devices, use concat if we have it available,
308 	 * otherwise fail.  Either way, it'll be called "sa1100".
309 	 */
310 	if (info->num_subdev == 1) {
311 		strcpy(info->subdev[0].name, "sa1100");
312 		info->mtd = info->subdev[0].mtd;
313 		ret = 0;
314 	} else if (info->num_subdev > 1) {
315 #ifdef CONFIG_MTD_CONCAT
316 		struct mtd_info *cdev[nr];
317 		/*
318 		 * We detected multiple devices.  Concatenate them together.
319 		 */
320 		for (i = 0; i < info->num_subdev; i++)
321 			cdev[i] = info->subdev[i].mtd;
322 
323 		info->mtd = mtd_concat_create(cdev, info->num_subdev,
324 					      "sa1100");
325 		if (info->mtd == NULL)
326 			ret = -ENXIO;
327 #else
328 		printk(KERN_ERR "SA1100 flash: multiple devices "
329 		       "found but MTD concat support disabled.\n");
330 		ret = -ENXIO;
331 #endif
332 	}
333 
334 	if (ret == 0)
335 		return info;
336 
337  err:
338 	sa1100_destroy(info);
339  out:
340 	return ERR_PTR(ret);
341 }
342 
343 static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
344 
345 static int __init sa1100_mtd_probe(struct device *dev)
346 {
347 	struct platform_device *pdev = to_platform_device(dev);
348 	struct flash_platform_data *flash = pdev->dev.platform_data;
349 	struct mtd_partition *parts;
350 	const char *part_type = NULL;
351 	struct sa_info *info;
352 	int err, nr_parts = 0;
353 
354 	if (!flash)
355 		return -ENODEV;
356 
357 	info = sa1100_setup_mtd(pdev, flash);
358 	if (IS_ERR(info)) {
359 		err = PTR_ERR(info);
360 		goto out;
361 	}
362 
363 	/*
364 	 * Partition selection stuff.
365 	 */
366 #ifdef CONFIG_MTD_PARTITIONS
367 	nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0);
368 	if (nr_parts > 0) {
369 		info->parts = parts;
370 		part_type = "dynamic";
371 	} else
372 #endif
373 	{
374 		parts = flash->parts;
375 		nr_parts = flash->nr_parts;
376 		part_type = "static";
377 	}
378 
379 	if (nr_parts == 0) {
380 		printk(KERN_NOTICE "SA1100 flash: no partition info "
381 			"available, registering whole flash\n");
382 		add_mtd_device(info->mtd);
383 	} else {
384 		printk(KERN_NOTICE "SA1100 flash: using %s partition "
385 			"definition\n", part_type);
386 		add_mtd_partitions(info->mtd, parts, nr_parts);
387 	}
388 
389 	dev_set_drvdata(dev, info);
390 	err = 0;
391 
392  out:
393 	return err;
394 }
395 
396 static int __exit sa1100_mtd_remove(struct device *dev)
397 {
398 	struct sa_info *info = dev_get_drvdata(dev);
399 	dev_set_drvdata(dev, NULL);
400 	sa1100_destroy(info);
401 	return 0;
402 }
403 
404 #ifdef CONFIG_PM
405 static int sa1100_mtd_suspend(struct device *dev, pm_message_t state, u32 level)
406 {
407 	struct sa_info *info = dev_get_drvdata(dev);
408 	int ret = 0;
409 
410 	if (info && level == SUSPEND_SAVE_STATE)
411 		ret = info->mtd->suspend(info->mtd);
412 
413 	return ret;
414 }
415 
416 static int sa1100_mtd_resume(struct device *dev, u32 level)
417 {
418 	struct sa_info *info = dev_get_drvdata(dev);
419 	if (info && level == RESUME_RESTORE_STATE)
420 		info->mtd->resume(info->mtd);
421 	return 0;
422 }
423 #else
424 #define sa1100_mtd_suspend NULL
425 #define sa1100_mtd_resume  NULL
426 #endif
427 
428 static struct device_driver sa1100_mtd_driver = {
429 	.name		= "flash",
430 	.bus		= &platform_bus_type,
431 	.probe		= sa1100_mtd_probe,
432 	.remove		= __exit_p(sa1100_mtd_remove),
433 	.suspend	= sa1100_mtd_suspend,
434 	.resume		= sa1100_mtd_resume,
435 };
436 
437 static int __init sa1100_mtd_init(void)
438 {
439 	return driver_register(&sa1100_mtd_driver);
440 }
441 
442 static void __exit sa1100_mtd_exit(void)
443 {
444 	driver_unregister(&sa1100_mtd_driver);
445 }
446 
447 module_init(sa1100_mtd_init);
448 module_exit(sa1100_mtd_exit);
449 
450 MODULE_AUTHOR("Nicolas Pitre");
451 MODULE_DESCRIPTION("SA1100 CFI map driver");
452 MODULE_LICENSE("GPL");
453