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