1 /* 2 * S3C64XX/S5PC100 OneNAND driver at U-Boot 3 * 4 * Copyright (C) 2008-2009 Samsung Electronics 5 * Kyungmin Park <kyungmin.park@samsung.com> 6 * 7 * Implementation: 8 * Emulate the pseudo BufferRAM 9 * 10 * See file CREDITS for list of people who contributed to this 11 * project. 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License as 15 * published by the Free Software Foundation; either version 2 of 16 * the License, or (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 26 * MA 02111-1307 USA 27 */ 28 29 #include <common.h> 30 #include <malloc.h> 31 #include <linux/mtd/compat.h> 32 #include <linux/mtd/mtd.h> 33 #include <linux/mtd/onenand.h> 34 #include <linux/mtd/samsung_onenand.h> 35 36 #include <asm/io.h> 37 #include <asm/errno.h> 38 39 #ifdef ONENAND_DEBUG 40 #define DPRINTK(format, args...) \ 41 do { \ 42 printf("%s[%d]: " format "\n", __func__, __LINE__, ##args); \ 43 } while (0) 44 #else 45 #define DPRINTK(...) do { } while (0) 46 #endif 47 48 #define ONENAND_ERASE_STATUS 0x00 49 #define ONENAND_MULTI_ERASE_SET 0x01 50 #define ONENAND_ERASE_START 0x03 51 #define ONENAND_UNLOCK_START 0x08 52 #define ONENAND_UNLOCK_END 0x09 53 #define ONENAND_LOCK_START 0x0A 54 #define ONENAND_LOCK_END 0x0B 55 #define ONENAND_LOCK_TIGHT_START 0x0C 56 #define ONENAND_LOCK_TIGHT_END 0x0D 57 #define ONENAND_UNLOCK_ALL 0x0E 58 #define ONENAND_OTP_ACCESS 0x12 59 #define ONENAND_SPARE_ACCESS_ONLY 0x13 60 #define ONENAND_MAIN_ACCESS_ONLY 0x14 61 #define ONENAND_ERASE_VERIFY 0x15 62 #define ONENAND_MAIN_SPARE_ACCESS 0x16 63 #define ONENAND_PIPELINE_READ 0x4000 64 65 #if defined(CONFIG_S3C64XX) 66 #define MAP_00 (0x0 << 24) 67 #define MAP_01 (0x1 << 24) 68 #define MAP_10 (0x2 << 24) 69 #define MAP_11 (0x3 << 24) 70 #elif defined(CONFIG_S5P) 71 #define MAP_00 (0x0 << 26) 72 #define MAP_01 (0x1 << 26) 73 #define MAP_10 (0x2 << 26) 74 #define MAP_11 (0x3 << 26) 75 #endif 76 77 /* read/write of XIP buffer */ 78 #define CMD_MAP_00(mem_addr) (MAP_00 | ((mem_addr) << 1)) 79 /* read/write to the memory device */ 80 #define CMD_MAP_01(mem_addr) (MAP_01 | (mem_addr)) 81 /* control special functions of the memory device */ 82 #define CMD_MAP_10(mem_addr) (MAP_10 | (mem_addr)) 83 /* direct interface(direct access) with the memory device */ 84 #define CMD_MAP_11(mem_addr) (MAP_11 | ((mem_addr) << 2)) 85 86 struct s3c_onenand { 87 struct mtd_info *mtd; 88 void __iomem *base; 89 void __iomem *ahb_addr; 90 int bootram_command; 91 void __iomem *page_buf; 92 void __iomem *oob_buf; 93 unsigned int (*mem_addr)(int fba, int fpa, int fsa); 94 struct samsung_onenand *reg; 95 }; 96 97 static struct s3c_onenand *onenand; 98 99 static int s3c_read_cmd(unsigned int cmd) 100 { 101 return readl(onenand->ahb_addr + cmd); 102 } 103 104 static void s3c_write_cmd(int value, unsigned int cmd) 105 { 106 writel(value, onenand->ahb_addr + cmd); 107 } 108 109 /* 110 * MEM_ADDR 111 * 112 * fba: flash block address 113 * fpa: flash page address 114 * fsa: flash sector address 115 * 116 * return the buffer address on the memory device 117 * It will be combined with CMD_MAP_XX 118 */ 119 #if defined(CONFIG_S3C64XX) 120 static unsigned int s3c_mem_addr(int fba, int fpa, int fsa) 121 { 122 return (fba << 12) | (fpa << 6) | (fsa << 4); 123 } 124 #elif defined(CONFIG_S5P) 125 static unsigned int s3c_mem_addr(int fba, int fpa, int fsa) 126 { 127 return (fba << 13) | (fpa << 7) | (fsa << 5); 128 } 129 #endif 130 131 static void s3c_onenand_reset(void) 132 { 133 unsigned long timeout = 0x10000; 134 int stat; 135 136 writel(ONENAND_MEM_RESET_COLD, &onenand->reg->mem_reset); 137 while (timeout--) { 138 stat = readl(&onenand->reg->int_err_stat); 139 if (stat & RST_CMP) 140 break; 141 } 142 stat = readl(&onenand->reg->int_err_stat); 143 writel(stat, &onenand->reg->int_err_ack); 144 145 /* Clear interrupt */ 146 writel(0x0, &onenand->reg->int_err_ack); 147 /* Clear the ECC status */ 148 writel(0x0, &onenand->reg->ecc_err_stat); 149 } 150 151 static unsigned short s3c_onenand_readw(void __iomem *addr) 152 { 153 struct onenand_chip *this = onenand->mtd->priv; 154 int reg = addr - this->base; 155 int word_addr = reg >> 1; 156 int value; 157 158 /* It's used for probing time */ 159 switch (reg) { 160 case ONENAND_REG_MANUFACTURER_ID: 161 return readl(&onenand->reg->manufact_id); 162 case ONENAND_REG_DEVICE_ID: 163 return readl(&onenand->reg->device_id); 164 case ONENAND_REG_VERSION_ID: 165 return readl(&onenand->reg->flash_ver_id); 166 case ONENAND_REG_DATA_BUFFER_SIZE: 167 return readl(&onenand->reg->data_buf_size); 168 case ONENAND_REG_TECHNOLOGY: 169 return readl(&onenand->reg->tech); 170 case ONENAND_REG_SYS_CFG1: 171 return readl(&onenand->reg->mem_cfg); 172 173 /* Used at unlock all status */ 174 case ONENAND_REG_CTRL_STATUS: 175 return 0; 176 177 case ONENAND_REG_WP_STATUS: 178 return ONENAND_WP_US; 179 180 default: 181 break; 182 } 183 184 /* BootRAM access control */ 185 if (reg < ONENAND_DATARAM && onenand->bootram_command) { 186 if (word_addr == 0) 187 return readl(&onenand->reg->manufact_id); 188 if (word_addr == 1) 189 return readl(&onenand->reg->device_id); 190 if (word_addr == 2) 191 return readl(&onenand->reg->flash_ver_id); 192 } 193 194 value = s3c_read_cmd(CMD_MAP_11(word_addr)) & 0xffff; 195 printk(KERN_INFO "s3c_onenand_readw: Illegal access" 196 " at reg 0x%x, value 0x%x\n", word_addr, value); 197 return value; 198 } 199 200 static void s3c_onenand_writew(unsigned short value, void __iomem *addr) 201 { 202 struct onenand_chip *this = onenand->mtd->priv; 203 int reg = addr - this->base; 204 int word_addr = reg >> 1; 205 206 /* It's used for probing time */ 207 switch (reg) { 208 case ONENAND_REG_SYS_CFG1: 209 writel(value, &onenand->reg->mem_cfg); 210 return; 211 212 case ONENAND_REG_START_ADDRESS1: 213 case ONENAND_REG_START_ADDRESS2: 214 return; 215 216 /* Lock/lock-tight/unlock/unlock_all */ 217 case ONENAND_REG_START_BLOCK_ADDRESS: 218 return; 219 220 default: 221 break; 222 } 223 224 /* BootRAM access control */ 225 if (reg < ONENAND_DATARAM) { 226 if (value == ONENAND_CMD_READID) { 227 onenand->bootram_command = 1; 228 return; 229 } 230 if (value == ONENAND_CMD_RESET) { 231 writel(ONENAND_MEM_RESET_COLD, 232 &onenand->reg->mem_reset); 233 onenand->bootram_command = 0; 234 return; 235 } 236 } 237 238 printk(KERN_INFO "s3c_onenand_writew: Illegal access" 239 " at reg 0x%x, value 0x%x\n", word_addr, value); 240 241 s3c_write_cmd(value, CMD_MAP_11(word_addr)); 242 } 243 244 static int s3c_onenand_wait(struct mtd_info *mtd, int state) 245 { 246 unsigned int flags = INT_ACT; 247 unsigned int stat, ecc; 248 unsigned long timeout = 0x100000; 249 250 switch (state) { 251 case FL_READING: 252 flags |= BLK_RW_CMP | LOAD_CMP; 253 break; 254 case FL_WRITING: 255 flags |= BLK_RW_CMP | PGM_CMP; 256 break; 257 case FL_ERASING: 258 flags |= BLK_RW_CMP | ERS_CMP; 259 break; 260 case FL_LOCKING: 261 flags |= BLK_RW_CMP; 262 break; 263 default: 264 break; 265 } 266 267 while (timeout--) { 268 stat = readl(&onenand->reg->int_err_stat); 269 if (stat & flags) 270 break; 271 } 272 273 /* To get correct interrupt status in timeout case */ 274 stat = readl(&onenand->reg->int_err_stat); 275 writel(stat, &onenand->reg->int_err_ack); 276 277 /* 278 * In the Spec. it checks the controller status first 279 * However if you get the correct information in case of 280 * power off recovery (POR) test, it should read ECC status first 281 */ 282 if (stat & LOAD_CMP) { 283 ecc = readl(&onenand->reg->ecc_err_stat); 284 if (ecc & ONENAND_ECC_4BIT_UNCORRECTABLE) { 285 printk(KERN_INFO "%s: ECC error = 0x%04x\n", 286 __func__, ecc); 287 mtd->ecc_stats.failed++; 288 return -EBADMSG; 289 } 290 } 291 292 if (stat & (LOCKED_BLK | ERS_FAIL | PGM_FAIL | LD_FAIL_ECC_ERR)) { 293 printk(KERN_INFO "%s: controller error = 0x%04x\n", 294 __func__, stat); 295 if (stat & LOCKED_BLK) 296 printk(KERN_INFO "%s: it's locked error = 0x%04x\n", 297 __func__, stat); 298 299 return -EIO; 300 } 301 302 return 0; 303 } 304 305 static int s3c_onenand_command(struct mtd_info *mtd, int cmd, 306 loff_t addr, size_t len) 307 { 308 struct onenand_chip *this = mtd->priv; 309 unsigned int *m, *s; 310 int fba, fpa, fsa = 0; 311 unsigned int mem_addr; 312 int i, mcount, scount; 313 int index; 314 315 fba = (int) (addr >> this->erase_shift); 316 fpa = (int) (addr >> this->page_shift); 317 fpa &= this->page_mask; 318 319 mem_addr = onenand->mem_addr(fba, fpa, fsa); 320 321 switch (cmd) { 322 case ONENAND_CMD_READ: 323 case ONENAND_CMD_READOOB: 324 case ONENAND_CMD_BUFFERRAM: 325 ONENAND_SET_NEXT_BUFFERRAM(this); 326 default: 327 break; 328 } 329 330 index = ONENAND_CURRENT_BUFFERRAM(this); 331 332 /* 333 * Emulate Two BufferRAMs and access with 4 bytes pointer 334 */ 335 m = (unsigned int *) onenand->page_buf; 336 s = (unsigned int *) onenand->oob_buf; 337 338 if (index) { 339 m += (this->writesize >> 2); 340 s += (mtd->oobsize >> 2); 341 } 342 343 mcount = mtd->writesize >> 2; 344 scount = mtd->oobsize >> 2; 345 346 switch (cmd) { 347 case ONENAND_CMD_READ: 348 /* Main */ 349 for (i = 0; i < mcount; i++) 350 *m++ = s3c_read_cmd(CMD_MAP_01(mem_addr)); 351 return 0; 352 353 case ONENAND_CMD_READOOB: 354 writel(TSRF, &onenand->reg->trans_spare); 355 /* Main */ 356 for (i = 0; i < mcount; i++) 357 *m++ = s3c_read_cmd(CMD_MAP_01(mem_addr)); 358 359 /* Spare */ 360 for (i = 0; i < scount; i++) 361 *s++ = s3c_read_cmd(CMD_MAP_01(mem_addr)); 362 363 writel(0, &onenand->reg->trans_spare); 364 return 0; 365 366 case ONENAND_CMD_PROG: 367 /* Main */ 368 for (i = 0; i < mcount; i++) 369 s3c_write_cmd(*m++, CMD_MAP_01(mem_addr)); 370 return 0; 371 372 case ONENAND_CMD_PROGOOB: 373 writel(TSRF, &onenand->reg->trans_spare); 374 375 /* Main - dummy write */ 376 for (i = 0; i < mcount; i++) 377 s3c_write_cmd(0xffffffff, CMD_MAP_01(mem_addr)); 378 379 /* Spare */ 380 for (i = 0; i < scount; i++) 381 s3c_write_cmd(*s++, CMD_MAP_01(mem_addr)); 382 383 writel(0, &onenand->reg->trans_spare); 384 return 0; 385 386 case ONENAND_CMD_UNLOCK_ALL: 387 s3c_write_cmd(ONENAND_UNLOCK_ALL, CMD_MAP_10(mem_addr)); 388 return 0; 389 390 case ONENAND_CMD_ERASE: 391 s3c_write_cmd(ONENAND_ERASE_START, CMD_MAP_10(mem_addr)); 392 return 0; 393 394 case ONENAND_CMD_MULTIBLOCK_ERASE: 395 s3c_write_cmd(ONENAND_MULTI_ERASE_SET, CMD_MAP_10(mem_addr)); 396 return 0; 397 398 case ONENAND_CMD_ERASE_VERIFY: 399 s3c_write_cmd(ONENAND_ERASE_VERIFY, CMD_MAP_10(mem_addr)); 400 return 0; 401 402 default: 403 break; 404 } 405 406 return 0; 407 } 408 409 static unsigned char *s3c_get_bufferram(struct mtd_info *mtd, int area) 410 { 411 struct onenand_chip *this = mtd->priv; 412 int index = ONENAND_CURRENT_BUFFERRAM(this); 413 unsigned char *p; 414 415 if (area == ONENAND_DATARAM) { 416 p = (unsigned char *) onenand->page_buf; 417 if (index == 1) 418 p += this->writesize; 419 } else { 420 p = (unsigned char *) onenand->oob_buf; 421 if (index == 1) 422 p += mtd->oobsize; 423 } 424 425 return p; 426 } 427 428 static int onenand_read_bufferram(struct mtd_info *mtd, loff_t addr, int area, 429 unsigned char *buffer, int offset, 430 size_t count) 431 { 432 unsigned char *p; 433 434 p = s3c_get_bufferram(mtd, area); 435 memcpy(buffer, p + offset, count); 436 return 0; 437 } 438 439 static int onenand_write_bufferram(struct mtd_info *mtd, loff_t addr, int area, 440 const unsigned char *buffer, int offset, 441 size_t count) 442 { 443 unsigned char *p; 444 445 p = s3c_get_bufferram(mtd, area); 446 memcpy(p + offset, buffer, count); 447 return 0; 448 } 449 450 static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state) 451 { 452 struct samsung_onenand *reg = (struct samsung_onenand *)onenand->base; 453 unsigned int flags = INT_ACT | LOAD_CMP; 454 unsigned int stat; 455 unsigned long timeout = 0x10000; 456 457 while (timeout--) { 458 stat = readl(®->int_err_stat); 459 if (stat & flags) 460 break; 461 } 462 /* To get correct interrupt status in timeout case */ 463 stat = readl(&onenand->reg->int_err_stat); 464 writel(stat, &onenand->reg->int_err_ack); 465 466 if (stat & LD_FAIL_ECC_ERR) { 467 s3c_onenand_reset(); 468 return ONENAND_BBT_READ_ERROR; 469 } 470 471 if (stat & LOAD_CMP) { 472 int ecc = readl(&onenand->reg->ecc_err_stat); 473 if (ecc & ONENAND_ECC_4BIT_UNCORRECTABLE) { 474 s3c_onenand_reset(); 475 return ONENAND_BBT_READ_ERROR; 476 } 477 } 478 479 return 0; 480 } 481 482 static void s3c_onenand_check_lock_status(struct mtd_info *mtd) 483 { 484 struct onenand_chip *this = mtd->priv; 485 unsigned int block, end; 486 int tmp; 487 488 end = this->chipsize >> this->erase_shift; 489 490 for (block = 0; block < end; block++) { 491 tmp = s3c_read_cmd(CMD_MAP_01(onenand->mem_addr(block, 0, 0))); 492 493 if (readl(&onenand->reg->int_err_stat) & LOCKED_BLK) { 494 printf("block %d is write-protected!\n", block); 495 writel(LOCKED_BLK, &onenand->reg->int_err_ack); 496 } 497 } 498 } 499 500 static void s3c_onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, 501 size_t len, int cmd) 502 { 503 struct onenand_chip *this = mtd->priv; 504 int start, end, start_mem_addr, end_mem_addr; 505 506 start = ofs >> this->erase_shift; 507 start_mem_addr = onenand->mem_addr(start, 0, 0); 508 end = start + (len >> this->erase_shift) - 1; 509 end_mem_addr = onenand->mem_addr(end, 0, 0); 510 511 if (cmd == ONENAND_CMD_LOCK) { 512 s3c_write_cmd(ONENAND_LOCK_START, CMD_MAP_10(start_mem_addr)); 513 s3c_write_cmd(ONENAND_LOCK_END, CMD_MAP_10(end_mem_addr)); 514 } else { 515 s3c_write_cmd(ONENAND_UNLOCK_START, CMD_MAP_10(start_mem_addr)); 516 s3c_write_cmd(ONENAND_UNLOCK_END, CMD_MAP_10(end_mem_addr)); 517 } 518 519 this->wait(mtd, FL_LOCKING); 520 } 521 522 static void s3c_onenand_unlock_all(struct mtd_info *mtd) 523 { 524 struct onenand_chip *this = mtd->priv; 525 loff_t ofs = 0; 526 size_t len = this->chipsize; 527 528 /* FIXME workaround */ 529 this->subpagesize = mtd->writesize; 530 mtd->subpage_sft = 0; 531 532 if (this->options & ONENAND_HAS_UNLOCK_ALL) { 533 /* Write unlock command */ 534 this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0); 535 536 /* No need to check return value */ 537 this->wait(mtd, FL_LOCKING); 538 539 /* Workaround for all block unlock in DDP */ 540 if (!ONENAND_IS_DDP(this)) { 541 s3c_onenand_check_lock_status(mtd); 542 return; 543 } 544 545 /* All blocks on another chip */ 546 ofs = this->chipsize >> 1; 547 len = this->chipsize >> 1; 548 } 549 550 s3c_onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK); 551 s3c_onenand_check_lock_status(mtd); 552 } 553 554 #ifdef CONFIG_S3C64XX 555 static void s3c_set_width_regs(struct onenand_chip *this) 556 { 557 int dev_id, density; 558 int fba, fpa, fsa; 559 int dbs_dfs; 560 561 dev_id = DEVICE_ID0_REG; 562 563 density = (dev_id >> ONENAND_DEVICE_DENSITY_SHIFT) & 0xf; 564 dbs_dfs = !!(dev_id & ONENAND_DEVICE_IS_DDP); 565 566 fba = density + 7; 567 if (dbs_dfs) 568 fba--; /* Decrease the fba */ 569 fpa = 6; 570 if (density >= ONENAND_DEVICE_DENSITY_512Mb) 571 fsa = 2; 572 else 573 fsa = 1; 574 575 DPRINTK("FBA %lu, FPA %lu, FSA %lu, DDP %lu", 576 FBA_WIDTH0_REG, FPA_WIDTH0_REG, FSA_WIDTH0_REG, 577 DDP_DEVICE_REG); 578 579 DPRINTK("mem_cfg0 0x%lx, sync mode %lu, " 580 "dev_page_size %lu, BURST LEN %lu", 581 MEM_CFG0_REG, SYNC_MODE_REG, 582 DEV_PAGE_SIZE_REG, BURST_LEN0_REG); 583 584 DEV_PAGE_SIZE_REG = 0x1; 585 586 FBA_WIDTH0_REG = fba; 587 FPA_WIDTH0_REG = fpa; 588 FSA_WIDTH0_REG = fsa; 589 DBS_DFS_WIDTH0_REG = dbs_dfs; 590 } 591 #endif 592 593 void s3c_onenand_init(struct mtd_info *mtd) 594 { 595 struct onenand_chip *this = mtd->priv; 596 u32 size = (4 << 10); /* 4 KiB */ 597 598 onenand = malloc(sizeof(struct s3c_onenand)); 599 if (!onenand) 600 return; 601 602 onenand->page_buf = malloc(size * sizeof(char)); 603 if (!onenand->page_buf) 604 return; 605 memset(onenand->page_buf, 0xff, size); 606 607 onenand->oob_buf = malloc(128 * sizeof(char)); 608 if (!onenand->oob_buf) 609 return; 610 memset(onenand->oob_buf, 0xff, 128); 611 612 onenand->mtd = mtd; 613 614 #if defined(CONFIG_S3C64XX) 615 onenand->base = (void *)0x70100000; 616 onenand->ahb_addr = (void *)0x20000000; 617 #elif defined(CONFIG_S5P) 618 onenand->base = (void *)0xE7100000; 619 onenand->ahb_addr = (void *)0xB0000000; 620 #endif 621 onenand->mem_addr = s3c_mem_addr; 622 onenand->reg = (struct samsung_onenand *)onenand->base; 623 624 this->read_word = s3c_onenand_readw; 625 this->write_word = s3c_onenand_writew; 626 627 this->wait = s3c_onenand_wait; 628 this->bbt_wait = s3c_onenand_bbt_wait; 629 this->unlock_all = s3c_onenand_unlock_all; 630 this->command = s3c_onenand_command; 631 632 this->read_bufferram = onenand_read_bufferram; 633 this->write_bufferram = onenand_write_bufferram; 634 635 this->options |= ONENAND_RUNTIME_BADBLOCK_CHECK; 636 } 637