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