• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/arm/plat-samsung/
1/*
2 * S3C series device definition for nand device
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7*/
8
9#include <linux/gfp.h>
10#include <linux/kernel.h>
11#include <linux/platform_device.h>
12
13#include <linux/mtd/mtd.h>
14#include <linux/mtd/partitions.h>
15
16#include <mach/map.h>
17#include <plat/devs.h>
18#include <plat/nand.h>
19
20static struct resource s3c_nand_resource[] = {
21	[0] = {
22		.start = S3C_PA_NAND,
23		.end   = S3C_PA_NAND + SZ_1M,
24		.flags = IORESOURCE_MEM,
25	}
26};
27
28struct platform_device s3c_device_nand = {
29	.name		  = "s3c2410-nand",
30	.id		  = -1,
31	.num_resources	  = ARRAY_SIZE(s3c_nand_resource),
32	.resource	  = s3c_nand_resource,
33};
34
35EXPORT_SYMBOL(s3c_device_nand);
36
37/**
38 * s3c_nand_copy_set() - copy nand set data
39 * @set: The new structure, directly copied from the old.
40 *
41 * Copy all the fields from the NAND set field from what is probably __initdata
42 * to new kernel memory. The code returns 0 if the copy happened correctly or
43 * an error code for the calling function to display.
44 *
45 * Note, we currently do not try and look to see if we've already copied the
46 * data in a previous set.
47 */
48static int __init s3c_nand_copy_set(struct s3c2410_nand_set *set)
49{
50	void *ptr;
51	int size;
52
53	size = sizeof(struct mtd_partition) * set->nr_partitions;
54	if (size) {
55		ptr = kmemdup(set->partitions, size, GFP_KERNEL);
56		set->partitions = ptr;
57
58		if (!ptr)
59			return -ENOMEM;
60	}
61
62	if (set->nr_map && set->nr_chips) {
63		size = sizeof(int) * set->nr_chips;
64		ptr = kmemdup(set->nr_map, size, GFP_KERNEL);
65		set->nr_map = ptr;
66
67		if (!ptr)
68			return -ENOMEM;
69	}
70
71	if (set->ecc_layout) {
72		ptr = kmemdup(set->ecc_layout,
73			      sizeof(struct nand_ecclayout), GFP_KERNEL);
74		set->ecc_layout = ptr;
75
76		if (!ptr)
77			return -ENOMEM;
78	}
79
80	return 0;
81}
82
83void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
84{
85	struct s3c2410_platform_nand *npd;
86	int size;
87	int ret;
88
89	/* note, if we get a failure in allocation, we simply drop out of the
90	 * function. If there is so little memory available at initialisation
91	 * time then there is little chance the system is going to run.
92	 */
93
94	npd = kmemdup(nand, sizeof(struct s3c2410_platform_nand), GFP_KERNEL);
95	if (!npd) {
96		printk(KERN_ERR "%s: failed copying platform data\n", __func__);
97		return;
98	}
99
100	/* now see if we need to copy any of the nand set data */
101
102	size = sizeof(struct s3c2410_nand_set) * npd->nr_sets;
103	if (size) {
104		struct s3c2410_nand_set *from = npd->sets;
105		struct s3c2410_nand_set *to;
106		int i;
107
108		to = kmemdup(from, size, GFP_KERNEL);
109		npd->sets = to;	/* set, even if we failed */
110
111		if (!to) {
112			printk(KERN_ERR "%s: no memory for sets\n", __func__);
113			return;
114		}
115
116		for (i = 0; i < npd->nr_sets; i++) {
117			ret = s3c_nand_copy_set(to);
118			if (ret) {
119				printk(KERN_ERR "%s: failed to copy set %d\n",
120				__func__, i);
121				return;
122			}
123			to++;
124		}
125	}
126
127	s3c_device_nand.dev.platform_data = npd;
128}
129
130EXPORT_SYMBOL_GPL(s3c_nand_set_platdata);
131