3 * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
5 * SPDX-License-Identifier: GPL-2.0+
9 * flash.c - flash support for the 512k, 8bit boot flash on the GEVB
10 * most of this file was based on the existing U-Boot
16 #include <galileo/gt64260R.h>
17 #include <galileo/memory.h>
18 #include "intel_flash.h"
20 #define FLASH_ROM 0xFFFD /* unknown flash type */
21 #define FLASH_RAM 0xFFFE /* unknown flash type */
22 #define FLASH_MAN_UNKNOWN 0xFFFF0000
25 /* #define FLASH_ID_OVERRIDE */ /* Hack to set type to 040B if ROM emulator is installed.
26 * Can be used to program a ROM in circuit if a programmer
27 * is not available by swapping the rom out. */
29 /* Intel flash commands */
30 int flash_erase_intel(flash_info_t *info, int s_first, int s_last);
31 int write_word_intel(bank_addr_t addr, bank_word_t value);
33 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
35 /*-----------------------------------------------------------------------
38 static ulong flash_get_size (int portwidth, vu_long *addr, flash_info_t *info);
39 static int write_word (flash_info_t *info, ulong dest, ulong data);
40 static void flash_get_offsets (ulong base, flash_info_t *info);
42 /*-----------------------------------------------------------------------
49 unsigned long size_b0 = 0, size_b1 = 0;
50 unsigned long base, flash_size;
52 /* Init: no FLASHes known */
53 for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
54 flash_info[i].flash_id = FLASH_UNKNOWN;
58 base = CONFIG_SYS_FLASH_BASE;
59 #ifndef CONFIG_SYS_BOOT_FLASH_WIDTH
60 #define CONFIG_SYS_BOOT_FLASH_WIDTH 1
62 size_b0 = flash_get_size(CONFIG_SYS_BOOT_FLASH_WIDTH, (vu_long *)base,
67 print_size (size_b0, "");
68 printf("@%08lX] ", base);
71 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
72 printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n",
73 base, size_b0, size_b0<<20);
76 base = memoryGetDeviceBaseAddress(CONFIG_SYS_EXTRA_FLASH_DEVICE);
77 for(i=1;i<CONFIG_SYS_MAX_FLASH_BANKS;i++) {
78 unsigned long size = flash_get_size(CONFIG_SYS_EXTRA_FLASH_WIDTH, (vu_long *)base, &flash_info[i]);
82 print_size (size, "");
83 printf("@%08lX] ", base);
86 if (flash_info[i].flash_id == FLASH_UNKNOWN) {
88 printf ("## Unknown FLASH at %08lx: Size = 0x%08lx = %ld MB\n",
89 base, size_b1, size_b1<<20);
97 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
98 /* monitor protection ON by default */
99 flash_protect(FLAG_PROTECT_SET,
100 CONFIG_SYS_MONITOR_BASE,
101 CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
102 flash_get_info(CONFIG_SYS_MONITOR_BASE));
105 #ifdef CONFIG_ENV_IS_IN_FLASH
106 /* ENV protection ON by default */
107 flash_protect(FLAG_PROTECT_SET,
109 CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
110 flash_get_info(CONFIG_ENV_ADDR));
113 flash_size = size_b0 + size_b1;
117 /*-----------------------------------------------------------------------
120 flash_get_offsets (ulong base, flash_info_t *info)
125 if(!info->sector_count) return;
127 /* set up sector start address table */
128 switch(info->flash_id & FLASH_TYPEMASK) {
130 case FLASH_28F128J3A:
131 case FLASH_28F640J3A:
133 /* this chip has uniformly spaced sectors */
134 sector_size=info->size/info->sector_count;
135 for (i = 0; i < info->sector_count; i++)
136 info->start[i] = base + (i * sector_size);
139 if (info->flash_id & FLASH_BTYPE) {
140 /* set sector offsets for bottom boot block type */
141 info->start[0] = base + 0x00000000;
142 info->start[1] = base + 0x00008000;
143 info->start[2] = base + 0x0000C000;
144 info->start[3] = base + 0x00010000;
145 for (i = 4; i < info->sector_count; i++) {
146 info->start[i] = base + (i * 0x00020000) - 0x00060000;
149 /* set sector offsets for top boot block type */
150 i = info->sector_count - 1;
151 info->start[i--] = base + info->size - 0x00008000;
152 info->start[i--] = base + info->size - 0x0000C000;
153 info->start[i--] = base + info->size - 0x00010000;
154 for (; i >= 0; i--) {
155 info->start[i] = base + i * 0x00020000;
161 /*-----------------------------------------------------------------------
164 flash_info_t *flash_get_info(ulong base)
169 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
170 info = & flash_info[i];
171 if (info->start[0] <= base && base <= info->start[0] + info->size - 1)
175 return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
178 /*-----------------------------------------------------------------------
181 flash_print_info (flash_info_t *info)
185 if (info->flash_id == FLASH_UNKNOWN) {
186 printf ("missing or unknown FLASH type\n");
190 switch (info->flash_id & FLASH_VENDMASK) {
191 case FLASH_MAN_AMD: printf ("AMD "); break;
192 case FLASH_MAN_FUJ: printf ("FUJITSU "); break;
193 case FLASH_MAN_INTEL: printf ("INTEL "); break;
194 default: printf ("Unknown Vendor "); break;
197 switch (info->flash_id & FLASH_TYPEMASK) {
199 printf ("AM29LV040B (4 Mbit, bottom boot sect)\n");
202 printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
205 printf ("AM29LV400T (4 Mbit, top boot sector)\n");
208 printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
211 printf ("AM29LV800T (8 Mbit, top boot sector)\n");
214 printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
217 printf ("AM29LV160T (16 Mbit, top boot sector)\n");
220 printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
223 printf ("AM29LV320T (32 Mbit, top boot sector)\n");
225 case FLASH_28F640J3A:
226 printf ("28F640J3A (64 Mbit)\n");
228 case FLASH_28F128J3A:
229 printf ("28F128J3A (128 Mbit)\n");
238 printf ("Unknown Chip Type\n");
243 print_size (info->size, "");
244 printf (" in %d Sectors\n", info->sector_count);
246 printf (" Sector Start Addresses:");
247 for (i=0; i<info->sector_count; ++i) {
252 info->protect[i] ? " (RO)" : " "
259 /*-----------------------------------------------------------------------
263 /*-----------------------------------------------------------------------
267 * The following code cannot be run from FLASH!
270 static inline void flash_cmd(int width, volatile unsigned char *addr, int offset, unsigned char cmd)
272 /* supports 1x8, 1x16, and 2x16 */
273 /* 2x8 and 4x8 are not supported */
275 /* assuming chips are in 16 bit mode */
277 unsigned long cmd32=(cmd<<16)|cmd;
278 *(volatile unsigned long *)(addr+offset*2)=cmd32;
279 } else if (width == 2) {
281 *(volatile unsigned short *)((unsigned short*)addr+offset)=cmd;
284 *(volatile unsigned char *)(addr+offset)=cmd;
289 flash_get_size (int portwidth, vu_long *addr, flash_info_t *info)
292 volatile unsigned char *caddr = (unsigned char *)addr;
293 volatile unsigned short *saddr = (unsigned short *)addr;
294 volatile unsigned long *laddr = (unsigned long *)addr;
296 ulong id, manu, base = (ulong)addr;
298 info->portwidth=portwidth;
302 flash_cmd(portwidth,caddr,0,0xf0);
303 flash_cmd(portwidth,caddr,0,0xf0);
312 flash_cmd(portwidth,caddr,0,0xf0);
313 flash_cmd(portwidth,caddr,0,0xf0);
318 /* this area is ROM */
320 #ifndef FLASH_ID_OVERRIDE
321 info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN;
322 info->sector_count = 8;
323 info->size = 0x80000;
325 info->flash_id = FLASH_MAN_AMD + FLASH_AM040;
326 info->sector_count = 8;
327 info->size = 0x80000;
330 flash_get_offsets(base, info);
339 /* this area is RAM */
341 info->flash_id = FLASH_RAM + FLASH_MAN_UNKNOWN;
342 info->sector_count = 8;
343 info->size = 0x80000;
344 flash_get_offsets(base, info);
347 flash_cmd(portwidth,caddr,0,0xf0);
352 /* Write auto select command: read Manufacturer ID */
353 flash_cmd(portwidth,caddr,0x555,0xAA);
354 flash_cmd(portwidth,caddr,0x2AA,0x55);
355 flash_cmd(portwidth,caddr,0x555,0x90);
359 if ((caddr[0] == old[0]) &&
360 (caddr[1] == old[1])) {
362 /* this area is ROM */
363 #ifndef FLASH_ID_OVERRIDE
364 info->flash_id = FLASH_ROM + FLASH_MAN_UNKNOWN;
365 info->sector_count = 8;
366 info->size = 0x80000;
368 info->flash_id = FLASH_MAN_AMD + FLASH_AM040;
369 info->sector_count = 8;
370 info->size = 0x80000;
373 flash_get_offsets(base, info);
377 printf("%px%d: %02x:%02x -> %02x:%02x\n",
378 caddr, portwidth, old[0], old[1],
405 printf("\n%08lx:%08lx:%08lx\n", base, manu, id);
406 printf("%08lx %08lx %08lx %08lx\n",
407 laddr[0],laddr[1],laddr[2],laddr[3]);
412 info->flash_id = FLASH_MAN_AMD;
415 info->flash_id = FLASH_MAN_FUJ;
418 info->flash_id = FLASH_MAN_INTEL;
421 printf("Unknown Mfr [%08lx]:%08lx\n", manu, id);
422 info->flash_id = FLASH_UNKNOWN;
423 info->sector_count = 0;
425 return (0); /* no or unknown flash */
430 info->flash_id += FLASH_AM400T;
431 info->sector_count = 11;
432 info->size = 0x00100000;
437 info->flash_id += FLASH_AM400B;
438 info->sector_count = 11;
439 info->size = 0x00100000;
444 info->flash_id += FLASH_AM800T;
445 info->sector_count = 19;
446 info->size = 0x00200000;
451 info->flash_id += FLASH_AM800B;
452 info->sector_count = 19;
453 info->size = 0x00200000;
458 info->flash_id += FLASH_AM160T;
459 info->sector_count = 35;
460 info->size = 0x00400000;
465 info->flash_id += FLASH_AM160B;
466 info->sector_count = 35;
467 info->size = 0x00400000;
470 #if 0 /* enable when device IDs are available */
472 info->flash_id += FLASH_AM320T;
473 info->sector_count = 67;
474 info->size = 0x00800000;
478 info->flash_id += FLASH_AM320B;
479 info->sector_count = 67;
480 info->size = 0x00800000;
484 info->flash_id += FLASH_AM040;
485 info->sector_count = 8;
486 info->size = 0x80000;
490 case INTEL_ID_28F640J3A:
491 info->flash_id += FLASH_28F640J3A;
492 info->sector_count = 64;
493 info->size = 128*1024 * 64; /* 128kbytes x 64 blocks */
495 if(portwidth==4) info->size*=2; /* 2x16 */
498 case INTEL_ID_28F128J3A:
499 info->flash_id += FLASH_28F128J3A;
500 info->sector_count = 128;
501 info->size = 128*1024 * 128; /* 128kbytes x 128 blocks */
503 if(portwidth==4) info->size*=2; /* 2x16 */
507 printf("Unknown id %lx:[%lx]\n", manu, id);
508 info->flash_id = FLASH_UNKNOWN;
510 return (0); /* => no or unknown flash */
514 flash_get_offsets(base, info);
517 /* set up sector start address table */
518 if (info->flash_id & FLASH_AM040) {
519 /* this chip has uniformly spaced sectors */
520 for (i = 0; i < info->sector_count; i++)
521 info->start[i] = base + (i * 0x00010000);
523 } else if (info->flash_id & FLASH_BTYPE) {
524 /* set sector offsets for bottom boot block type */
525 info->start[0] = base + 0x00000000;
526 info->start[1] = base + 0x00008000;
527 info->start[2] = base + 0x0000C000;
528 info->start[3] = base + 0x00010000;
529 for (i = 4; i < info->sector_count; i++) {
530 info->start[i] = base + (i * 0x00020000) - 0x00060000;
533 /* set sector offsets for top boot block type */
534 i = info->sector_count - 1;
535 info->start[i--] = base + info->size - 0x00008000;
536 info->start[i--] = base + info->size - 0x0000C000;
537 info->start[i--] = base + info->size - 0x00010000;
538 for (; i >= 0; i--) {
539 info->start[i] = base + i * 0x00020000;
544 /* check for protected sectors */
545 for (i = 0; i < info->sector_count; i++) {
546 /* read sector protection at sector address, (A7 .. A0)=0x02 */
547 /* D0 = 1 if protected */
548 caddr = (volatile unsigned char *)(info->start[i]);
549 saddr = (volatile unsigned short *)(info->start[i]);
550 laddr = (volatile unsigned long *)(info->start[i]);
552 info->protect[i] = caddr[2] & 1;
553 else if(portwidth==2)
554 info->protect[i] = saddr[2] & 1;
556 info->protect[i] = laddr[2] & 1;
560 * Prevent writes to uninitialized FLASH.
562 if (info->flash_id != FLASH_UNKNOWN) {
563 caddr = (volatile unsigned char *)info->start[0];
565 flash_cmd(portwidth,caddr,0,0xF0); /* reset bank */
571 /* TODO: 2x16 unsupported */
573 flash_erase (flash_info_t *info, int s_first, int s_last)
575 volatile unsigned char *addr = (uchar *)(info->start[0]);
576 int flag, prot, sect, l_sect;
577 ulong start, now, last;
579 /* TODO: 2x16 unsupported */
580 if(info->portwidth==4) return 1;
582 if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 1;
583 if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
584 for (sect = s_first; sect<=s_last; sect++) {
585 int sector_size=info->size/info->sector_count;
586 addr = (uchar *)(info->start[sect]);
587 memset((void *)addr, 0, sector_size);
592 if ((s_first < 0) || (s_first > s_last)) {
593 if (info->flash_id == FLASH_UNKNOWN) {
594 printf ("- missing\n");
596 printf ("- no sectors to erase\n");
601 if ((info->flash_id&FLASH_VENDMASK) == FLASH_MAN_INTEL) {
602 return flash_erase_intel(info,
603 (unsigned short)s_first,
604 (unsigned short)s_last);
608 if ((info->flash_id == FLASH_UNKNOWN) ||
609 (info->flash_id > FLASH_AMD_COMP)) {
610 printf ("Can't erase unknown flash type %08lx - aborted\n",
617 for (sect=s_first; sect<=s_last; ++sect) {
618 if (info->protect[sect]) {
624 printf ("- Warning: %d protected sectors will not be erased!\n",
632 /* Disable interrupts which might cause a timeout here */
633 flag = disable_interrupts();
635 flash_cmd(info->portwidth,addr,0x555,0xAA);
636 flash_cmd(info->portwidth,addr,0x2AA,0x55);
637 flash_cmd(info->portwidth,addr,0x555,0x80);
638 flash_cmd(info->portwidth,addr,0x555,0xAA);
639 flash_cmd(info->portwidth,addr,0x2AA,0x55);
641 /* Start erase on unprotected sectors */
642 for (sect = s_first; sect<=s_last; sect++) {
643 if (info->protect[sect] == 0) { /* not protected */
644 addr = (uchar *)(info->start[sect]);
645 flash_cmd(info->portwidth,addr,0,0x30);
650 /* re-enable interrupts if necessary */
654 /* wait at least 80us - let's wait 1 ms */
658 * We wait for the last triggered sector
663 start = get_timer (0);
665 addr = (volatile unsigned char *)(info->start[l_sect]);
666 /* broken for 2x16: TODO */
667 while ((addr[0] & 0x80) != 0x80) {
668 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
669 printf ("Timeout\n");
672 /* show that we're waiting */
673 if ((now - last) > 1000) { /* every second */
680 /* reset to read mode */
681 addr = (volatile unsigned char *)info->start[0];
682 flash_cmd(info->portwidth,addr,0,0xf0);
683 flash_cmd(info->portwidth,addr,0,0xf0);
689 /*-----------------------------------------------------------------------
690 * Copy memory to flash, returns:
693 * 2 - Flash not erased
696 /* broken for 2x16: TODO */
698 write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
703 if(info->portwidth==4) return 1;
705 if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 0;
706 if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
707 memcpy((void *)addr, src, cnt);
711 wp = (addr & ~3); /* get lower word aligned address */
714 * handle unaligned start bytes
716 if ((l = addr - wp) != 0) {
718 for (i=0, cp=wp; i<l; ++i, ++cp) {
719 data = (data << 8) | (*(uchar *)cp);
721 for (; i<4 && cnt>0; ++i) {
722 data = (data << 8) | *src++;
726 for (; cnt==0 && i<4; ++i, ++cp) {
727 data = (data << 8) | (*(uchar *)cp);
730 if ((rc = write_word(info, wp, data)) != 0) {
737 * handle word aligned part
741 for (i=0; i<4; ++i) {
742 data = (data << 8) | *src++;
744 if ((rc = write_word(info, wp, data)) != 0) {
756 * handle unaligned tail bytes
759 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
760 data = (data << 8) | *src++;
763 for (; i<4; ++i, ++cp) {
764 data = (data << 8) | (*(uchar *)cp);
767 return (write_word(info, wp, data));
770 /*-----------------------------------------------------------------------
771 * Write a word to Flash, returns:
774 * 2 - Flash not erased
776 /* broken for 2x16: TODO */
778 write_word (flash_info_t *info, ulong dest, ulong data)
780 volatile unsigned char *addr = (uchar *)(info->start[0]);
784 if(info->portwidth==4) return 1;
786 if((info->flash_id & FLASH_TYPEMASK) == FLASH_ROM) return 1;
787 if((info->flash_id & FLASH_TYPEMASK) == FLASH_RAM) {
788 *(unsigned long *)dest=data;
791 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
792 unsigned short low = data & 0xffff;
793 unsigned short hi = (data >> 16) & 0xffff;
794 int ret = write_word_intel((bank_addr_t)dest, hi);
796 if (!ret) ret = write_word_intel((bank_addr_t)(dest+2), low);
801 /* Check if Flash is (sufficiently) erased */
802 if ((*((vu_long *)dest) & data) != data) {
805 /* Disable interrupts which might cause a timeout here */
806 flag = disable_interrupts();
808 /* first, perform an unlock bypass command to speed up flash writes */
813 /* write each byte out */
814 for (i = 0; i < 4; i++) {
815 char *data_ch = (char *)&data;
817 *(((char *)dest)+i) = data_ch[i];
818 udelay(10); /* XXX */
821 /* we're done, now do an unlock bypass reset */
825 /* re-enable interrupts if necessary */
829 /* data polling for D7 */
830 start = get_timer (0);
831 while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) {
832 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {