flashkw.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /*
  2. * sheevaplug nand flash driver
  3. *
  4. * for now separate from (inferno's) os/port/flashnand.c because the flash
  5. * seems newer, and has different commands, but that is nand-chip specific,
  6. * not sheevaplug-specific. they should be merged in future.
  7. *
  8. * the sheevaplug has a hynix 4gbit flash chip: hy27uf084g2m.
  9. * 2048 byte pages, with 64 spare bytes each; erase block size is 128k.
  10. *
  11. * it has a "glueless" interface, at 0xf9000000. that's the address
  12. * of the data register. the command and address registers are those
  13. * or'ed with 1 and 2 respectively.
  14. *
  15. * linux uses this layout for the nand flash (from address 0 onwards):
  16. * 1mb for u-boot
  17. * 4mb for kernel
  18. * 507mb for file system
  19. *
  20. * this is not so relevant here except for ecc. the first two areas
  21. * (u-boot and kernel) are expected to have 4-bit ecc per 512 bytes
  22. * (but calculated from last byte to first), bad erase blocks skipped.
  23. * the file system area has 1-bit ecc per 256 bytes.
  24. */
  25. #include "u.h"
  26. #include "../port/lib.h"
  27. #include "mem.h"
  28. #include "dat.h"
  29. #include "fns.h"
  30. #include "io.h"
  31. #include "../port/error.h"
  32. #include "../port/flashif.h"
  33. #include "../port/nandecc.h"
  34. enum {
  35. Debug = 0,
  36. Nopage = ~0ul, /* cache is empty */
  37. /* vendors */
  38. Hynix = 0xad,
  39. Samsung = 0xec,
  40. /* chips */
  41. Hy27UF084G2M = 0xdc,
  42. NandActCEBoot = 1<<1,
  43. };
  44. typedef struct Nandreg Nandreg;
  45. typedef struct Nandtab Nandtab;
  46. typedef struct Cache Cache;
  47. struct Nandreg { /* hw registers */
  48. ulong rdparms;
  49. ulong wrparms;
  50. uchar _pad0[0x70 - 0x20];
  51. ulong ctl;
  52. };
  53. struct Nandtab {
  54. int vid;
  55. int did;
  56. vlong size;
  57. char* name;
  58. };
  59. struct Cache {
  60. Flash *flif;
  61. ulong pageno;
  62. ulong pgsize; /* r->pagesize */
  63. char *page; /* of pgsize bytes */
  64. };
  65. enum {
  66. /* commands */
  67. Readstatus = 0x70,
  68. Readid = 0x90, /* needs 1 0-address write */
  69. Resetf = 0xff,
  70. /*
  71. * needs 5 address writes followed by Readstart,
  72. * Readstartcache or Restartcopy.
  73. */
  74. Read = 0x00,
  75. Readstart = 0x30,
  76. Readstartcache = 0x31,
  77. Readstartcopy = 0x35,
  78. /* after Readstartcache, to stop reading next pages */
  79. Readstopcache = 0x34,
  80. /* needs 5 address writes, the data, and -start or -cache */
  81. Program = 0x80,
  82. Programstart = 0x10,
  83. Programcache = 0x15,
  84. Copyback = 0x85, /* followed by Programstart */
  85. /* 3 address writes for block followed by Erasestart */
  86. Erase = 0x60,
  87. Erasestart = 0xd0,
  88. Randomread = 0x85,
  89. Randomwrite = 0x05,
  90. Randomwritestart= 0xe0,
  91. /* status bits */
  92. SFail = 1<<0,
  93. SCachefail = 1<<1,
  94. SIdle = 1<<5, /* doesn't seem to come on ever */
  95. SReady = 1<<6,
  96. SNotprotected = 1<<7,
  97. Srdymask = SReady, /* was SIdle|SReady */
  98. };
  99. Nandtab nandtab[] = {
  100. {Hynix, Hy27UF084G2M, 512*MB, "Hy27UF084G2M"},
  101. {Samsung, 0xdc, 512*MB, "Samsung 2Gb"},
  102. };
  103. static Cache cache;
  104. static void
  105. nandcmd(Flash *f, uchar b)
  106. {
  107. uchar *p = (uchar *)((ulong)f->addr|1);
  108. *p = b;
  109. coherence();
  110. }
  111. static void
  112. nandaddr(Flash *f, uchar b)
  113. {
  114. uchar *p = (uchar *)((ulong)f->addr|2);
  115. *p = b;
  116. coherence();
  117. }
  118. static uchar
  119. nandread(Flash *f)
  120. {
  121. return *(uchar *)f->addr;
  122. }
  123. static void
  124. nandreadn(Flash *f, uchar *buf, long n)
  125. {
  126. uchar *p = f->addr;
  127. while(n-- > 0)
  128. *buf++ = *p;
  129. }
  130. static void
  131. nandwrite(Flash *f, uchar b)
  132. {
  133. *(uchar *)f->addr = b;
  134. coherence();
  135. }
  136. static void
  137. nandwriten(Flash *f, uchar *buf, long n)
  138. {
  139. uchar *p = f->addr;
  140. while(n-- > 0)
  141. *p = *buf++;
  142. coherence();
  143. }
  144. static void
  145. nandclaim(Flash*)
  146. {
  147. Nandreg *nand = (Nandreg*)soc.nand;
  148. nand->ctl |= NandActCEBoot;
  149. coherence();
  150. }
  151. static void
  152. nandunclaim(Flash*)
  153. {
  154. Nandreg *nand = (Nandreg*)soc.nand;
  155. nand->ctl &= ~NandActCEBoot;
  156. coherence();
  157. }
  158. Nandtab *
  159. findflash(Flash *f, uintptr pa, uchar *id4p)
  160. {
  161. int i;
  162. ulong sts;
  163. uchar maker, device, id3, id4;
  164. Nandtab *chip;
  165. mmuidmap(pa, 16);
  166. f->addr = (void *)pa;
  167. /* make sure controller is idle */
  168. nandclaim(f);
  169. nandcmd(f, Resetf);
  170. nandunclaim(f);
  171. nandclaim(f);
  172. nandcmd(f, Readstatus);
  173. sts = nandread(f);
  174. nandunclaim(f);
  175. for (i = 10; i > 0 && !(sts & SReady); i--) {
  176. delay(50);
  177. nandclaim(f);
  178. nandcmd(f, Readstatus);
  179. sts = nandread(f);
  180. nandunclaim(f);
  181. }
  182. if(!(sts & SReady)) {
  183. if (Debug)
  184. print("flashkw: ctlr %#p not ready\n", pa);
  185. return nil;
  186. }
  187. nandclaim(f);
  188. nandcmd(f, Readid);
  189. nandaddr(f, 0);
  190. maker = nandread(f);
  191. device = nandread(f);
  192. id3 = nandread(f);
  193. USED(id3);
  194. id4 = nandread(f);
  195. nandunclaim(f);
  196. if (id4p)
  197. *id4p = id4;
  198. for(i = 0; i < nelem(nandtab); i++) {
  199. chip = &nandtab[i];
  200. if(chip->vid == maker && chip->did == device)
  201. return chip;
  202. }
  203. print("flashkw: unknown chip: vid %#ux did %#ux\n", maker, device);
  204. return nil;
  205. }
  206. int
  207. flashat(Flash *f, uintptr pa)
  208. {
  209. return findflash(f, pa, nil) != nil;
  210. }
  211. static int
  212. idchip(Flash *f)
  213. {
  214. uchar id4;
  215. Flashregion *r;
  216. Nandtab *chip;
  217. static int blocksizes[4] = { 64*1024, 128*1024, 256*1024, 0 };
  218. static int pagesizes[4] = { 1024, 2*1024, 0, 0 };
  219. static int spares[2] = { 8, 16 }; /* per 512 bytes */
  220. f->id = 0;
  221. f->devid = 0;
  222. f->width = 1;
  223. chip = findflash(f, (uintptr)f->addr, &id4);
  224. if (chip == nil)
  225. return -1;
  226. f->id = chip->vid;
  227. f->devid = chip->did;
  228. f->size = chip->size;
  229. f->width = 1;
  230. f->nr = 1;
  231. r = &f->regions[0];
  232. r->pagesize = pagesizes[id4 & MASK(2)];
  233. r->erasesize = blocksizes[(id4 >> 4) & MASK(2)];
  234. if (r->pagesize == 0 || r->erasesize == 0) {
  235. iprint("flashkw: bogus flash sizes\n");
  236. return -1;
  237. }
  238. r->n = f->size / r->erasesize;
  239. r->start = 0;
  240. r->end = f->size;
  241. assert(ispow2(r->pagesize));
  242. r->pageshift = log2(r->pagesize);
  243. assert(ispow2(r->erasesize));
  244. r->eraseshift = log2(r->erasesize);
  245. assert(r->eraseshift >= r->pageshift);
  246. if (cache.page == nil) {
  247. cache.pgsize = r->pagesize;
  248. cache.page = smalloc(r->pagesize);
  249. }
  250. r->spares = r->pagesize / 512 * spares[(id4 >> 2) & 1];
  251. print("#F0: kwnand: %s %,lud bytes pagesize %lud erasesize %,lud"
  252. " spares per page %lud\n", chip->name, f->size, r->pagesize,
  253. r->erasesize, r->spares);
  254. return 0;
  255. }
  256. static int
  257. ctlrwait(Flash *f)
  258. {
  259. int sts, cnt;
  260. nandclaim(f);
  261. for (;;) {
  262. nandcmd(f, Readstatus);
  263. for(cnt = 100; cnt > 0 && (nandread(f) & Srdymask) != Srdymask;
  264. cnt--)
  265. microdelay(50);
  266. nandcmd(f, Readstatus);
  267. sts = nandread(f);
  268. if((sts & Srdymask) == Srdymask)
  269. break;
  270. print("flashkw: flash ctlr busy, sts %#ux: resetting\n", sts);
  271. nandcmd(f, Resetf);
  272. }
  273. nandunclaim(f);
  274. return 0;
  275. }
  276. static int
  277. erasezone(Flash *f, Flashregion *r, ulong offset)
  278. {
  279. int i;
  280. ulong page, block;
  281. uchar s;
  282. if (Debug) {
  283. print("flashkw: erasezone: offset %#lux, region nblocks %d,"
  284. " start %#lux, end %#lux\n", offset, r->n, r->start,
  285. r->end);
  286. print(" erasesize %lud, pagesize %lud\n",
  287. r->erasesize, r->pagesize);
  288. }
  289. assert(r->erasesize != 0);
  290. if(offset & (r->erasesize - 1)) {
  291. print("flashkw: erase offset %lud not block aligned\n", offset);
  292. return -1;
  293. }
  294. page = offset >> r->pageshift;
  295. block = page >> (r->eraseshift - r->pageshift);
  296. if (Debug)
  297. print("flashkw: erase: block %#lux\n", block);
  298. /* make sure controller is idle */
  299. if(ctlrwait(f) < 0) {
  300. print("flashkw: erase: flash busy\n");
  301. return -1;
  302. }
  303. /* start erasing */
  304. nandclaim(f);
  305. nandcmd(f, Erase);
  306. nandaddr(f, page>>0);
  307. nandaddr(f, page>>8);
  308. nandaddr(f, page>>16);
  309. nandcmd(f, Erasestart);
  310. /* invalidate cache on any erasure (slight overkill) */
  311. cache.pageno = Nopage;
  312. /* have to wait until flash is done. typically ~2ms */
  313. delay(1);
  314. nandcmd(f, Readstatus);
  315. for(i = 0; i < 100; i++) {
  316. s = nandread(f);
  317. if(s & SReady) {
  318. nandunclaim(f);
  319. if(s & SFail) {
  320. print("flashkw: erase: failed, block %#lux\n",
  321. block);
  322. return -1;
  323. }
  324. return 0;
  325. }
  326. microdelay(50);
  327. }
  328. print("flashkw: erase timeout, block %#lux\n", block);
  329. nandunclaim(f);
  330. return -1;
  331. }
  332. static void
  333. flcachepage(Flash *f, ulong page, uchar *buf)
  334. {
  335. Flashregion *r = &f->regions[0];
  336. assert(cache.pgsize == r->pagesize);
  337. cache.flif = f;
  338. cache.pageno = page;
  339. /* permit i/o directly to or from the cache */
  340. if (buf != (uchar *)cache.page)
  341. memmove(cache.page, buf, cache.pgsize);
  342. }
  343. static int
  344. write1page(Flash *f, ulong offset, void *buf)
  345. {
  346. int i;
  347. ulong page, v;
  348. uchar s;
  349. uchar *eccp, *p;
  350. Flashregion *r = &f->regions[0];
  351. static uchar *oob;
  352. if (oob == nil)
  353. oob = smalloc(r->spares);
  354. page = offset >> r->pageshift;
  355. if (Debug)
  356. print("flashkw: write nand offset %#lux page %#lux\n",
  357. offset, page);
  358. if(offset & (r->pagesize - 1)) {
  359. print("flashkw: write offset %lud not page aligned\n", offset);
  360. return -1;
  361. }
  362. p = buf;
  363. memset(oob, 0xff, r->spares);
  364. assert(r->spares >= 24);
  365. eccp = oob + r->spares - 24;
  366. for(i = 0; i < r->pagesize / 256; i++) {
  367. v = nandecc(p);
  368. *eccp++ = v>>8;
  369. *eccp++ = v>>0;
  370. *eccp++ = v>>16;
  371. p += 256;
  372. }
  373. if(ctlrwait(f) < 0) {
  374. print("flashkw: write: nand not ready & idle\n");
  375. return -1;
  376. }
  377. /* write, only whole pages for now, no sub-pages */
  378. nandclaim(f);
  379. nandcmd(f, Program);
  380. nandaddr(f, 0);
  381. nandaddr(f, 0);
  382. nandaddr(f, page>>0);
  383. nandaddr(f, page>>8);
  384. nandaddr(f, page>>16);
  385. nandwriten(f, buf, r->pagesize);
  386. nandwriten(f, oob, r->spares);
  387. nandcmd(f, Programstart);
  388. microdelay(100);
  389. nandcmd(f, Readstatus);
  390. for(i = 0; i < 100; i++) {
  391. s = nandread(f);
  392. if(s & SReady) {
  393. nandunclaim(f);
  394. if(s & SFail) {
  395. print("flashkw: write failed, page %#lux\n",
  396. page);
  397. return -1;
  398. }
  399. return 0;
  400. }
  401. microdelay(10);
  402. }
  403. nandunclaim(f);
  404. flcachepage(f, page, buf);
  405. print("flashkw: write timeout for page %#lux\n", page);
  406. return -1;
  407. }
  408. static int
  409. read1page(Flash *f, ulong offset, void *buf)
  410. {
  411. int i;
  412. ulong addr, page, w;
  413. uchar *eccp, *p;
  414. Flashregion *r = &f->regions[0];
  415. static uchar *oob;
  416. if (oob == nil)
  417. oob = smalloc(r->spares);
  418. assert(r->pagesize != 0);
  419. addr = offset & (r->pagesize - 1);
  420. page = offset >> r->pageshift;
  421. if(addr != 0) {
  422. print("flashkw: read1page: read addr %#lux:"
  423. " must read aligned page\n", addr);
  424. return -1;
  425. }
  426. /* satisfy request from cache if possible */
  427. if (f == cache.flif && page == cache.pageno &&
  428. r->pagesize == cache.pgsize) {
  429. memmove(buf, cache.page, r->pagesize);
  430. return 0;
  431. }
  432. if (Debug)
  433. print("flashkw: read offset %#lux addr %#lux page %#lux\n",
  434. offset, addr, page);
  435. nandclaim(f);
  436. nandcmd(f, Read);
  437. nandaddr(f, addr>>0);
  438. nandaddr(f, addr>>8);
  439. nandaddr(f, page>>0);
  440. nandaddr(f, page>>8);
  441. nandaddr(f, page>>16);
  442. nandcmd(f, Readstart);
  443. microdelay(50);
  444. nandreadn(f, buf, r->pagesize);
  445. nandreadn(f, oob, r->spares);
  446. nandunclaim(f);
  447. /* verify/correct data. last 8*3 bytes is ecc, per 256 bytes. */
  448. p = buf;
  449. assert(r->spares >= 24);
  450. eccp = oob + r->spares - 24;
  451. for(i = 0; i < r->pagesize / 256; i++) {
  452. w = eccp[0] << 8 | eccp[1] << 0 | eccp[2] << 16;
  453. eccp += 3;
  454. switch(nandecccorrect(p, nandecc(p), &w, 1)) {
  455. case NandEccErrorBad:
  456. print("(page %d)\n", i);
  457. return -1;
  458. case NandEccErrorOneBit:
  459. case NandEccErrorOneBitInEcc:
  460. print("(page %d)\n", i);
  461. /* fall through */
  462. case NandEccErrorGood:
  463. break;
  464. }
  465. p += 256;
  466. }
  467. flcachepage(f, page, buf);
  468. return 0;
  469. }
  470. /*
  471. * read a page at offset into cache, copy fragment from buf into it
  472. * at pagoff, and rewrite that page.
  473. */
  474. static int
  475. rewrite(Flash *f, ulong offset, ulong pagoff, void *buf, ulong size)
  476. {
  477. if (read1page(f, offset, cache.page) < 0)
  478. return -1;
  479. memmove(&cache.page[pagoff], buf, size);
  480. return write1page(f, offset, cache.page);
  481. }
  482. /* there are no alignment constraints on offset, buf, nor n */
  483. static int
  484. write(Flash *f, ulong offset, void *buf, long n)
  485. {
  486. uint un, frag, pagoff;
  487. ulong pgsize;
  488. uchar *p;
  489. Flashregion *r = &f->regions[0];
  490. if(n <= 0)
  491. panic("flashkw: write: non-positive count %ld", n);
  492. un = n;
  493. assert(r->pagesize != 0);
  494. pgsize = r->pagesize;
  495. /* if a partial first page exists, update the first page with it. */
  496. p = buf;
  497. pagoff = offset % pgsize;
  498. if (pagoff != 0) {
  499. frag = pgsize - pagoff;
  500. if (frag > un) /* might not extend to end of page */
  501. frag = un;
  502. if (rewrite(f, offset - pagoff, pagoff, p, frag) < 0)
  503. return -1;
  504. offset += frag;
  505. p += frag;
  506. un -= frag;
  507. }
  508. /* copy whole pages */
  509. while (un >= pgsize) {
  510. if (write1page(f, offset, p) < 0)
  511. return -1;
  512. offset += pgsize;
  513. p += pgsize;
  514. un -= pgsize;
  515. }
  516. /* if a partial last page exists, update the last page with it. */
  517. if (un > 0)
  518. return rewrite(f, offset, 0, p, un);
  519. return 0;
  520. }
  521. /* there are no alignment constraints on offset, buf, nor n */
  522. static int
  523. read(Flash *f, ulong offset, void *buf, long n)
  524. {
  525. uint un, frag, pagoff;
  526. ulong pgsize;
  527. uchar *p;
  528. Flashregion *r = &f->regions[0];
  529. if(n <= 0)
  530. panic("flashkw: read: non-positive count %ld", n);
  531. un = n;
  532. assert(r->pagesize != 0);
  533. pgsize = r->pagesize;
  534. /* if partial 1st page, read it into cache & copy fragment to buf */
  535. p = buf;
  536. pagoff = offset % pgsize;
  537. if (pagoff != 0) {
  538. frag = pgsize - pagoff;
  539. if (frag > un) /* might not extend to end of page */
  540. frag = un;
  541. if (read1page(f, offset - pagoff, cache.page) < 0)
  542. return -1;
  543. offset += frag;
  544. memmove(p, &cache.page[pagoff], frag);
  545. p += frag;
  546. un -= frag;
  547. }
  548. /* copy whole pages */
  549. while (un >= pgsize) {
  550. if (read1page(f, offset, p) < 0)
  551. return -1;
  552. offset += pgsize;
  553. p += pgsize;
  554. un -= pgsize;
  555. }
  556. /* if partial last page, read into cache & copy initial fragment to buf */
  557. if (un > 0) {
  558. if (read1page(f, offset, cache.page) < 0)
  559. return -1;
  560. memmove(p, cache.page, un);
  561. }
  562. return 0;
  563. }
  564. static int
  565. reset(Flash *f)
  566. {
  567. if(f->data != nil)
  568. return 1;
  569. f->write = write;
  570. f->read = read;
  571. f->eraseall = nil;
  572. f->erasezone = erasezone;
  573. f->suspend = nil;
  574. f->resume = nil;
  575. f->sort = "nand";
  576. cache.pageno = Nopage;
  577. return idchip(f);
  578. }
  579. void
  580. flashkwlink(void)
  581. {
  582. addflashcard("nand", reset);
  583. }