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