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