samsung.c 13 KB

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