📄 flash.c
字号:
info->sector_count = sectors; info->size = sz; *addr = (FPW) INTEL_RESET; /* restore read mode */ } else { int sect[] = CFG_ATMEL_SECT; int sectsz[] = CFG_ATMEL_SECTSZ; info->sector_count = 0; info->size = 0; for (i = 0; i < CFG_ATMEL_REGION; i++) { info->sector_count += sect[i]; info->size += sect[i] * sectsz[i]; } /* reset ID mode */ addr[0] = (FPWV) 0x00F000F0; } if (info->sector_count > CFG_MAX_FLASH_SECT) { printf("** ERROR: sector count %d > max (%d) **\n", info->sector_count, CFG_MAX_FLASH_SECT); info->sector_count = CFG_MAX_FLASH_SECT; } return (info->size);}int flash_cmd_rd(volatile u16 * addr, int index){ return (int)addr[index];}#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI)int serial_flash_read_status(int chipsel){ u16 status; dspi_tx(chipsel, 0x80, SER_RDSR); dspi_rx(); dspi_tx(chipsel, 0x00, 0); status = dspi_rx(); return status;}#endif/* * This function gets the u-boot flash sector protection status * (flash_info_t.protect[]) in sync with the sector protection * status stored in hardware. */void flash_sync_real_protect(flash_info_t * info){ int i; switch (info->flash_id & FLASH_TYPEMASK) { case FLASH_28F160C3B: case FLASH_28F160C3T: case FLASH_28F320C3B: case FLASH_28F320C3T: case FLASH_28F640C3B: case FLASH_28F640C3T: for (i = 0; i < info->sector_count; ++i) { info->protect[i] = intel_sector_protected(info, i); } break; default: /* no h/w protect support */ break; }}/* * checks if "sector" in bank "info" is protected. Should work on intel * strata flash chips 28FxxxJ3x in 8-bit mode. * Returns 1 if sector is protected (or timed-out while trying to read * protection status), 0 if it is not. */uchar intel_sector_protected(flash_info_t * info, ushort sector){ FPWV *addr; FPWV *lock_conf_addr; ulong start; unsigned char ret; /* * first, wait for the WSM to be finished. The rationale for * waiting for the WSM to become idle for at most * CFG_FLASH_ERASE_TOUT is as follows. The WSM can be busy * because of: (1) erase, (2) program or (3) lock bit * configuration. So we just wait for the longest timeout of * the (1)-(3), i.e. the erase timeout. */ /* wait at least 35ns (W12) before issuing Read Status Register */ /*udelay(1); */ addr = (FPWV *) info->start[sector]; *addr = (FPW) INTEL_STATUS; start = get_timer(0); while ((*addr & (FPW) INTEL_FINISHED) != (FPW) INTEL_FINISHED) { if (get_timer(start) > CFG_FLASH_UNLOCK_TOUT) { *addr = (FPW) INTEL_RESET; /* restore read mode */ printf("WSM busy too long, can't get prot status\n"); return 1; } } /* issue the Read Identifier Codes command */ *addr = (FPW) INTEL_READID; /* Intel example code uses offset of 4 for 8-bit flash */ lock_conf_addr = (FPWV *) info->start[sector]; ret = (lock_conf_addr[INTEL_CFI_LOCK] & (FPW) INTEL_PROTECT) ? 1 : 0; /* put flash back in read mode */ *addr = (FPW) INTEL_RESET; return ret;}int flash_erase(flash_info_t * info, int s_first, int s_last){ int flag, prot, sect; ulong type, start, last; int rcode = 0, flashtype = 0;#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI) int count; u16 status;#endif if ((s_first < 0) || (s_first > s_last)) { if (info->flash_id == FLASH_UNKNOWN) printf("- missing\n"); else printf("- no sectors to erase\n"); return 1; } type = (info->flash_id & FLASH_VENDMASK); switch (type) { case FLASH_MAN_ATM: flashtype = 1; break; case FLASH_MAN_INTEL: flashtype = 2; break;#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI) case FLASH_MAN_STM: flashtype = 3; break;#endif default: type = (info->flash_id & FLASH_VENDMASK); printf("Can't erase unknown flash type %08lx - aborted\n", info->flash_id); return 1; } prot = 0; for (sect = s_first; sect <= s_last; ++sect) { if (info->protect[sect]) { prot++; } } if (prot) printf("- Warning: %d protected sectors will not be erased!\n", prot); else printf("\n"); start = get_timer(0); last = start;#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI) /* Perform bulk erase */ if (flashtype == 3) { if ((s_last - s_first) == (CFG_STM_SECT - 1)) { if (prot == 0) { dspi_tx(ser_flash_cs, 0x00, SER_WREN); dspi_rx(); status = serial_flash_read_status(ser_flash_cs); if (((status & 0x9C) != 0) && ((status & 0x02) != 0x02)) { printf("Can't erase flash\n"); return 1; } dspi_tx(ser_flash_cs, 0x00, SER_BULK_ERASE); dspi_rx(); count = 0; start = get_timer(0); do { status = serial_flash_read_status (ser_flash_cs); if (count++ > 0x10000) { spin_wheel(); count = 0; } if (get_timer(start) > CFG_FLASH_ERASE_TOUT) { printf("Timeout\n"); return 1; } } while (status & 0x01); printf("\b. done\n"); return 0; } else if (prot == CFG_STM_SECT) { return 1; } } }#endif /* Start erase on unprotected sectors */ for (sect = s_first; sect <= s_last; sect++) { if (info->protect[sect] == 0) { /* not protected */ FPWV *addr = (FPWV *) (info->start[sect]); int min = 0; printf("."); /* arm simple, non interrupt dependent timer */ start = get_timer(0); switch (flashtype) { case 1: { FPWV *base; /* first address in bank */ FPWV *atmeladdr; flag = disable_interrupts(); atmeladdr = (FPWV *) addr; /* concatenate to 8 bit */ base = (FPWV *) (CFG_ATMEL_BASE); /* First sector */ base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */ base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */ base[FLASH_CYCLE1] = (u8) 0x00800080; /* erase mode */ base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */ base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */ *atmeladdr = (u8) 0x00300030; /* erase sector */ if (flag) enable_interrupts(); while ((*atmeladdr & (u8) 0x00800080) != (u8) 0x00800080) { if (get_timer(start) > CFG_FLASH_ERASE_TOUT) { printf("Timeout\n"); *atmeladdr = (u8) 0x00F000F0; /* reset to read mode */ rcode = 1; break; } } *atmeladdr = (u8) 0x00F000F0; /* reset to read mode */ break; } case 2: { *addr = (FPW) INTEL_READID; min = addr[INTEL_CFI_TERB] & 0xff; min = 1 << min; /* ms */ min = (min / info->sector_count) * 1000; /* start erase block */ *addr = (FPW) INTEL_CLEAR; /* clear status register */ *addr = (FPW) INTEL_ERASE; /* erase setup */ *addr = (FPW) INTEL_CONFIRM; /* erase confirm */ while ((*addr & (FPW) INTEL_FINISHED) != (FPW) INTEL_FINISHED) { if (get_timer(start) > CFG_FLASH_ERASE_TOUT) { printf("Timeout\n"); *addr = (FPW) INTEL_SUSERASE; /* suspend erase */ *addr = (FPW) INTEL_RESET; /* reset to read mode */ rcode = 1; break; } } *addr = (FPW) INTEL_RESET; /* resest to read mode */ break; }#if defined(CONFIG_SERIAL_FLASH) && defined(CONFIG_CF_DSPI) case 3: { u8 sec = ((ulong) addr >> 16) & 0xFF; dspi_tx(ser_flash_cs, 0x00, SER_WREN); dspi_rx(); status = serial_flash_read_status (ser_flash_cs); if (((status & 0x9C) != 0) && ((status & 0x02) != 0x02)) { printf("Error Programming\n"); return 1; } dspi_tx(ser_flash_cs, 0x80, SER_SECT_ERASE); dspi_tx(ser_flash_cs, 0x80, sec); dspi_tx(ser_flash_cs, 0x80, 0); dspi_tx(ser_flash_cs, 0x00, 0); dspi_rx(); dspi_rx(); dspi_rx(); dspi_rx(); do { status = serial_flash_read_status (ser_flash_cs); if (get_timer(start) > CFG_FLASH_ERASE_TOUT) { printf("Timeout\n"); return 1; } } while (status & 0x01); break; }#endif } /* switch (flashtype) */ } } printf(" done\n"); return rcode;}int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt){ int count; if (info->flash_id == FLASH_UNKNOWN) return 4; switch (info->flash_id & FLASH_VENDMASK) { case FLASH_MAN_ATM: { u16 data = 0; 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++; } data = (data >> 8) | (data << 8); res = write_word_atm(info, (FPWV *) addr, data); } return res; } /* case FLASH_MAN_ATM */ case FLASH_MAN_INTEL: { ulong cp, wp; u16 data; int i, l, rc, port_width; /* get lower word aligned address */ wp = addr; port_width = sizeof(FPW); /* * 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, data)) != 0) return (rc); wp += port_width; } if (cnt > WR_BLOCK) { /* * handle word aligned part */ count = 0; while (cnt >= WR_BLOCK) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -