Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Rohit Hagargundgi and committed by
David Woodhouse
5988af23 67ce04bf

+917 -91
+10
Documentation/kernel-parameters.txt
··· 1380 1380 mtdparts= [MTD] 1381 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 1393 mtdset= [ARM] 1384 1394 ARM/S3C2412 JIVE boot control 1385 1395
+787 -78
drivers/mtd/onenand/onenand_base.c
··· 9 9 * auto-placement support, read-while load support, various fixes 10 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 16 * This program is free software; you can redistribute it and/or modify 13 17 * it under the terms of the GNU General Public License version 2 as 14 18 * published by the Free Software Foundation. ··· 30 26 #include <linux/mtd/partitions.h> 31 27 32 28 #include <asm/io.h> 29 + 30 + /* Default Flex-OneNAND boundary and lock respectively */ 31 + static int flex_bdry[MAX_DIES * 2] = { -1, 0, -1, 0 }; 32 + 33 + /** 34 + * onenand_oob_128 - oob info for Flex-Onenand with 4KB page 35 + * For now, we expose only 64 out of 80 ecc bytes 36 + */ 37 + static struct nand_ecclayout onenand_oob_128 = { 38 + .eccbytes = 64, 39 + .eccpos = { 40 + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 41 + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 42 + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 43 + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 44 + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 45 + 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 46 + 102, 103, 104, 105 47 + }, 48 + .oobfree = { 49 + {2, 4}, {18, 4}, {34, 4}, {50, 4}, 50 + {66, 4}, {82, 4}, {98, 4}, {114, 4} 51 + } 52 + }; 33 53 34 54 /** 35 55 * onenand_oob_64 - oob info for large (2KB) page ··· 93 65 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */ 94 66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 95 67 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */ 68 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 69 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 80 */ 70 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 71 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96 */ 72 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 73 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112 */ 74 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 75 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128 */ 96 76 }; 97 77 98 78 /** ··· 207 171 } 208 172 209 173 /** 174 + * flexonenand_block- For given address return block number 175 + * @param this - OneNAND device structure 176 + * @param addr - Address for which block number is needed 177 + */ 178 + static unsigned flexonenand_block(struct onenand_chip *this, loff_t addr) 179 + { 180 + unsigned boundary, blk, die = 0; 181 + 182 + if (ONENAND_IS_DDP(this) && addr >= this->diesize[0]) { 183 + die = 1; 184 + addr -= this->diesize[0]; 185 + } 186 + 187 + boundary = this->boundary[die]; 188 + 189 + blk = addr >> (this->erase_shift - 1); 190 + if (blk > boundary) 191 + blk = (blk + boundary + 1) >> 1; 192 + 193 + blk += die ? this->density_mask : 0; 194 + return blk; 195 + } 196 + 197 + inline unsigned onenand_block(struct onenand_chip *this, loff_t addr) 198 + { 199 + if (!FLEXONENAND(this)) 200 + return addr >> this->erase_shift; 201 + return flexonenand_block(this, addr); 202 + } 203 + 204 + /** 205 + * flexonenand_addr - Return address of the block 206 + * @this: OneNAND device structure 207 + * @block: Block number on Flex-OneNAND 208 + * 209 + * Return address of the block 210 + */ 211 + static loff_t flexonenand_addr(struct onenand_chip *this, int block) 212 + { 213 + loff_t ofs = 0; 214 + int die = 0, boundary; 215 + 216 + if (ONENAND_IS_DDP(this) && block >= this->density_mask) { 217 + block -= this->density_mask; 218 + die = 1; 219 + ofs = this->diesize[0]; 220 + } 221 + 222 + boundary = this->boundary[die]; 223 + ofs += (loff_t)block << (this->erase_shift - 1); 224 + if (block > (boundary + 1)) 225 + ofs += (loff_t)(block - boundary - 1) << (this->erase_shift - 1); 226 + return ofs; 227 + } 228 + 229 + loff_t onenand_addr(struct onenand_chip *this, int block) 230 + { 231 + if (!FLEXONENAND(this)) 232 + return (loff_t)block << this->erase_shift; 233 + return flexonenand_addr(this, block); 234 + } 235 + EXPORT_SYMBOL(onenand_addr); 236 + 237 + /** 210 238 * onenand_get_density - [DEFAULT] Get OneNAND density 211 239 * @param dev_id OneNAND device ID 212 240 * ··· 281 181 int density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; 282 182 return (density & ONENAND_DEVICE_DENSITY_MASK); 283 183 } 184 + 185 + /** 186 + * flexonenand_region - [Flex-OneNAND] Return erase region of addr 187 + * @param mtd MTD device structure 188 + * @param addr address whose erase region needs to be identified 189 + */ 190 + int flexonenand_region(struct mtd_info *mtd, loff_t addr) 191 + { 192 + int i; 193 + 194 + for (i = 0; i < mtd->numeraseregions; i++) 195 + if (addr < mtd->eraseregions[i].offset) 196 + break; 197 + return i - 1; 198 + } 199 + EXPORT_SYMBOL(flexonenand_region); 284 200 285 201 /** 286 202 * onenand_command - [DEFAULT] Send command to OneNAND device ··· 323 207 page = -1; 324 208 break; 325 209 326 - case ONENAND_CMD_ERASE: 327 - case ONENAND_CMD_BUFFERRAM: 328 - case ONENAND_CMD_OTP_ACCESS: 329 - block = (int) (addr >> this->erase_shift); 210 + case FLEXONENAND_CMD_PI_ACCESS: 211 + /* addr contains die index */ 212 + block = addr * this->density_mask; 330 213 page = -1; 331 214 break; 332 215 216 + case ONENAND_CMD_ERASE: 217 + case ONENAND_CMD_BUFFERRAM: 218 + case ONENAND_CMD_OTP_ACCESS: 219 + block = onenand_block(this, addr); 220 + page = -1; 221 + break; 222 + 223 + case FLEXONENAND_CMD_READ_PI: 224 + cmd = ONENAND_CMD_READ; 225 + block = addr * this->density_mask; 226 + page = 0; 227 + break; 228 + 333 229 default: 334 - block = (int) (addr >> this->erase_shift); 335 - page = (int) (addr >> this->page_shift); 230 + block = onenand_block(this, addr); 231 + page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; 336 232 337 233 if (ONENAND_IS_2PLANE(this)) { 338 234 /* Make the even block number */ ··· 364 236 value = onenand_bufferram_address(this, block); 365 237 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 366 238 367 - if (ONENAND_IS_2PLANE(this)) 239 + if (ONENAND_IS_MLC(this) || ONENAND_IS_2PLANE(this)) 368 240 /* It is always BufferRAM0 */ 369 241 ONENAND_SET_BUFFERRAM0(this); 370 242 else ··· 386 258 387 259 if (page != -1) { 388 260 /* Now we use page size operation */ 389 - int sectors = 4, count = 4; 261 + int sectors = 0, count = 0; 390 262 int dataram; 391 263 392 264 switch (cmd) { 265 + case FLEXONENAND_CMD_RECOVER_LSB: 393 266 case ONENAND_CMD_READ: 394 267 case ONENAND_CMD_READOOB: 395 - dataram = ONENAND_SET_NEXT_BUFFERRAM(this); 268 + if (ONENAND_IS_MLC(this)) 269 + /* It is always BufferRAM0 */ 270 + dataram = ONENAND_SET_BUFFERRAM0(this); 271 + else 272 + dataram = ONENAND_SET_NEXT_BUFFERRAM(this); 396 273 break; 397 274 398 275 default: ··· 423 290 this->write_word(cmd, this->base + ONENAND_REG_COMMAND); 424 291 425 292 return 0; 293 + } 294 + 295 + /** 296 + * onenand_read_ecc - return ecc status 297 + * @param this onenand chip structure 298 + */ 299 + static inline int onenand_read_ecc(struct onenand_chip *this) 300 + { 301 + int ecc, i, result = 0; 302 + 303 + if (!FLEXONENAND(this)) 304 + return this->read_word(this->base + ONENAND_REG_ECC_STATUS); 305 + 306 + for (i = 0; i < 4; i++) { 307 + ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS + i); 308 + if (likely(!ecc)) 309 + continue; 310 + if (ecc & FLEXONENAND_UNCORRECTABLE_ERROR) 311 + return ONENAND_ECC_2BIT_ALL; 312 + else 313 + result = ONENAND_ECC_1BIT_ALL; 314 + } 315 + 316 + return result; 426 317 } 427 318 428 319 /** ··· 488 331 * power off recovery (POR) test, it should read ECC status first 489 332 */ 490 333 if (interrupt & ONENAND_INT_READ) { 491 - int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 334 + int ecc = onenand_read_ecc(this); 492 335 if (ecc) { 493 336 if (ecc & ONENAND_ECC_2BIT_ALL) { 494 337 printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc); 495 338 mtd->ecc_stats.failed++; 496 339 return -EBADMSG; 497 340 } else if (ecc & ONENAND_ECC_1BIT_ALL) { 498 - printk(KERN_INFO "onenand_wait: correctable ECC error = 0x%04x\n", ecc); 341 + printk(KERN_DEBUG "onenand_wait: correctable ECC error = 0x%04x\n", ecc); 499 342 mtd->ecc_stats.corrected++; 500 343 } 501 344 } ··· 813 656 814 657 if (found && ONENAND_IS_DDP(this)) { 815 658 /* Select DataRAM for DDP */ 816 - int block = (int) (addr >> this->erase_shift); 659 + int block = onenand_block(this, addr); 817 660 int value = onenand_bufferram_address(this, block); 818 661 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 819 662 } ··· 973 816 } 974 817 975 818 /** 819 + * onenand_recover_lsb - [Flex-OneNAND] Recover LSB page data 820 + * @param mtd MTD device structure 821 + * @param addr address to recover 822 + * @param status return value from onenand_wait / onenand_bbt_wait 823 + * 824 + * MLC NAND Flash cell has paired pages - LSB page and MSB page. LSB page has 825 + * lower page address and MSB page has higher page address in paired pages. 826 + * If power off occurs during MSB page program, the paired LSB page data can 827 + * become corrupt. LSB page recovery read is a way to read LSB page though page 828 + * data are corrupted. When uncorrectable error occurs as a result of LSB page 829 + * read after power up, issue LSB page recovery read. 830 + */ 831 + static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status) 832 + { 833 + struct onenand_chip *this = mtd->priv; 834 + int i; 835 + 836 + /* Recovery is only for Flex-OneNAND */ 837 + if (!FLEXONENAND(this)) 838 + return status; 839 + 840 + /* check if we failed due to uncorrectable error */ 841 + if (status != -EBADMSG && status != ONENAND_BBT_READ_ECC_ERROR) 842 + return status; 843 + 844 + /* check if address lies in MLC region */ 845 + i = flexonenand_region(mtd, addr); 846 + if (mtd->eraseregions[i].erasesize < (1 << this->erase_shift)) 847 + return status; 848 + 849 + /* We are attempting to reread, so decrement stats.failed 850 + * which was incremented by onenand_wait due to read failure 851 + */ 852 + printk(KERN_INFO "onenand_recover_lsb: Attempting to recover from uncorrectable read\n"); 853 + mtd->ecc_stats.failed--; 854 + 855 + /* Issue the LSB page recovery command */ 856 + this->command(mtd, FLEXONENAND_CMD_RECOVER_LSB, addr, this->writesize); 857 + return this->wait(mtd, FL_READING); 858 + } 859 + 860 + /** 861 + * onenand_mlc_read_ops_nolock - MLC OneNAND read main and/or out-of-band 862 + * @param mtd MTD device structure 863 + * @param from offset to read from 864 + * @param ops: oob operation description structure 865 + * 866 + * MLC OneNAND / Flex-OneNAND has 4KB page size and 4KB dataram. 867 + * So, read-while-load is not present. 868 + */ 869 + static int onenand_mlc_read_ops_nolock(struct mtd_info *mtd, loff_t from, 870 + struct mtd_oob_ops *ops) 871 + { 872 + struct onenand_chip *this = mtd->priv; 873 + struct mtd_ecc_stats stats; 874 + size_t len = ops->len; 875 + size_t ooblen = ops->ooblen; 876 + u_char *buf = ops->datbuf; 877 + u_char *oobbuf = ops->oobbuf; 878 + int read = 0, column, thislen; 879 + int oobread = 0, oobcolumn, thisooblen, oobsize; 880 + int ret = 0; 881 + int writesize = this->writesize; 882 + 883 + DEBUG(MTD_DEBUG_LEVEL3, "onenand_mlc_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); 884 + 885 + if (ops->mode == MTD_OOB_AUTO) 886 + oobsize = this->ecclayout->oobavail; 887 + else 888 + oobsize = mtd->oobsize; 889 + 890 + oobcolumn = from & (mtd->oobsize - 1); 891 + 892 + /* Do not allow reads past end of device */ 893 + if (from + len > mtd->size) { 894 + printk(KERN_ERR "onenand_mlc_read_ops_nolock: Attempt read beyond end of device\n"); 895 + ops->retlen = 0; 896 + ops->oobretlen = 0; 897 + return -EINVAL; 898 + } 899 + 900 + stats = mtd->ecc_stats; 901 + 902 + while (read < len) { 903 + cond_resched(); 904 + 905 + thislen = min_t(int, writesize, len - read); 906 + 907 + column = from & (writesize - 1); 908 + if (column + thislen > writesize) 909 + thislen = writesize - column; 910 + 911 + if (!onenand_check_bufferram(mtd, from)) { 912 + this->command(mtd, ONENAND_CMD_READ, from, writesize); 913 + 914 + ret = this->wait(mtd, FL_READING); 915 + if (unlikely(ret)) 916 + ret = onenand_recover_lsb(mtd, from, ret); 917 + onenand_update_bufferram(mtd, from, !ret); 918 + if (ret == -EBADMSG) 919 + ret = 0; 920 + } 921 + 922 + this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); 923 + if (oobbuf) { 924 + thisooblen = oobsize - oobcolumn; 925 + thisooblen = min_t(int, thisooblen, ooblen - oobread); 926 + 927 + if (ops->mode == MTD_OOB_AUTO) 928 + onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen); 929 + else 930 + this->read_bufferram(mtd, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen); 931 + oobread += thisooblen; 932 + oobbuf += thisooblen; 933 + oobcolumn = 0; 934 + } 935 + 936 + read += thislen; 937 + if (read == len) 938 + break; 939 + 940 + from += thislen; 941 + buf += thislen; 942 + } 943 + 944 + /* 945 + * Return success, if no ECC failures, else -EBADMSG 946 + * fs driver will take care of that, because 947 + * retlen == desired len and result == -EBADMSG 948 + */ 949 + ops->retlen = read; 950 + ops->oobretlen = oobread; 951 + 952 + if (ret) 953 + return ret; 954 + 955 + if (mtd->ecc_stats.failed - stats.failed) 956 + return -EBADMSG; 957 + 958 + return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; 959 + } 960 + 961 + /** 976 962 * onenand_read_ops_nolock - [OneNAND Interface] OneNAND read main and/or out-of-band 977 963 * @param mtd MTD device structure 978 964 * @param from offset to read from ··· 1262 962 size_t len = ops->ooblen; 1263 963 mtd_oob_mode_t mode = ops->mode; 1264 964 u_char *buf = ops->oobbuf; 1265 - int ret = 0; 965 + int ret = 0, readcmd; 1266 966 1267 967 from += ops->ooboffs; 1268 968 ··· 1293 993 1294 994 stats = mtd->ecc_stats; 1295 995 996 + readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB; 997 + 1296 998 while (read < len) { 1297 999 cond_resched(); 1298 1000 1299 1001 thislen = oobsize - column; 1300 1002 thislen = min_t(int, thislen, len); 1301 1003 1302 - this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize); 1004 + this->command(mtd, readcmd, from, mtd->oobsize); 1303 1005 1304 1006 onenand_update_bufferram(mtd, from, 0); 1305 1007 1306 1008 ret = this->wait(mtd, FL_READING); 1009 + if (unlikely(ret)) 1010 + ret = onenand_recover_lsb(mtd, from, ret); 1011 + 1307 1012 if (ret && ret != -EBADMSG) { 1308 1013 printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret); 1309 1014 break; ··· 1358 1053 static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, 1359 1054 size_t *retlen, u_char *buf) 1360 1055 { 1056 + struct onenand_chip *this = mtd->priv; 1361 1057 struct mtd_oob_ops ops = { 1362 1058 .len = len, 1363 1059 .ooblen = 0, ··· 1368 1062 int ret; 1369 1063 1370 1064 onenand_get_device(mtd, FL_READING); 1371 - ret = onenand_read_ops_nolock(mtd, from, &ops); 1065 + ret = ONENAND_IS_MLC(this) ? 1066 + onenand_mlc_read_ops_nolock(mtd, from, &ops) : 1067 + onenand_read_ops_nolock(mtd, from, &ops); 1372 1068 onenand_release_device(mtd); 1373 1069 1374 1070 *retlen = ops.retlen; ··· 1388 1080 static int onenand_read_oob(struct mtd_info *mtd, loff_t from, 1389 1081 struct mtd_oob_ops *ops) 1390 1082 { 1083 + struct onenand_chip *this = mtd->priv; 1391 1084 int ret; 1392 1085 1393 1086 switch (ops->mode) { ··· 1403 1094 1404 1095 onenand_get_device(mtd, FL_READING); 1405 1096 if (ops->datbuf) 1406 - ret = onenand_read_ops_nolock(mtd, from, ops); 1097 + ret = ONENAND_IS_MLC(this) ? 1098 + onenand_mlc_read_ops_nolock(mtd, from, ops) : 1099 + onenand_read_ops_nolock(mtd, from, ops); 1407 1100 else 1408 1101 ret = onenand_read_oob_nolock(mtd, from, ops); 1409 1102 onenand_release_device(mtd); ··· 1439 1128 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); 1440 1129 1441 1130 if (interrupt & ONENAND_INT_READ) { 1442 - int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); 1131 + int ecc = onenand_read_ecc(this); 1443 1132 if (ecc & ONENAND_ECC_2BIT_ALL) { 1444 1133 printk(KERN_INFO "onenand_bbt_wait: ecc error = 0x%04x" 1445 1134 ", controller error 0x%04x\n", ecc, ctrl); 1446 - return ONENAND_BBT_READ_ERROR; 1135 + return ONENAND_BBT_READ_ECC_ERROR; 1447 1136 } 1448 1137 } else { 1449 1138 printk(KERN_ERR "onenand_bbt_wait: read timeout!" ··· 1474 1163 { 1475 1164 struct onenand_chip *this = mtd->priv; 1476 1165 int read = 0, thislen, column; 1477 - int ret = 0; 1166 + int ret = 0, readcmd; 1478 1167 size_t len = ops->ooblen; 1479 1168 u_char *buf = ops->oobbuf; 1480 1169 ··· 1494 1183 1495 1184 column = from & (mtd->oobsize - 1); 1496 1185 1186 + readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB; 1187 + 1497 1188 while (read < len) { 1498 1189 cond_resched(); 1499 1190 1500 1191 thislen = mtd->oobsize - column; 1501 1192 thislen = min_t(int, thislen, len); 1502 1193 1503 - this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize); 1194 + this->command(mtd, readcmd, from, mtd->oobsize); 1504 1195 1505 1196 onenand_update_bufferram(mtd, from, 0); 1506 1197 1507 1198 ret = onenand_bbt_wait(mtd, FL_READING); 1199 + if (unlikely(ret)) 1200 + ret = onenand_recover_lsb(mtd, from, ret); 1201 + 1508 1202 if (ret) 1509 1203 break; 1510 1204 ··· 1546 1230 { 1547 1231 struct onenand_chip *this = mtd->priv; 1548 1232 u_char *oob_buf = this->oob_buf; 1549 - int status, i; 1233 + int status, i, readcmd; 1550 1234 1551 - this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize); 1235 + readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB; 1236 + 1237 + this->command(mtd, readcmd, to, mtd->oobsize); 1552 1238 onenand_update_bufferram(mtd, to, 0); 1553 1239 status = this->wait(mtd, FL_READING); 1554 1240 if (status) ··· 1951 1633 { 1952 1634 struct onenand_chip *this = mtd->priv; 1953 1635 int column, ret = 0, oobsize; 1954 - int written = 0; 1636 + int written = 0, oobcmd; 1955 1637 u_char *oobbuf; 1956 1638 size_t len = ops->ooblen; 1957 1639 const u_char *buf = ops->oobbuf; ··· 1993 1675 1994 1676 oobbuf = this->oob_buf; 1995 1677 1678 + oobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB; 1679 + 1996 1680 /* Loop until all data write */ 1997 1681 while (written < len) { 1998 1682 int thislen = min_t(int, oobsize, len - written); ··· 2012 1692 memcpy(oobbuf + column, buf, thislen); 2013 1693 this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize); 2014 1694 2015 - this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize); 1695 + if (ONENAND_IS_MLC(this)) { 1696 + /* Set main area of DataRAM to 0xff*/ 1697 + memset(this->page_buf, 0xff, mtd->writesize); 1698 + this->write_bufferram(mtd, ONENAND_DATARAM, 1699 + this->page_buf, 0, mtd->writesize); 1700 + } 1701 + 1702 + this->command(mtd, oobcmd, to, mtd->oobsize); 2016 1703 2017 1704 onenand_update_bufferram(mtd, to, 0); 2018 1705 if (ONENAND_IS_2PLANE(this)) { ··· 2142 1815 { 2143 1816 struct onenand_chip *this = mtd->priv; 2144 1817 unsigned int block_size; 2145 - loff_t addr; 2146 - int len; 2147 - int ret = 0; 1818 + loff_t addr = instr->addr; 1819 + loff_t len = instr->len; 1820 + int ret = 0, i; 1821 + struct mtd_erase_region_info *region = NULL; 1822 + loff_t region_end = 0; 2148 1823 2149 1824 DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%012llx, len = %llu\n", (unsigned long long) instr->addr, (unsigned long long) instr->len); 2150 1825 2151 - block_size = (1 << this->erase_shift); 2152 - 2153 - /* Start address must align on block boundary */ 2154 - if (unlikely(instr->addr & (block_size - 1))) { 2155 - printk(KERN_ERR "onenand_erase: Unaligned address\n"); 1826 + /* Do not allow erase past end of device */ 1827 + if (unlikely((len + addr) > mtd->size)) { 1828 + printk(KERN_ERR "onenand_erase: Erase past end of device\n"); 2156 1829 return -EINVAL; 1830 + } 1831 + 1832 + if (FLEXONENAND(this)) { 1833 + /* Find the eraseregion of this address */ 1834 + i = flexonenand_region(mtd, addr); 1835 + region = &mtd->eraseregions[i]; 1836 + 1837 + block_size = region->erasesize; 1838 + region_end = region->offset + region->erasesize * region->numblocks; 1839 + 1840 + /* Start address within region must align on block boundary. 1841 + * Erase region's start offset is always block start address. 1842 + */ 1843 + if (unlikely((addr - region->offset) & (block_size - 1))) { 1844 + printk(KERN_ERR "onenand_erase: Unaligned address\n"); 1845 + return -EINVAL; 1846 + } 1847 + } else { 1848 + block_size = 1 << this->erase_shift; 1849 + 1850 + /* Start address must align on block boundary */ 1851 + if (unlikely(addr & (block_size - 1))) { 1852 + printk(KERN_ERR "onenand_erase: Unaligned address\n"); 1853 + return -EINVAL; 1854 + } 2157 1855 } 2158 1856 2159 1857 /* Length must align on block boundary */ 2160 - if (unlikely(instr->len & (block_size - 1))) { 1858 + if (unlikely(len & (block_size - 1))) { 2161 1859 printk(KERN_ERR "onenand_erase: Length not block aligned\n"); 2162 - return -EINVAL; 2163 - } 2164 - 2165 - /* Do not allow erase past end of device */ 2166 - if (unlikely((instr->len + instr->addr) > mtd->size)) { 2167 - printk(KERN_ERR "onenand_erase: Erase past end of device\n"); 2168 1860 return -EINVAL; 2169 1861 } 2170 1862 ··· 2193 1847 onenand_get_device(mtd, FL_ERASING); 2194 1848 2195 1849 /* Loop throught the pages */ 2196 - len = instr->len; 2197 - addr = instr->addr; 2198 - 2199 1850 instr->state = MTD_ERASING; 2200 1851 2201 1852 while (len) { ··· 2212 1869 ret = this->wait(mtd, FL_ERASING); 2213 1870 /* Check, if it is write protected */ 2214 1871 if (ret) { 2215 - printk(KERN_ERR "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift)); 1872 + printk(KERN_ERR "onenand_erase: Failed erase, block %d\n", 1873 + onenand_block(this, addr)); 2216 1874 instr->state = MTD_ERASE_FAILED; 2217 1875 instr->fail_addr = addr; 2218 1876 goto erase_exit; ··· 2221 1877 2222 1878 len -= block_size; 2223 1879 addr += block_size; 1880 + 1881 + if (addr == region_end) { 1882 + if (!len) 1883 + break; 1884 + region++; 1885 + 1886 + block_size = region->erasesize; 1887 + region_end = region->offset + region->erasesize * region->numblocks; 1888 + 1889 + if (len & (block_size - 1)) { 1890 + /* FIXME: This should be handled at MTD partitioning level. */ 1891 + printk(KERN_ERR "onenand_erase: Unaligned address\n"); 1892 + goto erase_exit; 1893 + } 1894 + } 1895 + 2224 1896 } 2225 1897 2226 1898 instr->state = MTD_ERASE_DONE; ··· 2315 1955 int block; 2316 1956 2317 1957 /* Get block number */ 2318 - block = ((int) ofs) >> bbm->bbt_erase_shift; 1958 + block = onenand_block(this, ofs); 2319 1959 if (bbm->bbt) 2320 1960 bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); 2321 1961 2322 1962 /* We write two bytes, so we dont have to mess with 16 bit access */ 2323 1963 ofs += mtd->oobsize + (bbm->badblockpos & ~0x01); 2324 - return onenand_write_oob_nolock(mtd, ofs, &ops); 1964 + /* FIXME : What to do when marking SLC block in partition 1965 + * with MLC erasesize? For now, it is not advisable to 1966 + * create partitions containing both SLC and MLC regions. 1967 + */ 1968 + return onenand_write_oob_nolock(mtd, ofs, &ops); 2325 1969 } 2326 1970 2327 1971 /** ··· 2369 2005 int start, end, block, value, status; 2370 2006 int wp_status_mask; 2371 2007 2372 - start = ofs >> this->erase_shift; 2373 - end = len >> this->erase_shift; 2008 + start = onenand_block(this, ofs); 2009 + end = onenand_block(this, ofs + len) - 1; 2374 2010 2375 2011 if (cmd == ONENAND_CMD_LOCK) 2376 2012 wp_status_mask = ONENAND_WP_LS; ··· 2382 2018 /* Set start block address */ 2383 2019 this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS); 2384 2020 /* Set end block address */ 2385 - this->write_word(start + end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); 2021 + this->write_word(end, this->base + ONENAND_REG_END_BLOCK_ADDRESS); 2386 2022 /* Write lock command */ 2387 2023 this->command(mtd, cmd, 0, 0); 2388 2024 ··· 2403 2039 } 2404 2040 2405 2041 /* Block lock scheme */ 2406 - for (block = start; block < start + end; block++) { 2042 + for (block = start; block < end + 1; block++) { 2407 2043 /* Set block address */ 2408 2044 value = onenand_block_address(this, block); 2409 2045 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); ··· 2511 2147 { 2512 2148 struct onenand_chip *this = mtd->priv; 2513 2149 loff_t ofs = 0; 2514 - size_t len = this->chipsize; 2150 + loff_t len = mtd->size; 2515 2151 2516 2152 if (this->options & ONENAND_HAS_UNLOCK_ALL) { 2517 2153 /* Set start block address */ ··· 2532 2168 return; 2533 2169 2534 2170 /* Workaround for all block unlock in DDP */ 2535 - if (ONENAND_IS_DDP(this)) { 2171 + if (ONENAND_IS_DDP(this) && !FLEXONENAND(this)) { 2536 2172 /* All blocks on another chip */ 2537 2173 ofs = this->chipsize >> 1; 2538 2174 len = this->chipsize >> 1; ··· 2574 2210 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); 2575 2211 this->wait(mtd, FL_OTPING); 2576 2212 2577 - ret = onenand_read_ops_nolock(mtd, from, &ops); 2213 + ret = ONENAND_IS_MLC(this) ? 2214 + onenand_mlc_read_ops_nolock(mtd, from, &ops) : 2215 + onenand_read_ops_nolock(mtd, from, &ops); 2578 2216 2579 2217 /* Exit OTP access mode */ 2580 2218 this->command(mtd, ONENAND_CMD_RESET, 0, 0); ··· 2643 2277 size_t *retlen, u_char *buf) 2644 2278 { 2645 2279 struct onenand_chip *this = mtd->priv; 2646 - struct mtd_oob_ops ops = { 2647 - .mode = MTD_OOB_PLACE, 2648 - .ooblen = len, 2649 - .oobbuf = buf, 2650 - .ooboffs = 0, 2651 - }; 2280 + struct mtd_oob_ops ops; 2652 2281 int ret; 2653 2282 2654 2283 /* Enter OTP access mode */ 2655 2284 this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0); 2656 2285 this->wait(mtd, FL_OTPING); 2657 2286 2658 - ret = onenand_write_oob_nolock(mtd, from, &ops); 2659 - 2660 - *retlen = ops.oobretlen; 2287 + if (FLEXONENAND(this)) { 2288 + /* 2289 + * For Flex-OneNAND, we write lock mark to 1st word of sector 4 of 2290 + * main area of page 49. 2291 + */ 2292 + ops.len = mtd->writesize; 2293 + ops.ooblen = 0; 2294 + ops.datbuf = buf; 2295 + ops.oobbuf = NULL; 2296 + ret = onenand_write_ops_nolock(mtd, mtd->writesize * 49, &ops); 2297 + *retlen = ops.retlen; 2298 + } else { 2299 + ops.mode = MTD_OOB_PLACE; 2300 + ops.ooblen = len; 2301 + ops.oobbuf = buf; 2302 + ops.ooboffs = 0; 2303 + ret = onenand_write_oob_nolock(mtd, from, &ops); 2304 + *retlen = ops.oobretlen; 2305 + } 2661 2306 2662 2307 /* Exit OTP access mode */ 2663 2308 this->command(mtd, ONENAND_CMD_RESET, 0, 0); ··· 2852 2475 size_t len) 2853 2476 { 2854 2477 struct onenand_chip *this = mtd->priv; 2855 - u_char *oob_buf = this->oob_buf; 2478 + u_char *buf = FLEXONENAND(this) ? this->page_buf : this->oob_buf; 2856 2479 size_t retlen; 2857 2480 int ret; 2858 2481 2859 - memset(oob_buf, 0xff, mtd->oobsize); 2482 + memset(buf, 0xff, FLEXONENAND(this) ? this->writesize 2483 + : mtd->oobsize); 2860 2484 /* 2861 2485 * Note: OTP lock operation 2862 2486 * OTP block : 0xXXFC 2863 2487 * 1st block : 0xXXF3 (If chip support) 2864 2488 * Both : 0xXXF0 (If chip support) 2865 2489 */ 2866 - oob_buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC; 2490 + if (FLEXONENAND(this)) 2491 + buf[FLEXONENAND_OTP_LOCK_OFFSET] = 0xFC; 2492 + else 2493 + buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC; 2867 2494 2868 2495 /* 2869 2496 * Write lock mark to 8th word of sector0 of page0 of the spare0. 2870 2497 * We write 16 bytes spare area instead of 2 bytes. 2498 + * For Flex-OneNAND, we write lock mark to 1st word of sector 4 of 2499 + * main area of page 49. 2871 2500 */ 2872 - from = 0; 2873 - len = 16; 2874 2501 2875 - ret = onenand_otp_walk(mtd, from, len, &retlen, oob_buf, do_otp_lock, MTD_OTP_USER); 2502 + from = 0; 2503 + len = FLEXONENAND(this) ? mtd->writesize : 16; 2504 + 2505 + ret = onenand_otp_walk(mtd, from, len, &retlen, buf, do_otp_lock, MTD_OTP_USER); 2876 2506 2877 2507 return ret ? : retlen; 2878 2508 } ··· 2926 2542 break; 2927 2543 } 2928 2544 2545 + if (ONENAND_IS_MLC(this)) 2546 + this->options &= ~ONENAND_HAS_2PLANE; 2547 + 2548 + if (FLEXONENAND(this)) { 2549 + this->options &= ~ONENAND_HAS_CONT_LOCK; 2550 + this->options |= ONENAND_HAS_UNLOCK_ALL; 2551 + } 2552 + 2929 2553 if (this->options & ONENAND_HAS_CONT_LOCK) 2930 2554 printk(KERN_DEBUG "Lock scheme is Continuous Lock\n"); 2931 2555 if (this->options & ONENAND_HAS_UNLOCK_ALL) ··· 2951 2559 */ 2952 2560 static void onenand_print_device_info(int device, int version) 2953 2561 { 2954 - int vcc, demuxed, ddp, density; 2562 + int vcc, demuxed, ddp, density, flexonenand; 2955 2563 2956 2564 vcc = device & ONENAND_DEVICE_VCC_MASK; 2957 2565 demuxed = device & ONENAND_DEVICE_IS_DEMUX; 2958 2566 ddp = device & ONENAND_DEVICE_IS_DDP; 2959 2567 density = onenand_get_density(device); 2960 - printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n", 2961 - demuxed ? "" : "Muxed ", 2568 + flexonenand = device & DEVICE_IS_FLEXONENAND; 2569 + printk(KERN_INFO "%s%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n", 2570 + demuxed ? "" : "Muxed ", 2571 + flexonenand ? "Flex-" : "", 2962 2572 ddp ? "(DDP)" : "", 2963 2573 (16 << density), 2964 2574 vcc ? "2.65/3.3" : "1.8", ··· 2998 2604 2999 2605 return (i == size); 3000 2606 } 2607 + 2608 + /** 2609 + * flexonenand_get_boundary - Reads the SLC boundary 2610 + * @param onenand_info - onenand info structure 2611 + **/ 2612 + static int flexonenand_get_boundary(struct mtd_info *mtd) 2613 + { 2614 + struct onenand_chip *this = mtd->priv; 2615 + unsigned die, bdry; 2616 + int ret, syscfg, locked; 2617 + 2618 + /* Disable ECC */ 2619 + syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1); 2620 + this->write_word((syscfg | 0x0100), this->base + ONENAND_REG_SYS_CFG1); 2621 + 2622 + for (die = 0; die < this->dies; die++) { 2623 + this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0); 2624 + this->wait(mtd, FL_SYNCING); 2625 + 2626 + this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0); 2627 + ret = this->wait(mtd, FL_READING); 2628 + 2629 + bdry = this->read_word(this->base + ONENAND_DATARAM); 2630 + if ((bdry >> FLEXONENAND_PI_UNLOCK_SHIFT) == 3) 2631 + locked = 0; 2632 + else 2633 + locked = 1; 2634 + this->boundary[die] = bdry & FLEXONENAND_PI_MASK; 2635 + 2636 + this->command(mtd, ONENAND_CMD_RESET, 0, 0); 2637 + ret = this->wait(mtd, FL_RESETING); 2638 + 2639 + printk(KERN_INFO "Die %d boundary: %d%s\n", die, 2640 + this->boundary[die], locked ? "(Locked)" : "(Unlocked)"); 2641 + } 2642 + 2643 + /* Enable ECC */ 2644 + this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); 2645 + return 0; 2646 + } 2647 + 2648 + /** 2649 + * flexonenand_get_size - Fill up fields in onenand_chip and mtd_info 2650 + * boundary[], diesize[], mtd->size, mtd->erasesize 2651 + * @param mtd - MTD device structure 2652 + */ 2653 + static void flexonenand_get_size(struct mtd_info *mtd) 2654 + { 2655 + struct onenand_chip *this = mtd->priv; 2656 + int die, i, eraseshift, density; 2657 + int blksperdie, maxbdry; 2658 + loff_t ofs; 2659 + 2660 + density = onenand_get_density(this->device_id); 2661 + blksperdie = ((loff_t)(16 << density) << 20) >> (this->erase_shift); 2662 + blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0; 2663 + maxbdry = blksperdie - 1; 2664 + eraseshift = this->erase_shift - 1; 2665 + 2666 + mtd->numeraseregions = this->dies << 1; 2667 + 2668 + /* This fills up the device boundary */ 2669 + flexonenand_get_boundary(mtd); 2670 + die = ofs = 0; 2671 + i = -1; 2672 + for (; die < this->dies; die++) { 2673 + if (!die || this->boundary[die-1] != maxbdry) { 2674 + i++; 2675 + mtd->eraseregions[i].offset = ofs; 2676 + mtd->eraseregions[i].erasesize = 1 << eraseshift; 2677 + mtd->eraseregions[i].numblocks = 2678 + this->boundary[die] + 1; 2679 + ofs += mtd->eraseregions[i].numblocks << eraseshift; 2680 + eraseshift++; 2681 + } else { 2682 + mtd->numeraseregions -= 1; 2683 + mtd->eraseregions[i].numblocks += 2684 + this->boundary[die] + 1; 2685 + ofs += (this->boundary[die] + 1) << (eraseshift - 1); 2686 + } 2687 + if (this->boundary[die] != maxbdry) { 2688 + i++; 2689 + mtd->eraseregions[i].offset = ofs; 2690 + mtd->eraseregions[i].erasesize = 1 << eraseshift; 2691 + mtd->eraseregions[i].numblocks = maxbdry ^ 2692 + this->boundary[die]; 2693 + ofs += mtd->eraseregions[i].numblocks << eraseshift; 2694 + eraseshift--; 2695 + } else 2696 + mtd->numeraseregions -= 1; 2697 + } 2698 + 2699 + /* Expose MLC erase size except when all blocks are SLC */ 2700 + mtd->erasesize = 1 << this->erase_shift; 2701 + if (mtd->numeraseregions == 1) 2702 + mtd->erasesize >>= 1; 2703 + 2704 + printk(KERN_INFO "Device has %d eraseregions\n", mtd->numeraseregions); 2705 + for (i = 0; i < mtd->numeraseregions; i++) 2706 + printk(KERN_INFO "[offset: 0x%08x, erasesize: 0x%05x," 2707 + " numblocks: %04u]\n", 2708 + (unsigned int) mtd->eraseregions[i].offset, 2709 + mtd->eraseregions[i].erasesize, 2710 + mtd->eraseregions[i].numblocks); 2711 + 2712 + for (die = 0, mtd->size = 0; die < this->dies; die++) { 2713 + this->diesize[die] = (loff_t)blksperdie << this->erase_shift; 2714 + this->diesize[die] -= (loff_t)(this->boundary[die] + 1) 2715 + << (this->erase_shift - 1); 2716 + mtd->size += this->diesize[die]; 2717 + } 2718 + } 2719 + 2720 + /** 2721 + * flexonenand_check_blocks_erased - Check if blocks are erased 2722 + * @param mtd_info - mtd info structure 2723 + * @param start - first erase block to check 2724 + * @param end - last erase block to check 2725 + * 2726 + * Converting an unerased block from MLC to SLC 2727 + * causes byte values to change. Since both data and its ECC 2728 + * have changed, reads on the block give uncorrectable error. 2729 + * This might lead to the block being detected as bad. 2730 + * 2731 + * Avoid this by ensuring that the block to be converted is 2732 + * erased. 2733 + */ 2734 + static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int end) 2735 + { 2736 + struct onenand_chip *this = mtd->priv; 2737 + int i, ret; 2738 + int block; 2739 + struct mtd_oob_ops ops = { 2740 + .mode = MTD_OOB_PLACE, 2741 + .ooboffs = 0, 2742 + .ooblen = mtd->oobsize, 2743 + .datbuf = NULL, 2744 + .oobbuf = this->oob_buf, 2745 + }; 2746 + loff_t addr; 2747 + 2748 + printk(KERN_DEBUG "Check blocks from %d to %d\n", start, end); 2749 + 2750 + for (block = start; block <= end; block++) { 2751 + addr = flexonenand_addr(this, block); 2752 + if (onenand_block_isbad_nolock(mtd, addr, 0)) 2753 + continue; 2754 + 2755 + /* 2756 + * Since main area write results in ECC write to spare, 2757 + * it is sufficient to check only ECC bytes for change. 2758 + */ 2759 + ret = onenand_read_oob_nolock(mtd, addr, &ops); 2760 + if (ret) 2761 + return ret; 2762 + 2763 + for (i = 0; i < mtd->oobsize; i++) 2764 + if (this->oob_buf[i] != 0xff) 2765 + break; 2766 + 2767 + if (i != mtd->oobsize) { 2768 + printk(KERN_WARNING "Block %d not erased.\n", block); 2769 + return 1; 2770 + } 2771 + } 2772 + 2773 + return 0; 2774 + } 2775 + 2776 + /** 2777 + * flexonenand_set_boundary - Writes the SLC boundary 2778 + * @param mtd - mtd info structure 2779 + */ 2780 + int flexonenand_set_boundary(struct mtd_info *mtd, int die, 2781 + int boundary, int lock) 2782 + { 2783 + struct onenand_chip *this = mtd->priv; 2784 + int ret, density, blksperdie, old, new, thisboundary; 2785 + loff_t addr; 2786 + 2787 + /* Change only once for SDP Flex-OneNAND */ 2788 + if (die && (!ONENAND_IS_DDP(this))) 2789 + return 0; 2790 + 2791 + /* boundary value of -1 indicates no required change */ 2792 + if (boundary < 0 || boundary == this->boundary[die]) 2793 + return 0; 2794 + 2795 + density = onenand_get_density(this->device_id); 2796 + blksperdie = ((16 << density) << 20) >> this->erase_shift; 2797 + blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0; 2798 + 2799 + if (boundary >= blksperdie) { 2800 + printk(KERN_ERR "flexonenand_set_boundary: Invalid boundary value. " 2801 + "Boundary not changed.\n"); 2802 + return -EINVAL; 2803 + } 2804 + 2805 + /* Check if converting blocks are erased */ 2806 + old = this->boundary[die] + (die * this->density_mask); 2807 + new = boundary + (die * this->density_mask); 2808 + ret = flexonenand_check_blocks_erased(mtd, min(old, new) + 1, max(old, new)); 2809 + if (ret) { 2810 + printk(KERN_ERR "flexonenand_set_boundary: Please erase blocks before boundary change\n"); 2811 + return ret; 2812 + } 2813 + 2814 + this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0); 2815 + this->wait(mtd, FL_SYNCING); 2816 + 2817 + /* Check is boundary is locked */ 2818 + this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0); 2819 + ret = this->wait(mtd, FL_READING); 2820 + 2821 + thisboundary = this->read_word(this->base + ONENAND_DATARAM); 2822 + if ((thisboundary >> FLEXONENAND_PI_UNLOCK_SHIFT) != 3) { 2823 + printk(KERN_ERR "flexonenand_set_boundary: boundary locked\n"); 2824 + ret = 1; 2825 + goto out; 2826 + } 2827 + 2828 + printk(KERN_INFO "flexonenand_set_boundary: Changing die %d boundary: %d%s\n", 2829 + die, boundary, lock ? "(Locked)" : "(Unlocked)"); 2830 + 2831 + addr = die ? this->diesize[0] : 0; 2832 + 2833 + boundary &= FLEXONENAND_PI_MASK; 2834 + boundary |= lock ? 0 : (3 << FLEXONENAND_PI_UNLOCK_SHIFT); 2835 + 2836 + this->command(mtd, ONENAND_CMD_ERASE, addr, 0); 2837 + ret = this->wait(mtd, FL_ERASING); 2838 + if (ret) { 2839 + printk(KERN_ERR "flexonenand_set_boundary: Failed PI erase for Die %d\n", die); 2840 + goto out; 2841 + } 2842 + 2843 + this->write_word(boundary, this->base + ONENAND_DATARAM); 2844 + this->command(mtd, ONENAND_CMD_PROG, addr, 0); 2845 + ret = this->wait(mtd, FL_WRITING); 2846 + if (ret) { 2847 + printk(KERN_ERR "flexonenand_set_boundary: Failed PI write for Die %d\n", die); 2848 + goto out; 2849 + } 2850 + 2851 + this->command(mtd, FLEXONENAND_CMD_PI_UPDATE, die, 0); 2852 + ret = this->wait(mtd, FL_WRITING); 2853 + out: 2854 + this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_REG_COMMAND); 2855 + this->wait(mtd, FL_RESETING); 2856 + if (!ret) 2857 + /* Recalculate device size on boundary change*/ 2858 + flexonenand_get_size(mtd); 2859 + 2860 + return ret; 2861 + } 2862 + 2863 + /** 2864 + * flexonenand_setup - capture Flex-OneNAND boundary and lock 2865 + * values passed as kernel parameters 2866 + * @param s kernel parameter string 2867 + */ 2868 + static int flexonenand_setup(char *s) 2869 + { 2870 + int ints[5], i; 2871 + 2872 + s = get_options(s, 5, ints); 2873 + 2874 + for (i = 0; i < ints[0]; i++) 2875 + flex_bdry[i] = ints[i + 1]; 2876 + 2877 + return 1; 2878 + } 2879 + 2880 + __setup("onenand.bdry=", flexonenand_setup); 3001 2881 3002 2882 /** 3003 2883 * onenand_probe - [OneNAND Interface] Probe the OneNAND device ··· 3315 2647 maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); 3316 2648 dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); 3317 2649 ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); 2650 + this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY); 3318 2651 3319 2652 /* Check OneNAND device */ 3320 2653 if (maf_id != bram_maf_id || dev_id != bram_dev_id) ··· 3327 2658 this->version_id = ver_id; 3328 2659 3329 2660 density = onenand_get_density(dev_id); 2661 + if (FLEXONENAND(this)) { 2662 + this->dies = ONENAND_IS_DDP(this) ? 2 : 1; 2663 + /* Maximum possible erase regions */ 2664 + mtd->numeraseregions = this->dies << 1; 2665 + mtd->eraseregions = kzalloc(sizeof(struct mtd_erase_region_info) 2666 + * (this->dies << 1), GFP_KERNEL); 2667 + if (!mtd->eraseregions) 2668 + return -ENOMEM; 2669 + } 2670 + 2671 + /* 2672 + * For Flex-OneNAND, chipsize represents maximum possible device size. 2673 + * mtd->size represents the actual device size. 2674 + */ 3330 2675 this->chipsize = (16 << density) << 20; 3331 - /* Set density mask. it is used for DDP */ 3332 - if (ONENAND_IS_DDP(this)) 3333 - this->density_mask = (1 << (density + 6)); 3334 - else 3335 - this->density_mask = 0; 3336 2676 3337 2677 /* OneNAND page size & block size */ 3338 2678 /* The data buffer size is equal to page size */ 3339 2679 mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); 2680 + /* We use the full BufferRAM */ 2681 + if (ONENAND_IS_MLC(this)) 2682 + mtd->writesize <<= 1; 2683 + 3340 2684 mtd->oobsize = mtd->writesize >> 5; 3341 2685 /* Pages per a block are always 64 in OneNAND */ 3342 2686 mtd->erasesize = mtd->writesize << 6; 2687 + /* 2688 + * Flex-OneNAND SLC area has 64 pages per block. 2689 + * Flex-OneNAND MLC area has 128 pages per block. 2690 + * Expose MLC erase size to find erase_shift and page_mask. 2691 + */ 2692 + if (FLEXONENAND(this)) 2693 + mtd->erasesize <<= 1; 3343 2694 3344 2695 this->erase_shift = ffs(mtd->erasesize) - 1; 3345 2696 this->page_shift = ffs(mtd->writesize) - 1; 3346 2697 this->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1; 2698 + /* Set density mask. it is used for DDP */ 2699 + if (ONENAND_IS_DDP(this)) 2700 + this->density_mask = this->chipsize >> (this->erase_shift + 1); 3347 2701 /* It's real page size */ 3348 2702 this->writesize = mtd->writesize; 3349 2703 3350 2704 /* REVIST: Multichip handling */ 3351 2705 3352 - mtd->size = this->chipsize; 2706 + if (FLEXONENAND(this)) 2707 + flexonenand_get_size(mtd); 2708 + else 2709 + mtd->size = this->chipsize; 3353 2710 3354 2711 /* Check OneNAND features */ 3355 2712 onenand_check_features(mtd); ··· 3430 2735 */ 3431 2736 int onenand_scan(struct mtd_info *mtd, int maxchips) 3432 2737 { 3433 - int i; 2738 + int i, ret; 3434 2739 struct onenand_chip *this = mtd->priv; 3435 2740 3436 2741 if (!this->read_word) ··· 3492 2797 * Allow subpage writes up to oobsize. 3493 2798 */ 3494 2799 switch (mtd->oobsize) { 2800 + case 128: 2801 + this->ecclayout = &onenand_oob_128; 2802 + mtd->subpage_sft = 0; 2803 + break; 3495 2804 case 64: 3496 2805 this->ecclayout = &onenand_oob_64; 3497 2806 mtd->subpage_sft = 2; ··· 3561 2862 /* Unlock whole block */ 3562 2863 onenand_unlock_all(mtd); 3563 2864 3564 - return this->scan_bbt(mtd); 2865 + ret = this->scan_bbt(mtd); 2866 + if ((!FLEXONENAND(this)) || ret) 2867 + return ret; 2868 + 2869 + /* Change Flex-OneNAND boundaries if required */ 2870 + for (i = 0; i < MAX_DIES; i++) 2871 + flexonenand_set_boundary(mtd, i, flex_bdry[2 * i], 2872 + flex_bdry[(2 * i) + 1]); 2873 + 2874 + return 0; 3565 2875 } 3566 2876 3567 2877 /** ··· 3599 2891 kfree(this->page_buf); 3600 2892 if (this->options & ONENAND_OOBBUF_ALLOC) 3601 2893 kfree(this->oob_buf); 2894 + kfree(mtd->eraseregions); 3602 2895 } 3603 2896 3604 2897 EXPORT_SYMBOL_GPL(onenand_scan);
+10 -4
drivers/mtd/onenand/onenand_bbt.c
··· 63 63 loff_t from; 64 64 size_t readlen, ooblen; 65 65 struct mtd_oob_ops ops; 66 + int rgn; 66 67 67 68 printk(KERN_INFO "Scanning device for bad blocks\n"); 68 69 ··· 77 76 /* Note that numblocks is 2 * (real numblocks) here; 78 77 * see i += 2 below as it makses shifting and masking less painful 79 78 */ 80 - numblocks = mtd->size >> (bbm->bbt_erase_shift - 1); 79 + numblocks = this->chipsize >> (bbm->bbt_erase_shift - 1); 81 80 startblock = 0; 82 81 from = 0; 83 82 ··· 107 106 } 108 107 } 109 108 i += 2; 110 - from += (1 << bbm->bbt_erase_shift); 109 + 110 + if (FLEXONENAND(this)) { 111 + rgn = flexonenand_region(mtd, from); 112 + from += mtd->eraseregions[rgn].erasesize; 113 + } else 114 + from += (1 << bbm->bbt_erase_shift); 111 115 } 112 116 113 117 return 0; ··· 149 143 uint8_t res; 150 144 151 145 /* Get block number * 2 */ 152 - block = (int) (offs >> (bbm->bbt_erase_shift - 1)); 146 + block = (int) (onenand_block(this, offs) << 1); 153 147 res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03; 154 148 155 149 DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n", ··· 184 178 struct bbm_info *bbm = this->bbm; 185 179 int len, ret = 0; 186 180 187 - len = mtd->size >> (this->erase_shift + 2); 181 + len = this->chipsize >> (this->erase_shift + 2); 188 182 /* Allocate memory (2bit per block) and clear the memory bad block table */ 189 183 bbm->bbt = kzalloc(len, GFP_KERNEL); 190 184 if (!bbm->bbt) {
+74 -7
drivers/mtd/onenand/onenand_sim.c
··· 6 6 * Copyright © 2005-2007 Samsung Electronics 7 7 * Kyungmin Park <kyungmin.park@samsung.com> 8 8 * 9 + * Vishak G <vishak.g at samsung.com>, Rohit Hagargundgi <h.rohit at samsung.com> 10 + * Flex-OneNAND simulator support 11 + * Copyright (C) Samsung Electronics, 2008 12 + * 9 13 * This program is free software; you can redistribute it and/or modify 10 14 * it under the terms of the GNU General Public License version 2 as 11 15 * published by the Free Software Foundation. ··· 28 24 #ifndef CONFIG_ONENAND_SIM_MANUFACTURER 29 25 #define CONFIG_ONENAND_SIM_MANUFACTURER 0xec 30 26 #endif 27 + 31 28 #ifndef CONFIG_ONENAND_SIM_DEVICE_ID 32 29 #define CONFIG_ONENAND_SIM_DEVICE_ID 0x04 33 30 #endif 31 + 32 + #define CONFIG_FLEXONENAND ((CONFIG_ONENAND_SIM_DEVICE_ID >> 9) & 1) 33 + 34 34 #ifndef CONFIG_ONENAND_SIM_VERSION_ID 35 35 #define CONFIG_ONENAND_SIM_VERSION_ID 0x1e 36 + #endif 37 + 38 + #ifndef CONFIG_ONENAND_SIM_TECHNOLOGY_ID 39 + #define CONFIG_ONENAND_SIM_TECHNOLOGY_ID CONFIG_FLEXONENAND 40 + #endif 41 + 42 + /* Initial boundary values for Flex-OneNAND Simulator */ 43 + #ifndef CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY 44 + #define CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY 0x01 45 + #endif 46 + 47 + #ifndef CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY 48 + #define CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY 0x01 36 49 #endif 37 50 38 51 static int manuf_id = CONFIG_ONENAND_SIM_MANUFACTURER; 39 52 static int device_id = CONFIG_ONENAND_SIM_DEVICE_ID; 40 53 static int version_id = CONFIG_ONENAND_SIM_VERSION_ID; 54 + static int technology_id = CONFIG_ONENAND_SIM_TECHNOLOGY_ID; 55 + static int boundary[] = { 56 + CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY, 57 + CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY, 58 + }; 41 59 42 60 struct onenand_flash { 43 61 void __iomem *base; ··· 83 57 (writew(v, this->base + ONENAND_REG_WP_STATUS)) 84 58 85 59 /* It has all 0xff chars */ 86 - #define MAX_ONENAND_PAGESIZE (2048 + 64) 60 + #define MAX_ONENAND_PAGESIZE (4096 + 128) 87 61 static unsigned char *ffchars; 62 + 63 + #if CONFIG_FLEXONENAND 64 + #define PARTITION_NAME "Flex-OneNAND simulator partition" 65 + #else 66 + #define PARTITION_NAME "OneNAND simulator partition" 67 + #endif 88 68 89 69 static struct mtd_partition os_partitions[] = { 90 70 { 91 - .name = "OneNAND simulator partition", 71 + .name = PARTITION_NAME, 92 72 .offset = 0, 93 73 .size = MTDPART_SIZ_FULL, 94 74 }, ··· 136 104 137 105 switch (cmd) { 138 106 case ONENAND_CMD_UNLOCK: 107 + case ONENAND_CMD_UNLOCK_ALL: 139 108 if (block_lock_scheme) 140 109 ONENAND_SET_WP_STATUS(ONENAND_WP_US, this); 141 110 else ··· 261 228 { 262 229 struct mtd_info *mtd = &info->mtd; 263 230 struct onenand_flash *flash = this->priv; 264 - int main_offset, spare_offset; 231 + int main_offset, spare_offset, die = 0; 265 232 void __iomem *src; 266 233 void __iomem *dest; 267 234 unsigned int i; 235 + static int pi_operation; 236 + int erasesize, rgn; 268 237 269 238 if (dataram) { 270 239 main_offset = mtd->writesize; ··· 276 241 spare_offset = 0; 277 242 } 278 243 244 + if (pi_operation) { 245 + die = readw(this->base + ONENAND_REG_START_ADDRESS2); 246 + die >>= ONENAND_DDP_SHIFT; 247 + } 248 + 279 249 switch (cmd) { 250 + case FLEXONENAND_CMD_PI_ACCESS: 251 + pi_operation = 1; 252 + break; 253 + 254 + case ONENAND_CMD_RESET: 255 + pi_operation = 0; 256 + break; 257 + 280 258 case ONENAND_CMD_READ: 281 259 src = ONENAND_CORE(flash) + offset; 282 260 dest = ONENAND_MAIN_AREA(this, main_offset); 261 + if (pi_operation) { 262 + writew(boundary[die], this->base + ONENAND_DATARAM); 263 + break; 264 + } 283 265 memcpy(dest, src, mtd->writesize); 284 266 /* Fall through */ 285 267 ··· 309 257 case ONENAND_CMD_PROG: 310 258 src = ONENAND_MAIN_AREA(this, main_offset); 311 259 dest = ONENAND_CORE(flash) + offset; 260 + if (pi_operation) { 261 + boundary[die] = readw(this->base + ONENAND_DATARAM); 262 + break; 263 + } 312 264 /* To handle partial write */ 313 265 for (i = 0; i < (1 << mtd->subpage_sft); i++) { 314 266 int off = i * this->subpagesize; ··· 340 284 break; 341 285 342 286 case ONENAND_CMD_ERASE: 343 - memset(ONENAND_CORE(flash) + offset, 0xff, mtd->erasesize); 287 + if (pi_operation) 288 + break; 289 + 290 + if (FLEXONENAND(this)) { 291 + rgn = flexonenand_region(mtd, offset); 292 + erasesize = mtd->eraseregions[rgn].erasesize; 293 + } else 294 + erasesize = mtd->erasesize; 295 + 296 + memset(ONENAND_CORE(flash) + offset, 0xff, erasesize); 344 297 memset(ONENAND_CORE_SPARE(flash, this, offset), 0xff, 345 - (mtd->erasesize >> 5)); 298 + (erasesize >> 5)); 346 299 break; 347 300 348 301 default: ··· 404 339 } 405 340 406 341 if (block != -1) 407 - offset += block << this->erase_shift; 342 + offset = onenand_addr(this, block); 408 343 409 344 if (page != -1) 410 345 offset += page << this->page_shift; ··· 455 390 } 456 391 457 392 density = device_id >> ONENAND_DEVICE_DENSITY_SHIFT; 393 + density &= ONENAND_DEVICE_DENSITY_MASK; 458 394 size = ((16 << 20) << density); 459 395 460 396 ONENAND_CORE(flash) = vmalloc(size + (size >> 5)); ··· 471 405 writew(manuf_id, flash->base + ONENAND_REG_MANUFACTURER_ID); 472 406 writew(device_id, flash->base + ONENAND_REG_DEVICE_ID); 473 407 writew(version_id, flash->base + ONENAND_REG_VERSION_ID); 408 + writew(technology_id, flash->base + ONENAND_REG_TECHNOLOGY); 474 409 475 - if (density < 2) 410 + if (density < 2 && (!CONFIG_FLEXONENAND)) 476 411 buffer_size = 0x0400; /* 1KiB page */ 477 412 else 478 413 buffer_size = 0x0800; /* 2KiB page */
+18
include/linux/mtd/onenand.h
··· 17 17 #include <linux/mtd/onenand_regs.h> 18 18 #include <linux/mtd/bbm.h> 19 19 20 + #define MAX_DIES 2 20 21 #define MAX_BUFFERRAM 2 21 22 22 23 /* Scan and identify a OneNAND device */ ··· 52 51 /** 53 52 * struct onenand_chip - OneNAND Private Flash Chip Data 54 53 * @base: [BOARDSPECIFIC] address to access OneNAND 54 + * @dies: [INTERN][FLEX-ONENAND] number of dies on chip 55 + * @boundary: [INTERN][FLEX-ONENAND] Boundary of the dies 56 + * @diesize: [INTERN][FLEX-ONENAND] Size of the dies 55 57 * @chipsize: [INTERN] the size of one chip for multichip arrays 58 + * FIXME For Flex-OneNAND, chipsize holds maximum possible 59 + * device size ie when all blocks are considered MLC 56 60 * @device_id: [INTERN] device ID 57 61 * @density_mask: chip density, used for DDP devices 58 62 * @verstion_id: [INTERN] version ID ··· 98 92 */ 99 93 struct onenand_chip { 100 94 void __iomem *base; 95 + unsigned dies; 96 + unsigned boundary[MAX_DIES]; 97 + loff_t diesize[MAX_DIES]; 101 98 unsigned int chipsize; 102 99 unsigned int device_id; 103 100 unsigned int version_id; 101 + unsigned int technology; 104 102 unsigned int density_mask; 105 103 unsigned int options; 106 104 ··· 155 145 #define ONENAND_SET_BUFFERRAM0(this) (this->bufferram_index = 0) 156 146 #define ONENAND_SET_BUFFERRAM1(this) (this->bufferram_index = 1) 157 147 148 + #define FLEXONENAND(this) \ 149 + (this->device_id & DEVICE_IS_FLEXONENAND) 158 150 #define ONENAND_GET_SYS_CFG1(this) \ 159 151 (this->read_word(this->base + ONENAND_REG_SYS_CFG1)) 160 152 #define ONENAND_SET_SYS_CFG1(v, this) \ ··· 164 152 165 153 #define ONENAND_IS_DDP(this) \ 166 154 (this->device_id & ONENAND_DEVICE_IS_DDP) 155 + 156 + #define ONENAND_IS_MLC(this) \ 157 + (this->technology & ONENAND_TECHNOLOGY_IS_MLC) 167 158 168 159 #ifdef CONFIG_MTD_ONENAND_2X_PROGRAM 169 160 #define ONENAND_IS_2PLANE(this) \ ··· 205 190 206 191 int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, 207 192 struct mtd_oob_ops *ops); 193 + unsigned onenand_block(struct onenand_chip *this, loff_t addr); 194 + loff_t onenand_addr(struct onenand_chip *this, int block); 195 + int flexonenand_region(struct mtd_info *mtd, loff_t addr); 208 196 209 197 #endif /* __LINUX_MTD_ONENAND_H */
+18 -2
include/linux/mtd/onenand_regs.h
··· 67 67 /* 68 68 * Device ID Register F001h (R) 69 69 */ 70 + #define DEVICE_IS_FLEXONENAND (1 << 9) 71 + #define FLEXONENAND_PI_MASK (0x3ff) 72 + #define FLEXONENAND_PI_UNLOCK_SHIFT (14) 70 73 #define ONENAND_DEVICE_DENSITY_MASK (0xf) 71 74 #define ONENAND_DEVICE_DENSITY_SHIFT (4) 72 75 #define ONENAND_DEVICE_IS_DDP (1 << 3) ··· 87 84 #define ONENAND_VERSION_PROCESS_SHIFT (8) 88 85 89 86 /* 87 + * Technology Register F006h (R) 88 + */ 89 + #define ONENAND_TECHNOLOGY_IS_MLC (1 << 0) 90 + 91 + /* 90 92 * Start Address 1 F100h (R/W) & Start Address 2 F101h (R/W) 91 93 */ 92 94 #define ONENAND_DDP_SHIFT (15) ··· 101 93 /* 102 94 * Start Address 8 F107h (R/W) 103 95 */ 104 - #define ONENAND_FPA_MASK (0x3f) 96 + /* Note: It's actually 0x3f in case of SLC */ 97 + #define ONENAND_FPA_MASK (0x7f) 105 98 #define ONENAND_FPA_SHIFT (2) 106 99 #define ONENAND_FSA_MASK (0x03) 107 100 ··· 114 105 #define ONENAND_BSA_BOOTRAM (0 << 2) 115 106 #define ONENAND_BSA_DATARAM0 (2 << 2) 116 107 #define ONENAND_BSA_DATARAM1 (3 << 2) 117 - #define ONENAND_BSC_MASK (0x03) 108 + /* Note: It's actually 0x03 in case of SLC */ 109 + #define ONENAND_BSC_MASK (0x07) 118 110 119 111 /* 120 112 * Command Register F220h (R/W) ··· 134 124 #define ONENAND_CMD_RESET (0xF0) 135 125 #define ONENAND_CMD_OTP_ACCESS (0x65) 136 126 #define ONENAND_CMD_READID (0x90) 127 + #define FLEXONENAND_CMD_PI_UPDATE (0x05) 128 + #define FLEXONENAND_CMD_PI_ACCESS (0x66) 129 + #define FLEXONENAND_CMD_RECOVER_LSB (0x05) 137 130 138 131 /* NOTE: Those are not *REAL* commands */ 139 132 #define ONENAND_CMD_BUFFERRAM (0x1978) 133 + #define FLEXONENAND_CMD_READ_PI (0x1985) 140 134 141 135 /* 142 136 * System Configuration 1 Register F221h (R, R/W) ··· 206 192 #define ONENAND_ECC_1BIT_ALL (0x5555) 207 193 #define ONENAND_ECC_2BIT (1 << 1) 208 194 #define ONENAND_ECC_2BIT_ALL (0xAAAA) 195 + #define FLEXONENAND_UNCORRECTABLE_ERROR (0x1010) 209 196 210 197 /* 211 198 * One-Time Programmable (OTP) 212 199 */ 200 + #define FLEXONENAND_OTP_LOCK_OFFSET (2048) 213 201 #define ONENAND_OTP_LOCK_OFFSET (14) 214 202 215 203 #endif /* __ONENAND_REG_H */