aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRohit Hagargundgi <h.rohit@samsung.com>2009-05-12 16:46:57 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-06-05 13:59:21 -0400
commit5988af2319781bc8e0ce418affec4e09cfa77907 (patch)
tree7de04259b49ab0b50b98e9dae6a5fe61d3de67bc
parent67ce04bf2746f8a1f8c2a104b313d20c63f68378 (diff)
mtd: Flex-OneNAND support
Add support for Samsung Flex-OneNAND devices. Flex-OneNAND combines SLC and MLC technologies into a single device. SLC area provides increased reliability and speed, suitable for storing code such as bootloader, kernel and root file system. MLC area provides high density and is suitable for storing user data. SLC and MLC regions can be configured through kernel parameter. [akpm@linux-foundation.org: export flexoand_region and onenand_addr] Signed-off-by: Rohit Hagargundgi <h.rohit@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Cc: Vishak G <vishak.g@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--Documentation/kernel-parameters.txt10
-rw-r--r--drivers/mtd/onenand/onenand_base.c857
-rw-r--r--drivers/mtd/onenand/onenand_bbt.c14
-rw-r--r--drivers/mtd/onenand/onenand_sim.c81
-rw-r--r--include/linux/mtd/onenand.h18
-rw-r--r--include/linux/mtd/onenand_regs.h20
6 files changed, 913 insertions, 87 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index e87bdbfbcc75..12df135f8af9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1380,6 +1380,16 @@ and is between 256 and 4096 characters. It is defined in the file
1380 mtdparts= [MTD] 1380 mtdparts= [MTD]
1381 See drivers/mtd/cmdlinepart.c. 1381 See drivers/mtd/cmdlinepart.c.
1382 1382
1383 onenand.bdry= [HW,MTD] Flex-OneNAND Boundary Configuration
1384
1385 Format: [die0_boundary][,die0_lock][,die1_boundary][,die1_lock]
1386
1387 boundary - index of last SLC block on Flex-OneNAND.
1388 The remaining blocks are configured as MLC blocks.
1389 lock - Configure if Flex-OneNAND boundary should be locked.
1390 Once locked, the boundary cannot be changed.
1391 1 indicates lock status, 0 indicates unlock status.
1392
1383 mtdset= [ARM] 1393 mtdset= [ARM]
1384 ARM/S3C2412 JIVE boot control 1394 ARM/S3C2412 JIVE boot control
1385 1395
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 2346857a275d..8d4c9c253732 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -9,6 +9,10 @@
9 * auto-placement support, read-while load support, various fixes 9 * auto-placement support, read-while load support, various fixes
10 * Copyright (C) Nokia Corporation, 2007 10 * Copyright (C) Nokia Corporation, 2007
11 * 11 *
12 * Vishak G <vishak.g at samsung.com>, Rohit Hagargundgi <h.rohit at samsung.com>
13 * Flex-OneNAND support
14 * Copyright (C) Samsung Electronics, 2008
15 *
12 * This program is free software; you can redistribute it and/or modify 16 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as 17 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation. 18 * published by the Free Software Foundation.
@@ -27,6 +31,30 @@
27 31
28#include <asm/io.h> 32#include <asm/io.h>
29 33
34/* Default Flex-OneNAND boundary and lock respectively */
35static int flex_bdry[MAX_DIES * 2] = { -1, 0, -1, 0 };
36
37/**
38 * onenand_oob_128 - oob info for Flex-Onenand with 4KB page
39 * For now, we expose only 64 out of 80 ecc bytes
40 */
41static struct nand_ecclayout onenand_oob_128 = {
42 .eccbytes = 64,
43 .eccpos = {
44 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
45 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
46 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
47 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
48 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
49 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
50 102, 103, 104, 105
51 },
52 .oobfree = {
53 {2, 4}, {18, 4}, {34, 4}, {50, 4},
54 {66, 4}, {82, 4}, {98, 4}, {114, 4}
55 }
56};
57
30/** 58/**
31 * onenand_oob_64 - oob info for large (2KB) page 59 * onenand_oob_64 - oob info for large (2KB) page
32 */ 60 */
@@ -65,6 +93,14 @@ static const unsigned char ffchars[] = {
65 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */ 93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */
66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */ 95 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */
96 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
97 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 80 */
98 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
99 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96 */
100 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
101 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112 */
102 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
103 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128 */
68}; 104};
69 105
70/** 106/**
@@ -171,6 +207,70 @@ static int onenand_buffer_address(int dataram1, int sectors, int count)
171} 207}
172 208
173/** 209/**
210 * flexonenand_block- For given address return block number
211 * @param this - OneNAND device structure
212 * @param addr - Address for which block number is needed
213 */
214static unsigned flexonenand_block(struct onenand_chip *this, loff_t addr)
215{
216 unsigned boundary, blk, die = 0;
217
218 if (ONENAND_IS_DDP(this) && addr >= this->diesize[0]) {
219 die = 1;
220 addr -= this->diesize[0];
221 }
222
223 boundary = this->boundary[die];
224
225 blk = addr >> (this->erase_shift - 1);
226 if (blk > boundary)
227 blk = (blk + boundary + 1) >> 1;
228
229 blk += die ? this->density_mask : 0;
230 return blk;
231}
232
233inline unsigned onenand_block(struct onenand_chip *this, loff_t addr)
234{
235 if (!FLEXONENAND(this))
236 return addr >> this->erase_shift;
237 return flexonenand_block(this, addr);
238}
239
240/**
241 * flexonenand_addr - Return address of the block
242 * @this: OneNAND device structure
243 * @block: Block number on Flex-OneNAND
244 *
245 * Return address of the block
246 */
247static loff_t flexonenand_addr(struct onenand_chip *this, int block)
248{
249 loff_t ofs = 0;
250 int die = 0, boundary;
251
252 if (ONENAND_IS_DDP(this) && block >= this->density_mask) {
253 block -= this->density_mask;
254 die = 1;
255 ofs = this->diesize[0];
256 }
257
258 boundary = this->boundary[die];
259 ofs += (loff_t)block << (this->erase_shift - 1);
260 if (block > (boundary + 1))
261 ofs += (loff_t)(block - boundary - 1) << (this->erase_shift - 1);
262 return ofs;
263}
264
265loff_t onenand_addr(struct onenand_chip *this, int block)
266{
267 if (!FLEXONENAND(this))
268 return (loff_t)block << this->erase_shift;
269 return flexonenand_addr(this, block);
270}
271EXPORT_SYMBOL(onenand_addr);
272
273/**
174 * onenand_get_density - [DEFAULT] Get OneNAND density 274 * onenand_get_density - [DEFAULT] Get OneNAND density
175 * @param dev_id OneNAND device ID 275 * @param dev_id OneNAND device ID
176 * 276 *
@@ -183,6 +283,22 @@ static inline int onenand_get_density(int dev_id)
183} 283}
184 284
185/** 285/**
286 * flexonenand_region - [Flex-OneNAND] Return erase region of addr
287 * @param mtd MTD device structure
288 * @param addr address whose erase region needs to be identified
289 */
290int flexonenand_region(struct mtd_info *mtd, loff_t addr)
291{
292 int i;
293
294 for (i = 0; i < mtd->numeraseregions; i++)
295 if (addr < mtd->eraseregions[i].offset)
296 break;
297 return i - 1;
298}