diff options
-rw-r--r-- | drivers/mtd/nand/sharpsl.c | 158 | ||||
-rw-r--r-- | include/linux/mtd/sharpsl.h | 20 |
2 files changed, 104 insertions, 74 deletions
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 17625c0a8f61..698378ca8e0a 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/mtd/nand.h> | 20 | #include <linux/mtd/nand.h> |
21 | #include <linux/mtd/nand_ecc.h> | 21 | #include <linux/mtd/nand_ecc.h> |
22 | #include <linux/mtd/partitions.h> | 22 | #include <linux/mtd/partitions.h> |
23 | #include <linux/mtd/sharpsl.h> | ||
23 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
25 | 26 | ||
@@ -53,31 +54,6 @@ struct sharpsl_nand { | |||
53 | #define FLCLE (1 << 1) | 54 | #define FLCLE (1 << 1) |
54 | #define FLCE0 (1 << 0) | 55 | #define FLCE0 (1 << 0) |
55 | 56 | ||
56 | #ifdef CONFIG_MTD_PARTITIONS | ||
57 | /* | ||
58 | * Define partitions for flash device | ||
59 | */ | ||
60 | #define DEFAULT_NUM_PARTITIONS 3 | ||
61 | |||
62 | static struct mtd_partition sharpsl_nand_default_partition_info[] = { | ||
63 | { | ||
64 | .name = "System Area", | ||
65 | .offset = 0, | ||
66 | .size = 7 * 1024 * 1024, | ||
67 | }, | ||
68 | { | ||
69 | .name = "Root Filesystem", | ||
70 | .offset = 7 * 1024 * 1024, | ||
71 | .size = 30 * 1024 * 1024, | ||
72 | }, | ||
73 | { | ||
74 | .name = "Home Filesystem", | ||
75 | .offset = MTDPART_OFS_APPEND, | ||
76 | .size = MTDPART_SIZ_FULL, | ||
77 | }, | ||
78 | }; | ||
79 | #endif | ||
80 | |||
81 | /* | 57 | /* |
82 | * hardware specific access to control-lines | 58 | * hardware specific access to control-lines |
83 | * ctrl: | 59 | * ctrl: |
@@ -106,31 +82,6 @@ static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd, | |||
106 | writeb(cmd, chip->IO_ADDR_W); | 82 | writeb(cmd, chip->IO_ADDR_W); |
107 | } | 83 | } |
108 | 84 | ||
109 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | ||
110 | |||
111 | static struct nand_bbt_descr sharpsl_bbt = { | ||
112 | .options = 0, | ||
113 | .offs = 4, | ||
114 | .len = 2, | ||
115 | .pattern = scan_ff_pattern | ||
116 | }; | ||
117 | |||
118 | static struct nand_bbt_descr sharpsl_akita_bbt = { | ||
119 | .options = 0, | ||
120 | .offs = 4, | ||
121 | .len = 1, | ||
122 | .pattern = scan_ff_pattern | ||
123 | }; | ||
124 | |||
125 | static struct nand_ecclayout akita_oobinfo = { | ||
126 | .eccbytes = 24, | ||
127 | .eccpos = { | ||
128 | 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11, | ||
129 | 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, | ||
130 | 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37}, | ||
131 | .oobfree = {{0x08, 0x09}} | ||
132 | }; | ||
133 | |||
134 | static int sharpsl_nand_dev_ready(struct mtd_info *mtd) | 85 | static int sharpsl_nand_dev_ready(struct mtd_info *mtd) |
135 | { | 86 | { |
136 | struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); | 87 | struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd); |
@@ -169,6 +120,12 @@ static int __devinit sharpsl_nand_probe(struct platform_device *pdev) | |||
169 | struct resource *r; | 120 | struct resource *r; |
170 | int err = 0; | 121 | int err = 0; |
171 | struct sharpsl_nand *sharpsl; | 122 | struct sharpsl_nand *sharpsl; |
123 | struct sharpsl_nand_platform_data *data = pdev->dev.platform_data; | ||
124 | |||
125 | if (!data) { | ||
126 | dev_err(&pdev->dev, "no platform data!\n"); | ||
127 | return -EINVAL; | ||
128 | } | ||
172 | 129 | ||
173 | /* Allocate memory for MTD device structure and private data */ | 130 | /* Allocate memory for MTD device structure and private data */ |
174 | sharpsl = kzalloc(sizeof(struct sharpsl_nand), GFP_KERNEL); | 131 | sharpsl = kzalloc(sizeof(struct sharpsl_nand), GFP_KERNEL); |
@@ -218,11 +175,8 @@ static int __devinit sharpsl_nand_probe(struct platform_device *pdev) | |||
218 | this->ecc.mode = NAND_ECC_HW; | 175 | this->ecc.mode = NAND_ECC_HW; |
219 | this->ecc.size = 256; | 176 | this->ecc.size = 256; |
220 | this->ecc.bytes = 3; | 177 | this->ecc.bytes = 3; |
221 | this->badblock_pattern = &sharpsl_bbt; | 178 | this->badblock_pattern = data->badblock_pattern; |
222 | if (machine_is_akita() || machine_is_borzoi()) { | 179 | this->ecc.layout = data->ecc_layout; |
223 | this->badblock_pattern = &sharpsl_akita_bbt; | ||
224 | this->ecc.layout = &akita_oobinfo; | ||
225 | } | ||
226 | this->ecc.hwctl = sharpsl_nand_enable_hwecc; | 180 | this->ecc.hwctl = sharpsl_nand_enable_hwecc; |
227 | this->ecc.calculate = sharpsl_nand_calculate_ecc; | 181 | this->ecc.calculate = sharpsl_nand_calculate_ecc; |
228 | this->ecc.correct = nand_correct_data; | 182 | this->ecc.correct = nand_correct_data; |
@@ -236,29 +190,16 @@ static int __devinit sharpsl_nand_probe(struct platform_device *pdev) | |||
236 | sharpsl->mtd.name = "sharpsl-nand"; | 190 | sharpsl->mtd.name = "sharpsl-nand"; |
237 | #ifdef CONFIG_MTD_PARTITIONS | 191 | #ifdef CONFIG_MTD_PARTITIONS |
238 | nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0); | 192 | nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0); |
239 | |||
240 | if (nr_partitions <= 0) { | 193 | if (nr_partitions <= 0) { |
241 | nr_partitions = ARRAY_SIZE(sharpsl_nand_default_partition_info); | 194 | nr_partitions = data->nr_partitions; |
242 | sharpsl_partition_info = sharpsl_nand_default_partition_info; | 195 | sharpsl_partition_info = data->partitions; |
243 | if (machine_is_poodle()) { | ||
244 | sharpsl_partition_info[1].size = 22 * 1024 * 1024; | ||
245 | } else if (machine_is_corgi() || machine_is_shepherd()) { | ||
246 | sharpsl_partition_info[1].size = 25 * 1024 * 1024; | ||
247 | } else if (machine_is_husky()) { | ||
248 | sharpsl_partition_info[1].size = 53 * 1024 * 1024; | ||
249 | } else if (machine_is_spitz()) { | ||
250 | sharpsl_partition_info[1].size = 5 * 1024 * 1024; | ||
251 | } else if (machine_is_akita()) { | ||
252 | sharpsl_partition_info[1].size = 58 * 1024 * 1024; | ||
253 | } else if (machine_is_borzoi()) { | ||
254 | sharpsl_partition_info[1].size = 32 * 1024 * 1024; | ||
255 | } | ||
256 | } | 196 | } |
257 | 197 | ||
258 | err = add_mtd_partitions(&sharpsl->mtd, sharpsl_partition_info, nr_partitions); | 198 | if (nr_partitions > 0) |
259 | #else | 199 | err = add_mtd_partitions(&sharpsl->mtd, sharpsl_partition_info, nr_partitions); |
260 | err = add_mtd_device(&sharpsl->mtd); | 200 | else |
261 | #endif | 201 | #endif |
202 | err = add_mtd_device(&sharpsl->mtd); | ||
262 | if (err) | 203 | if (err) |
263 | goto err_add; | 204 | goto err_add; |
264 | 205 | ||
@@ -306,6 +247,58 @@ static struct platform_driver sharpsl_nand_driver = { | |||
306 | .remove = __devexit_p(sharpsl_nand_remove), | 247 | .remove = __devexit_p(sharpsl_nand_remove), |
307 | }; | 248 | }; |
308 | 249 | ||
250 | /* | ||
251 | * Define partitions for flash device | ||
252 | */ | ||
253 | static struct mtd_partition sharpsl_nand_partitions[] = { | ||
254 | { | ||
255 | .name = "System Area", | ||
256 | .offset = 0, | ||
257 | .size = 7 * 1024 * 1024, | ||
258 | }, | ||
259 | { | ||
260 | .name = "Root Filesystem", | ||
261 | .offset = 7 * 1024 * 1024, | ||
262 | .size = 30 * 1024 * 1024, | ||
263 | }, | ||
264 | { | ||
265 | .name = "Home Filesystem", | ||
266 | .offset = MTDPART_OFS_APPEND, | ||
267 | .size = MTDPART_SIZ_FULL, | ||
268 | }, | ||
269 | }; | ||
270 | |||
271 | static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; | ||
272 | |||
273 | static struct nand_bbt_descr sharpsl_bbt = { | ||
274 | .options = 0, | ||
275 | .offs = 4, | ||
276 | .len = 2, | ||
277 | .pattern = scan_ff_pattern | ||
278 | }; | ||
279 | |||
280 | static struct nand_bbt_descr sharpsl_akita_bbt = { | ||
281 | .options = 0, | ||
282 | .offs = 4, | ||
283 | .len = 1, | ||
284 | .pattern = scan_ff_pattern | ||
285 | }; | ||
286 | |||
287 | static struct nand_ecclayout akita_oobinfo = { | ||
288 | .eccbytes = 24, | ||
289 | .eccpos = { | ||
290 | 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11, | ||
291 | 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23, | ||
292 | 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37}, | ||
293 | .oobfree = {{0x08, 0x09}} | ||
294 | }; | ||
295 | |||
296 | static struct sharpsl_nand_platform_data sharpsl_nand_platform_data = { | ||
297 | .badblock_pattern = &sharpsl_bbt, | ||
298 | .partitions = sharpsl_nand_partitions, | ||
299 | .nr_partitions = ARRAY_SIZE(sharpsl_nand_partitions), | ||
300 | }; | ||
301 | |||
309 | static struct resource sharpsl_nand_resources[] = { | 302 | static struct resource sharpsl_nand_resources[] = { |
310 | { | 303 | { |
311 | .start = 0x0C000000, | 304 | .start = 0x0C000000, |
@@ -319,10 +312,27 @@ static struct platform_device sharpsl_nand_device = { | |||
319 | .id = -1, | 312 | .id = -1, |
320 | .resource = sharpsl_nand_resources, | 313 | .resource = sharpsl_nand_resources, |
321 | .num_resources = ARRAY_SIZE(sharpsl_nand_resources), | 314 | .num_resources = ARRAY_SIZE(sharpsl_nand_resources), |
315 | .dev.platform_data = &sharpsl_nand_platform_data, | ||
322 | }; | 316 | }; |
323 | 317 | ||
324 | static int __init sharpsl_nand_init(void) | 318 | static int __init sharpsl_nand_init(void) |
325 | { | 319 | { |
320 | if (machine_is_poodle()) { | ||
321 | sharpsl_nand_partitions[1].size = 22 * 1024 * 1024; | ||
322 | } else if (machine_is_corgi() || machine_is_shepherd()) { | ||
323 | sharpsl_nand_partitions[1].size = 25 * 1024 * 1024; | ||
324 | } else if (machine_is_husky()) { | ||
325 | sharpsl_nand_partitions[1].size = 53 * 1024 * 1024; | ||
326 | } else if (machine_is_spitz()) { | ||
327 | sharpsl_nand_partitions[1].size = 5 * 1024 * 1024; | ||
328 | } else if (machine_is_akita()) { | ||
329 | sharpsl_nand_partitions[1].size = 58 * 1024 * 1024; | ||
330 | sharpsl_nand_platform_data.badblock_pattern = &sharpsl_akita_bbt; | ||
331 | sharpsl_nand_platform_data.ecc_layout = &akita_oobinfo; | ||
332 | } else if (machine_is_borzoi()) { | ||
333 | sharpsl_nand_partitions[1].size = 32 * 1024 * 1024; | ||
334 | } | ||
335 | |||
326 | platform_device_register(&sharpsl_nand_device); | 336 | platform_device_register(&sharpsl_nand_device); |
327 | return platform_driver_register(&sharpsl_nand_driver); | 337 | return platform_driver_register(&sharpsl_nand_driver); |
328 | } | 338 | } |
diff --git a/include/linux/mtd/sharpsl.h b/include/linux/mtd/sharpsl.h new file mode 100644 index 000000000000..25f4d2a845c1 --- /dev/null +++ b/include/linux/mtd/sharpsl.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * SharpSL NAND support | ||
3 | * | ||
4 | * Copyright (C) 2008 Dmitry Baryshkov | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/mtd/nand.h> | ||
12 | #include <linux/mtd/nand_ecc.h> | ||
13 | #include <linux/mtd/partitions.h> | ||
14 | |||
15 | struct sharpsl_nand_platform_data { | ||
16 | struct nand_bbt_descr *badblock_pattern; | ||
17 | struct nand_ecclayout *ecc_layout; | ||
18 | struct mtd_partition *partitions; | ||
19 | unsigned int nr_partitions; | ||
20 | }; | ||