diff options
| author | Rohit Hagargundgi <h.rohit@samsung.com> | 2009-05-12 16:46:57 -0400 |
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-06-05 13:59:21 -0400 |
| commit | 5988af2319781bc8e0ce418affec4e09cfa77907 (patch) | |
| tree | 7de04259b49ab0b50b98e9dae6a5fe61d3de67bc | |
| parent | 67ce04bf2746f8a1f8c2a104b313d20c63f68378 (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.txt | 10 | ||||
| -rw-r--r-- | drivers/mtd/onenand/onenand_base.c | 857 | ||||
| -rw-r--r-- | drivers/mtd/onenand/onenand_bbt.c | 14 | ||||
| -rw-r--r-- | drivers/mtd/onenand/onenand_sim.c | 81 | ||||
| -rw-r--r-- | include/linux/mtd/onenand.h | 18 | ||||
| -rw-r--r-- | include/linux/mtd/onenand_regs.h | 20 |
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 */ | ||
| 35 | static 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 | */ | ||
| 41 | static 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 | */ | ||
| 214 | static 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 | |||
| 233 | inline 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 | */ | ||
| 247 | static 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 | |||
| 265 | loff_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 | } | ||
| 271 | EXPORT_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 | */ | ||
| 290 | int 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 | } | ||
