📄 flash.c
字号:
base = (FPWV *) (CFG_AMD_BASE); base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */ base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */ base[FLASH_CYCLE1] = (FPW) 0x00800080; /* erase mode */ base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */ base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */ *addr = (FPW) 0x00300030; /* erase sector */ } while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) { if (get_timer (start) > CFG_FLASH_ERASE_TOUT) { printf ("Timeout\n"); if (intel) { *addr = (FPW) 0x00B000B0; /* suspend erase */ *addr = (FPW) 0x00FF00FF; /* reset to read mode */ } else *addr = (FPW) 0x00F000F0; /* reset to read mode */ rcode = 1; break; } } if (intel) { *addr = (FPW) 0x00500050; /* clear status register cmd. */ *addr = (FPW) 0x00FF00FF; /* resest to read mode */ } else *addr = (FPW) 0x00F000F0; /* reset to read mode */ printf (" done\n"); } } return rcode;}/*----------------------------------------------------------------------- * Copy memory to flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased * 4 - Flash not identified */int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt){ if (info->flash_id == FLASH_UNKNOWN) { return 4; } switch (info->flash_id & FLASH_VENDMASK) { case FLASH_MAN_AMD: { FPW data = 0; /* 16 or 32 bit word, matches flash bus width */ int bytes; /* number of bytes to program in current word */ int left; /* number of bytes left to program */ int i, res; for (left = cnt, res = 0; left > 0 && res == 0; addr += sizeof (data), left -= sizeof (data) - bytes) { bytes = addr & (sizeof (data) - 1); addr &= ~(sizeof (data) - 1); /* combine source and destination data so can program * an entire word of 16 or 32 bits */ for (i = 0; i < sizeof (data); i++) { data <<= 8; if (i < bytes || i - bytes >= left) data += *((uchar *) addr + i); else data += *src++; } res = write_word_amd (info, (FPWV *) addr, data); } return res; } /* case FLASH_MAN_AMD */ case FLASH_MAN_INTEL: { ulong cp, wp; FPW data; int count, i, l, rc, port_width; /* get lower word aligned address */ wp = addr; port_width = 1; /* * handle unaligned start bytes */ if ((l = addr - wp) != 0) { data = 0; for (i = 0, cp = wp; i < l; ++i, ++cp) { data = (data << 8) | (*(uchar *) cp); } for (; i < port_width && cnt > 0; ++i) { data = (data << 8) | *src++; --cnt; ++cp; } for (; cnt == 0 && i < port_width; ++i, ++cp) data = (data << 8) | (*(uchar *) cp); if ((rc = write_data (info, wp, SWAP (data))) != 0) return (rc); wp += port_width; } if (cnt > WR_BLOCK) { /* * handle word aligned part */ count = 0; while (cnt >= WR_BLOCK) { if ((rc = write_data_block (info, (ulong) src, wp)) != 0) return (rc); wp += WR_BLOCK; src += WR_BLOCK; cnt -= WR_BLOCK; if (count++ > 0x800) { spin_wheel (); count = 0; } } } if (cnt < WR_BLOCK) { /* * handle word aligned part */ count = 0; while (cnt >= port_width) { data = 0; for (i = 0; i < port_width; ++i) data = (data << 8) | *src++; if ((rc = write_data (info, wp, SWAP (data))) != 0) return (rc); wp += port_width; cnt -= port_width; if (count++ > 0x800) { spin_wheel (); count = 0; } } } if (cnt == 0) return (0); /* * handle unaligned tail bytes */ data = 0; for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) { data = (data << 8) | *src++; --cnt; } for (; i < port_width; ++i, ++cp) data = (data << 8) | (*(uchar *) cp); return (write_data (info, wp, SWAP (data))); } /* case FLASH_MAN_INTEL */ } /* switch */ return (0);}/*----------------------------------------------------------------------- * Write a word or halfword to Flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased */static int write_data (flash_info_t * info, ulong dest, FPW data){ FPWV *addr = (FPWV *) dest; ulong start; int flag; /* Check if Flash is (sufficiently) erased */ if ((*addr & data) != data) { printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr); return (2); } /* Disable interrupts which might cause a timeout here */ flag = disable_interrupts (); *addr = (FPW) 0x00400040; /* write setup */ *addr = data; /* arm simple, non interrupt dependent timer */ start = get_timer (0); /* wait while polling the status register */ while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) { if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { *addr = (FPW) 0x00FF00FF; /* restore read mode */ return (1); } } *addr = (FPW) 0x00FF00FF; /* restore read mode */ return (0);}/*----------------------------------------------------------------------- * Write a word or halfword to Flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased */static int write_data_block (flash_info_t * info, ulong src, ulong dest){ FPWV *srcaddr = (FPWV *) src; FPWV *dstaddr = (FPWV *) dest; ulong start; int flag, i; /* Check if Flash is (sufficiently) erased */ for (i = 0; i < WR_BLOCK; i++) if ((*dstaddr++ & 0xff) != 0xff) { printf ("not erased at %08lx (%lx)\n", (ulong) dstaddr, *dstaddr); return (2); } dstaddr = (FPWV *) dest; /* Disable interrupts which might cause a timeout here */ flag = disable_interrupts (); *dstaddr = (FPW) 0x00e800e8; /* write block setup */ /* arm simple, non interrupt dependent timer */ start = get_timer (0); /* wait while polling the status register */ while ((*dstaddr & (FPW) 0x00800080) != (FPW) 0x00800080) { if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { *dstaddr = (FPW) 0x00FF00FF; /* restore read mode */ return (1); } } *dstaddr = (FPW) 0x001f001f; /* write 32 to buffer */ for (i = 0; i < WR_BLOCK; i++) *dstaddr++ = *srcaddr++; dstaddr -= 1; *dstaddr = (FPW) 0x00d000d0; /* write 32 to buffer */ /* arm simple, non interrupt dependent timer */ start = get_timer (0); /* wait while polling the status register */ while ((*dstaddr & (FPW) 0x00800080) != (FPW) 0x00800080) { if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { *dstaddr = (FPW) 0x00FF00FF; /* restore read mode */ return (1); } } *dstaddr = (FPW) 0x00FF00FF; /* restore read mode */ return (0);}/*----------------------------------------------------------------------- * Write a word to Flash for AMD FLASH * A word is 16 or 32 bits, whichever the bus width of the flash bank * (not an individual chip) is. * * returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased */static int write_word_amd (flash_info_t * info, FPWV * dest, FPW data){ ulong start; int flag; int res = 0; /* result, assume success */ FPWV *base; /* first address in flash bank */ /* Check if Flash is (sufficiently) erased */ if ((*dest & data) != data) { return (2); } base = (FPWV *) (CFG_AMD_BASE); /* Disable interrupts which might cause a timeout here */ flag = disable_interrupts (); base[FLASH_CYCLE1] = (FPW) 0x00AA00AA; /* unlock */ base[FLASH_CYCLE2] = (FPW) 0x00550055; /* unlock */ base[FLASH_CYCLE1] = (FPW) 0x00A000A0; /* selects program mode */ *dest = data; /* start programming the data */ /* re-enable interrupts if necessary */ if (flag) enable_interrupts (); start = get_timer (0); /* data polling for D7 */ while (res == 0 && (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) { if (get_timer (start) > CFG_FLASH_WRITE_TOUT) { *dest = (FPW) 0x00F000F0; /* reset bank */ res = 1; } } return (res);}void inline spin_wheel (void){ static int p = 0; static char w[] = "\\/-"; printf ("\010%c", w[p]); (++p == 3) ? (p = 0) : 0;}/*----------------------------------------------------------------------- * Set/Clear sector's lock bit, returns: * 0 - OK * 1 - Error (timeout, voltage problems, etc.) */int flash_real_protect (flash_info_t * info, long sector, int prot){ ulong start; int i, j; int curr_bank; int bank; int rc = 0; FPWV *addr = (FPWV *) (info->start[sector]); int flag = disable_interrupts (); /* * 29F040B AMD flash does not support software protection/unprotection, * the only way to protect the AMD flash is marked it as prot bit. * This flash only support hardware protection, by supply or not supply * 12vpp to the flash */ if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) { info->protect[sector] = prot; return 0; } *addr = INTEL_CLEAR; /* Clear status register */ if (prot) { /* Set sector lock bit */ *addr = INTEL_LOCKBIT; /* Sector lock bit */ *addr = INTEL_PROTECT; /* set */ } else { /* Clear sector lock bit */ *addr = INTEL_LOCKBIT; /* All sectors lock bits */ *addr = INTEL_CONFIRM; /* clear */ } start = get_timer (0); while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) { if (get_timer (start) > CFG_FLASH_UNLOCK_TOUT) { printf ("Flash lock bit operation timed out\n"); rc = 1; break; } } if (*addr != INTEL_OK) { printf ("Flash lock bit operation failed at %08X, CSR=%08X\n", (uint) addr, (uint) * addr); rc = 1; } if (!rc) info->protect[sector] = prot; /* * Clear lock bit command clears all sectors lock bits, so * we have to restore lock bits of protected sectors. */ if (!prot) { /* * re-locking must be done for all banks that belong on one * FLASH chip, as all the sectors on the chip were unlocked * by INTEL_LOCKBIT/INTEL_CONFIRM commands. (let's hope * that banks never span chips, in particular chips which * support h/w protection differently). */ /* find the current bank number */ curr_bank = CFG_MAX_FLASH_BANKS + 1; for (j = 0; j < CFG_MAX_FLASH_BANKS; ++j) { if (&flash_info[j] == info) { curr_bank = j; } } if (curr_bank == CFG_MAX_FLASH_BANKS + 1) { printf("Error: can't determine bank number!\n"); } for (bank = 0; bank < CFG_MAX_FLASH_BANKS; ++bank) { if (!same_chip_banks(curr_bank, bank)) { continue; } info = &flash_info[bank]; for (i = 0; i < info->sector_count; i++) { if (info->protect[i]) { start = get_timer (0); addr = (FPWV *) (info->start[i]); *addr = INTEL_LOCKBIT; /* Sector lock bit */ *addr = INTEL_PROTECT; /* set */ while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) { if (get_timer (start) > CFG_FLASH_UNLOCK_TOUT) { printf ("Flash lock bit operation timed out\n"); rc = 1; break; } } } } } /* * get the s/w sector protection status in sync with the h/w, * in case something went wrong during the re-locking. */ flash_sync_real_protect(info); /* resets flash to read mode */ } if (flag) enable_interrupts (); *addr = INTEL_RESET; /* Reset to read array mode */ return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -