xref: /openbmc/linux/drivers/mtd/maps/sa1100-flash.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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/mach-types.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 *data;
134 };
135 
136 struct sa_info {
137 	struct mtd_partition	*parts;
138 	struct mtd_info		*mtd;
139 	int			num_subdev;
140 	struct sa_subdev_info	subdev[0];
141 };
142 
143 static void sa1100_set_vpp(struct map_info *map, int on)
144 {
145 	struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map);
146 	subdev->data->set_vpp(on);
147 }
148 
149 static void sa1100_destroy_subdev(struct sa_subdev_info *subdev)
150 {
151 	if (subdev->mtd)
152 		map_destroy(subdev->mtd);
153 	if (subdev->map.virt)
154 		iounmap(subdev->map.virt);
155 	release_mem_region(subdev->map.phys, subdev->map.size);
156 }
157 
158 static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *res)
159 {
160 	unsigned long phys;
161 	unsigned int size;
162 	int ret;
163 
164 	phys = res->start;
165 	size = res->end - phys + 1;
166 
167 	/*
168 	 * Retrieve the bankwidth from the MSC registers.
169 	 * We currently only implement CS0 and CS1 here.
170 	 */
171 	switch (phys) {
172 	default:
173 		printk(KERN_WARNING "SA1100 flash: unknown base address "
174 		       "0x%08lx, assuming CS0\n", phys);
175 
176 	case SA1100_CS0_PHYS:
177 		subdev->map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
178 		break;
179 
180 	case SA1100_CS1_PHYS:
181 		subdev->map.bankwidth = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4;
182 		break;
183 	}
184 
185 	if (!request_mem_region(phys, size, subdev->name)) {
186 		ret = -EBUSY;
187 		goto out;
188 	}
189 
190 	if (subdev->data->set_vpp)
191 		subdev->map.set_vpp = sa1100_set_vpp;
192 
193 	subdev->map.phys = phys;
194 	subdev->map.size = size;
195 	subdev->map.virt = ioremap(phys, size);
196 	if (!subdev->map.virt) {
197 		ret = -ENOMEM;
198 		goto err;
199 	}
200 
201 	simple_map_init(&subdev->map);
202 
203 	/*
204 	 * Now let's probe for the actual flash.  Do it here since
205 	 * specific machine settings might have been set above.
206 	 */
207 	subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map);
208 	if (subdev->mtd == NULL) {
209 		ret = -ENXIO;
210 		goto err;
211 	}
212 	subdev->mtd->owner = THIS_MODULE;
213 
214 	printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
215 		"%d-bit\n", phys, subdev->mtd->size >> 20,
216 		subdev->map.bankwidth * 8);
217 
218 	return 0;
219 
220  err:
221 	sa1100_destroy_subdev(subdev);
222  out:
223 	return ret;
224 }
225 
226 static void sa1100_destroy(struct sa_info *info)
227 {
228 	int i;
229 
230 	if (info->mtd) {
231 		del_mtd_partitions(info->mtd);
232 
233 #ifdef CONFIG_MTD_CONCAT
234 		if (info->mtd != info->subdev[0].mtd)
235 			mtd_concat_destroy(info->mtd);
236 #endif
237 	}
238 
239 	if (info->parts)
240 		kfree(info->parts);
241 
242 	for (i = info->num_subdev - 1; i >= 0; i--)
243 		sa1100_destroy_subdev(&info->subdev[i]);
244 	kfree(info);
245 }
246 
247 static struct sa_info *__init
248 sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash)
249 {
250 	struct sa_info *info;
251 	int nr, size, i, ret = 0;
252 
253 	/*
254 	 * Count number of devices.
255 	 */
256 	for (nr = 0; ; nr++)
257 		if (!platform_get_resource(pdev, IORESOURCE_MEM, nr))
258 			break;
259 
260 	if (nr == 0) {
261 		ret = -ENODEV;
262 		goto out;
263 	}
264 
265 	size = sizeof(struct sa_info) + sizeof(struct sa_subdev_info) * nr;
266 
267 	/*
268 	 * Allocate the map_info structs in one go.
269 	 */
270 	info = kmalloc(size, GFP_KERNEL);
271 	if (!info) {
272 		ret = -ENOMEM;
273 		goto out;
274 	}
275 
276 	memset(info, 0, size);
277 
278 	/*
279 	 * Claim and then map the memory regions.
280 	 */
281 	for (i = 0; i < nr; i++) {
282 		struct sa_subdev_info *subdev = &info->subdev[i];
283 		struct resource *res;
284 
285 		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
286 		if (!res)
287 			break;
288 
289 		subdev->map.name = subdev->name;
290 		sprintf(subdev->name, "sa1100-%d", i);
291 		subdev->data = flash;
292 
293 		ret = sa1100_probe_subdev(subdev, res);
294 		if (ret)
295 			break;
296 	}
297 
298 	info->num_subdev = i;
299 
300 	/*
301 	 * ENXIO is special.  It means we didn't find a chip when we probed.
302 	 */
303 	if (ret != 0 && !(ret == -ENXIO && info->num_subdev > 0))
304 		goto err;
305 
306 	/*
307 	 * If we found one device, don't bother with concat support.  If
308 	 * we found multiple devices, use concat if we have it available,
309 	 * otherwise fail.  Either way, it'll be called "sa1100".
310 	 */
311 	if (info->num_subdev == 1) {
312 		strcpy(info->subdev[0].name, "sa1100");
313 		info->mtd = info->subdev[0].mtd;
314 		ret = 0;
315 	} else if (info->num_subdev > 1) {
316 #ifdef CONFIG_MTD_CONCAT
317 		struct mtd_info *cdev[nr];
318 		/*
319 		 * We detected multiple devices.  Concatenate them together.
320 		 */
321 		for (i = 0; i < info->num_subdev; i++)
322 			cdev[i] = info->subdev[i].mtd;
323 
324 		info->mtd = mtd_concat_create(cdev, info->num_subdev,
325 					      "sa1100");
326 		if (info->mtd == NULL)
327 			ret = -ENXIO;
328 #else
329 		printk(KERN_ERR "SA1100 flash: multiple devices "
330 		       "found but MTD concat support disabled.\n");
331 		ret = -ENXIO;
332 #endif
333 	}
334 
335 	if (ret == 0)
336 		return info;
337 
338  err:
339 	sa1100_destroy(info);
340  out:
341 	return ERR_PTR(ret);
342 }
343 
344 static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
345 
346 static int __init sa1100_mtd_probe(struct device *dev)
347 {
348 	struct platform_device *pdev = to_platform_device(dev);
349 	struct flash_platform_data *flash = pdev->dev.platform_data;
350 	struct mtd_partition *parts;
351 	const char *part_type = NULL;
352 	struct sa_info *info;
353 	int err, nr_parts = 0;
354 
355 	if (!flash)
356 		return -ENODEV;
357 
358 	info = sa1100_setup_mtd(pdev, flash);
359 	if (IS_ERR(info)) {
360 		err = PTR_ERR(info);
361 		goto out;
362 	}
363 
364 	/*
365 	 * Partition selection stuff.
366 	 */
367 #ifdef CONFIG_MTD_PARTITIONS
368 	nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0);
369 	if (nr_parts > 0) {
370 		info->parts = parts;
371 		part_type = "dynamic";
372 	} else
373 #endif
374 	{
375 		parts = flash->parts;
376 		nr_parts = flash->nr_parts;
377 		part_type = "static";
378 	}
379 
380 	if (nr_parts == 0) {
381 		printk(KERN_NOTICE "SA1100 flash: no partition info "
382 			"available, registering whole flash\n");
383 		add_mtd_device(info->mtd);
384 	} else {
385 		printk(KERN_NOTICE "SA1100 flash: using %s partition "
386 			"definition\n", part_type);
387 		add_mtd_partitions(info->mtd, parts, nr_parts);
388 	}
389 
390 	dev_set_drvdata(dev, info);
391 	err = 0;
392 
393  out:
394 	return err;
395 }
396 
397 static int __exit sa1100_mtd_remove(struct device *dev)
398 {
399 	struct sa_info *info = dev_get_drvdata(dev);
400 	dev_set_drvdata(dev, NULL);
401 	sa1100_destroy(info);
402 	return 0;
403 }
404 
405 #ifdef CONFIG_PM
406 static int sa1100_mtd_suspend(struct device *dev, u32 state, u32 level)
407 {
408 	struct sa_info *info = dev_get_drvdata(dev);
409 	int ret = 0;
410 
411 	if (info && level == SUSPEND_SAVE_STATE)
412 		ret = info->mtd->suspend(info->mtd);
413 
414 	return ret;
415 }
416 
417 static int sa1100_mtd_resume(struct device *dev, u32 level)
418 {
419 	struct sa_info *info = dev_get_drvdata(dev);
420 	if (info && level == RESUME_RESTORE_STATE)
421 		info->mtd->resume(info->mtd);
422 	return 0;
423 }
424 #else
425 #define sa1100_mtd_suspend NULL
426 #define sa1100_mtd_resume  NULL
427 #endif
428 
429 static struct device_driver sa1100_mtd_driver = {
430 	.name		= "flash",
431 	.bus		= &platform_bus_type,
432 	.probe		= sa1100_mtd_probe,
433 	.remove		= __exit_p(sa1100_mtd_remove),
434 	.suspend	= sa1100_mtd_suspend,
435 	.resume		= sa1100_mtd_resume,
436 };
437 
438 static int __init sa1100_mtd_init(void)
439 {
440 	return driver_register(&sa1100_mtd_driver);
441 }
442 
443 static void __exit sa1100_mtd_exit(void)
444 {
445 	driver_unregister(&sa1100_mtd_driver);
446 }
447 
448 module_init(sa1100_mtd_init);
449 module_exit(sa1100_mtd_exit);
450 
451 MODULE_AUTHOR("Nicolas Pitre");
452 MODULE_DESCRIPTION("SA1100 CFI map driver");
453 MODULE_LICENSE("GPL");
454