5 * Sangmoon Kim, Etin Systems, dogoil@etinsys.com.
7 * See file CREDITS for list of people who contributed to this
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 #include <asm/processor.h>
28 #include <asm/pci_io.h>
32 int (*do_flash_erase)(flash_info_t*, uint32_t, uint32_t);
33 int (*write_dword)(flash_info_t*, ulong, uint64_t);
35 typedef uint64_t cfi_word;
37 #define cfi_read(flash, addr) *((volatile cfi_word*)(flash->start[0] + addr))
39 #define cfi_write(flash, val, addr) \
40 move64((cfi_word*)&val, \
41 (cfi_word*)(flash->start[0] + addr))
43 #define CMD(x) ((((cfi_word)x)<<48)|(((cfi_word)x)<<32)|(((cfi_word)x)<<16)|(((cfi_word)x)))
45 static void write32(unsigned long addr, uint32_t value)
47 *(volatile uint32_t*)(addr) = value;
51 static uint32_t read32(unsigned long addr)
54 value = *(volatile uint32_t*)addr;
59 static cfi_word cfi_cmd(flash_info_t *flash, uint8_t cmd, uint32_t addr)
61 uint32_t base = flash->start[0];
62 uint32_t val=(cmd << 16) | cmd;
64 write32(base + addr, val);
68 static uint16_t cfi_read_query(flash_info_t *flash, uint32_t addr)
70 uint32_t base = flash->start[0];
72 return (uint16_t)read32(base + addr);
75 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
77 static void move64(uint64_t *src, uint64_t *dest)
79 asm volatile("lfd 0, 0(3)\n\t" /* fpr0 = *scr */
80 "stfd 0, 0(4)" /* *dest = fpr0 */
81 : : : "fr0" ); /* Clobbers fr0 */
85 static int cfi_write_dword(flash_info_t *flash, ulong dest, cfi_word data)
90 status = cfi_read(flash, dest);
93 cfi_cmd(flash, 0x40, 0);
94 cfi_write(flash, data, dest);
97 start = get_timer (0);
99 status = cfi_read(flash, dest);
101 if(status == CMD(0x80))
103 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
104 cfi_cmd(flash, 0xff, 0);
109 cfi_cmd(flash, 0xff, 0);
114 static int jedec_write_dword (flash_info_t *flash, ulong dest, cfi_word data)
119 status = cfi_read(flash, dest);
120 if(status != CMD(0xffff)) return 2;
122 cfi_cmd(flash, 0xaa, 0x555);
123 cfi_cmd(flash, 0x55, 0x2aa);
124 cfi_cmd(flash, 0xa0, 0x555);
126 cfi_write(flash, data, dest);
129 start = get_timer (0);
131 while(status != data) {
132 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
134 status = cfi_read(flash, dest);
140 static __inline__ unsigned long get_msr(void)
143 __asm__ __volatile__ ("mfmsr %0" : "=r" (msr) :);
147 static __inline__ void set_msr(unsigned long msr)
149 __asm__ __volatile__ ("mtmsr %0" : : "r" (msr));
152 int write_buff (flash_info_t *flash, uchar *src, ulong addr, ulong cnt)
157 uint8_t *t = (uint8_t*)&data;
158 unsigned long base = flash->start[0];
161 if (flash->flash_id == FLASH_UNKNOWN)
172 wp = (addr & ~7); /* get lower word aligned address */
175 data = cfi_read(flash, wp);
177 l = ( cnt < (8-s) ) ? cnt : (8-s);
178 for(i = 0; i < l; i++)
180 if ((rc = write_dword(flash, wp, data)) != 0)
187 for (i = 0; i < 8; i++)
189 if ((rc = write_dword(flash, wp, data)) != 0)
200 data = cfi_read(flash, wp);
201 for(i = 0; i < cnt; i++)
203 rc = write_dword(flash, wp, data);
209 static int cfi_erase_oneblock(flash_info_t *flash, uint32_t sect)
213 ulong start, last, now;
216 flag = disable_interrupts();
218 sa = (flash->start[sect] - flash->start[0]);
219 write32(flash->start[sect], 0x00200020);
220 write32(flash->start[sect], 0x00d000d0);
226 start = get_timer (0);
230 status = cfi_read(flash, sa);
232 if (status == CMD(0x80))
234 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
235 cfi_cmd(flash, 0xff, 0);
236 printf ("Timeout\n");
240 if ((now - last) > 1000) {
246 cfi_cmd(flash, 0xff, 0);
250 static int cfi_erase(flash_info_t *flash, uint32_t s_first, uint32_t s_last)
255 for (sect = s_first; sect <= s_last; sect++) {
256 if (flash->protect[sect] == 0) {
257 rc = cfi_erase_oneblock(flash, sect);
258 if (rc != ERR_OK) break;
265 static int jedec_erase(flash_info_t *flash, uint32_t s_first, uint32_t s_last)
271 ulong start, last, now;
273 flag = disable_interrupts();
275 cfi_cmd(flash, 0xaa, 0x555);
276 cfi_cmd(flash, 0x55, 0x2aa);
277 cfi_cmd(flash, 0x80, 0x555);
278 cfi_cmd(flash, 0xaa, 0x555);
279 cfi_cmd(flash, 0x55, 0x2aa);
280 for ( sect = s_first; sect <= s_last; sect++) {
281 if (flash->protect[sect] == 0) {
282 sa = flash->start[sect] - flash->start[0];
283 write32(flash->start[sect], 0x00300030);
293 start = get_timer (0);
296 status = cfi_read(flash, sa);
297 if (status == CMD(0xffff))
300 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
301 printf ("Timeout\n");
305 if ((now - last) > 1000) {
312 cfi_cmd(flash, 0xf0, 0);
319 int flash_erase (flash_info_t *flash, int s_first, int s_last)
324 if ((s_first < 0) || (s_first > s_last)) {
325 if (flash->flash_id == FLASH_UNKNOWN)
326 printf ("- missing\n");
328 printf ("- no sectors to erase\n");
329 return ERR_NOT_ERASED;
331 if (flash->flash_id == FLASH_UNKNOWN) {
332 printf ("Can't erase unknown flash type - aborted\n");
333 return ERR_NOT_ERASED;
337 for (sect = s_first; sect <= s_last; sect++)
338 if (flash->protect[sect]) prot++;
341 printf ("- Warning: %d protected sectors will not be erased!\n",
346 return do_flash_erase(flash, s_first, s_last);
349 struct jedec_flash_info {
350 const uint16_t mfr_id;
351 const uint16_t dev_id;
354 const int InterfaceDesc;
355 const int NumEraseRegions;
356 const ulong regions[4];
359 #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
365 static const struct jedec_flash_info jedec_table[] = {
367 mfr_id: (uint16_t)AMD_MANUFACT,
368 dev_id: (uint16_t)AMD_ID_LV800T,
369 name: "AMD AM29LV800T",
372 regions: {ERASEINFO(0x10000,15),
373 ERASEINFO(0x08000,1),
374 ERASEINFO(0x02000,2),
378 mfr_id: (uint16_t)AMD_MANUFACT,
379 dev_id: (uint16_t)AMD_ID_LV800B,
380 name: "AMD AM29LV800B",
383 regions: {ERASEINFO(0x10000,15),
384 ERASEINFO(0x08000,1),
385 ERASEINFO(0x02000,2),
389 mfr_id: (uint16_t)AMD_MANUFACT,
390 dev_id: (uint16_t)AMD_ID_LV160T,
391 name: "AMD AM29LV160T",
394 regions: {ERASEINFO(0x10000,31),
395 ERASEINFO(0x08000,1),
396 ERASEINFO(0x02000,2),
400 mfr_id: (uint16_t)AMD_MANUFACT,
401 dev_id: (uint16_t)AMD_ID_LV160B,
402 name: "AMD AM29LV160B",
405 regions: {ERASEINFO(0x04000,1),
406 ERASEINFO(0x02000,2),
407 ERASEINFO(0x08000,1),
408 ERASEINFO(0x10000,31)
411 mfr_id: (uint16_t)AMD_MANUFACT,
412 dev_id: (uint16_t)AMD_ID_LV320T,
413 name: "AMD AM29LV320T",
416 regions: {ERASEINFO(0x10000,63),
421 mfr_id: (uint16_t)AMD_MANUFACT,
422 dev_id: (uint16_t)AMD_ID_LV320B,
423 name: "AMD AM29LV320B",
426 regions: {ERASEINFO(0x02000,8),
427 ERASEINFO(0x10000,63)
432 static ulong cfi_init(uint32_t base, flash_info_t *flash)
443 flash->start[0] = base;
444 cfi_cmd(flash, 0xF0, 0);
445 cfi_cmd(flash, 0x98, 0);
446 if ( !( cfi_read_query(flash, 0x10) == 'Q' &&
447 cfi_read_query(flash, 0x11) == 'R' &&
448 cfi_read_query(flash, 0x12) == 'Y' )) {
449 cfi_cmd(flash, 0xff, 0);
453 flash->size = 1 << cfi_read_query(flash, 0x27);
455 block_count = cfi_read_query(flash, 0x2c);
456 primary = cfi_read_query(flash, 0x15);
457 if ( cfi_read_query(flash, primary + 4) == 0x30)
458 reverse = (cfi_read_query(flash, 0x1) & 0x01);
460 reverse = (cfi_read_query(flash, primary+15) == 3);
462 flash->sector_count = 0;
464 for ( block = reverse ? block_count - 1 : 0;
465 reverse ? block >= 0 : block < block_count;
466 reverse ? block-- : block ++) {
468 (cfi_read_query(flash, 0x2d + block*4+2) |
469 (cfi_read_query(flash, 0x2d + block*4+3) << 8)) << 8;
471 (cfi_read_query(flash, 0x2d + block*4+0) |
472 (cfi_read_query(flash, 0x2d + block*4+1) << 8)) + 1;
473 for(sector = 0; sector < sector_count; sector++) {
474 flash->start[flash->sector_count++] = base + offset;
475 offset += sector_size * 4;
478 mfr_id = cfi_read_query(flash, 0x00);
479 dev_id = cfi_read_query(flash, 0x01);
481 cfi_cmd(flash, 0xff, 0);
483 flash->flash_id = (mfr_id << 16) | dev_id;
485 for (sector = 0; sector < flash->sector_count; sector++) {
486 write32(flash->start[sector], 0x00600060);
487 write32(flash->start[sector], 0x00d000d0);
489 cfi_cmd(flash, 0xff, 0);
491 for (sector = 0; sector < flash->sector_count; sector++)
492 flash->protect[sector] = 0;
494 do_flash_erase = cfi_erase;
495 write_dword = cfi_write_dword;
500 static ulong jedec_init(unsigned long base, flash_info_t *flash)
503 int block, block_count;
506 flash->start[0] = base;
507 cfi_cmd(flash, 0xF0, 0x000);
508 cfi_cmd(flash, 0xAA, 0x555);
509 cfi_cmd(flash, 0x55, 0x2AA);
510 cfi_cmd(flash, 0x90, 0x555);
511 mfr_id = cfi_read_query(flash, 0x000);
512 dev_id = cfi_read_query(flash, 0x0001);
513 cfi_cmd(flash, 0xf0, 0x000);
515 for(i=0; i<sizeof(jedec_table)/sizeof(struct jedec_flash_info); i++) {
516 if((jedec_table[i].mfr_id == mfr_id) &&
517 (jedec_table[i].dev_id == dev_id)) {
519 flash->flash_id = (mfr_id << 16) | dev_id;
520 flash->size = 1 << jedec_table[0].DevSize;
522 block_count = jedec_table[i].NumEraseRegions;
524 flash->sector_count = 0;
525 for (block = 0; block < block_count; block++) {
526 int sector_size = jedec_table[i].regions[block];
527 int sector_count = (sector_size & 0xff) + 1;
529 for (sector=0; sector<sector_count; sector++) {
530 flash->start[flash->sector_count++] =
532 offset += sector_size * 4;
539 for (sector = 0; sector < flash->sector_count; sector++)
540 flash->protect[sector] = 0;
542 do_flash_erase = jedec_erase;
543 write_dword = jedec_write_dword;
548 inline void mtibat1u(unsigned int x)
550 __asm__ __volatile__ ("mtspr 530, %0" :: "r" (x));
553 inline void mtibat1l(unsigned int x)
555 __asm__ __volatile__ ("mtspr 531, %0" :: "r" (x));
558 inline void mtdbat1u(unsigned int x)
560 __asm__ __volatile__ ("mtspr 538, %0" :: "r" (x));
563 inline void mtdbat1l(unsigned int x)
565 __asm__ __volatile__ ("mtspr 539, %0" :: "r" (x));
568 unsigned long flash_init (void)
570 unsigned long size = 0;
575 CONFIG_WRITE_WORD(ERCR3, 0x0C00000C);
576 CONFIG_WRITE_WORD(ERCR4, 0x0800000C);
578 set_msr(msr & ~(MSR_IR | MSR_DR));
579 mtibat1l(0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT);
580 mtibat1u(0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP);
581 mtdbat1l(0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT);
582 mtdbat1u(0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP);
585 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
586 flash_info[i].flash_id = FLASH_UNKNOWN;
587 size = cfi_init(FLASH_BASE0_PRELIM, &flash_info[0]);
589 size = jedec_init(FLASH_BASE0_PRELIM, &flash_info[0]);
591 if (flash_info[0].flash_id == FLASH_UNKNOWN)
592 printf ("# Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n",
598 void flash_print_info (flash_info_t *flash)
604 volatile unsigned long *p;
606 if (flash->flash_id == FLASH_UNKNOWN) {
607 printf ("missing or unknown FLASH type\n");
611 if (flash->flash_id == FLASH_UNKNOWN) {
612 printf ("missing or unknown FLASH type\n");
616 switch (((flash->flash_id) >> 16) & 0xff) {
634 printf ("Unknown Vendor ");
638 switch ((flash->flash_id) & 0xffff) {
639 case (uint16_t)AMD_ID_LV800T:
640 printf ("AM29LV800T\n");
642 case (uint16_t)AMD_ID_LV800B:
643 printf ("AM29LV800B\n");
645 case (uint16_t)AMD_ID_LV160T:
646 printf ("AM29LV160T\n");
648 case (uint16_t)AMD_ID_LV160B:
649 printf ("AM29LV160B\n");
651 case (uint16_t)AMD_ID_LV320T:
652 printf ("AM29LV320T\n");
654 case (uint16_t)AMD_ID_LV320B:
655 printf ("AM29LV320B\n");
657 case (uint16_t)INTEL_ID_28F800C3T:
658 printf ("28F800C3T\n");
660 case (uint16_t)INTEL_ID_28F800C3B:
661 printf ("28F800C3B\n");
663 case (uint16_t)INTEL_ID_28F160C3T:
664 printf ("28F160C3T\n");
666 case (uint16_t)INTEL_ID_28F160C3B:
667 printf ("28F160C3B\n");
669 case (uint16_t)INTEL_ID_28F320C3T:
670 printf ("28F320C3T\n");
672 case (uint16_t)INTEL_ID_28F320C3B:
673 printf ("28F320C3B\n");
675 case (uint16_t)INTEL_ID_28F640C3T:
676 printf ("28F640C3T\n");
678 case (uint16_t)INTEL_ID_28F640C3B:
679 printf ("28F640C3B\n");
682 printf ("Unknown Chip Type\n");
686 if (flash->size >= (1 << 20)) {
687 printf (" Size: %ld MB in %d Sectors\n",
688 flash->size >> 20, flash->sector_count);
690 printf (" Size: %ld kB in %d Sectors\n",
691 flash->size >> 10, flash->sector_count);
694 printf (" Sector Start Addresses:");
695 for (i = 0; i < flash->sector_count; ++i) {
696 /* Check if whole sector is erased*/
697 if (i != (flash->sector_count-1))
698 size = flash->start[i+1] - flash->start[i];
700 size = flash->start[0] + flash->size - flash->start[i];
703 p = (volatile unsigned long *)flash->start[i];
704 size = size >> 2; /* divide by 4 for longword access */
705 for (k=0; k<size; k++) {
706 if (*p++ != 0xffffffff) {
715 printf (" %08lX%s%s",
718 flash->protect[i] ? "RO " : " ");