samsung.c 14 KB

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