📄 cam5200_flash.c
字号:
if ((rc = write_word(info, wp, data)) != 0) return (rc); wp += 4; cnt -= 4; } if (cnt == 0) return (0); /* * handle unaligned tail bytes */ data = 0; for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) { data = (data << 8) | *src++; --cnt; } for (; i < 4; ++i, ++cp) data = (data << 8) | (*(uchar *) cp); return (write_word(info, wp, data));}/*----------------------------------------------------------------------- * Copy memory to flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased */#ifdef CFG_FLASH_2ND_16BIT_DEVstatic int write_word(flash_info_t * info, ulong dest, ulong data){ if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) { return write_word_16(info, dest, data); } else { return write_word_32(info, dest, data); }}static int write_word_32(flash_info_t * info, ulong dest, ulong data)#elsestatic int write_word(flash_info_t * info, ulong dest, ulong data)#endif{ volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *) (info->start[0]); volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *) dest; volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *) & data; ulong start; int i, flag; /* Check if Flash is (sufficiently) erased */ if ((*((vu_long *)dest) & data) != data) return (2); for (i = 0; i < 4 / sizeof(CFG_FLASH_WORD_SIZE); i++) { /* Disable interrupts which might cause a timeout here */ flag = disable_interrupts(); addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00AA00AA; addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x00550055; addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x00A000A0; dest2[i] = data2[i]; /* re-enable interrupts if necessary */ if (flag) enable_interrupts(); /* data polling for D7 */ start = get_timer(0); while ((dest2[i] & (CFG_FLASH_WORD_SIZE) 0x00800080) != (data2[i] & (CFG_FLASH_WORD_SIZE) 0x00800080)) { if (get_timer(start) > CFG_FLASH_WRITE_TOUT) return (1); } } return (0);}#ifdef CFG_FLASH_2ND_16BIT_DEV#undef CFG_FLASH_WORD_SIZE#define CFG_FLASH_WORD_SIZE unsigned short/* * The following code cannot be run from FLASH! */static ulong flash_get_size_16(vu_long * addr, flash_info_t * info){ short i; CFG_FLASH_WORD_SIZE value; ulong base = (ulong) addr; volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *) addr; DEBUGF("get_size16: FLASH ADDR: %08x\n", (unsigned)addr); /* issue bank reset to return to read mode */ addr2[0] = (CFG_FLASH_WORD_SIZE) 0xF000F000; /* Write auto select command: read Manufacturer ID */ addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0xAA00AA00; addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x55005500; addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x90009000; udelay(1000); value = swap16(addr2[0]); DEBUGF("FLASH MANUFACT: %x\n", value); switch (value) { case (CFG_FLASH_WORD_SIZE) AMD_MANUFACT: info->flash_id = FLASH_MAN_AMD; break; case (CFG_FLASH_WORD_SIZE) FUJ_MANUFACT: info->flash_id = FLASH_MAN_FUJ; break; default: info->flash_id = FLASH_UNKNOWN; info->sector_count = 0; info->size = 0; return (0); /* no or unknown flash */ } value = swap16(addr2[1]); /* device ID */ DEBUGF("\nFLASH DEVICEID: %x\n", value); switch (value) { case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320B: info->flash_id += FLASH_AM320B; info->sector_count = 71; info->size = 0x00400000; break; /* => 4 MB */ case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320T: info->flash_id += FLASH_AM320T; info->sector_count = 71; info->size = 0x00400000; break; /* => 4 MB */ default: info->flash_id = FLASH_UNKNOWN; return (0); /* => no or unknown flash */ } if (info->flash_id & FLASH_BTYPE) { /* set sector offsets for bottom boot block type */ info->start[0] = base + 0x00000000; info->start[1] = base + 0x00002000; info->start[2] = base + 0x00004000; info->start[3] = base + 0x00006000; info->start[4] = base + 0x00008000; info->start[5] = base + 0x0000a000; info->start[6] = base + 0x0000c000; info->start[7] = base + 0x0000e000; for (i = 8; i < info->sector_count; i++) info->start[i] = base + (i * 0x00010000) - 0x00070000; } else { /* set sector offsets for top boot block type */ i = info->sector_count - 1; info->start[i--] = base + info->size - 0x00002000; info->start[i--] = base + info->size - 0x00004000; info->start[i--] = base + info->size - 0x00006000; info->start[i--] = base + info->size - 0x00008000; info->start[i--] = base + info->size - 0x0000a000; info->start[i--] = base + info->size - 0x0000c000; info->start[i--] = base + info->size - 0x0000e000; for (; i >= 0; i--) info->start[i] = base + i * 0x00010000; } /* check for protected sectors */ for (i = 0; i < info->sector_count; i++) { /* read sector protection at sector address, (A7 .. A0) = 0x02 */ /* D0 = 1 if protected */ addr2 = (volatile CFG_FLASH_WORD_SIZE *)(info->start[i]); info->protect[i] = addr2[2] & 1; } /* issue bank reset to return to read mode */ addr2[0] = (CFG_FLASH_WORD_SIZE) 0xF000F000; return (info->size);}static int wait_for_DQ7_16(flash_info_t * info, int sect){ ulong start, now, last; volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *) (info->start[sect]); start = get_timer(0); last = start; while ((addr[0] & (CFG_FLASH_WORD_SIZE) 0x80008000) != (CFG_FLASH_WORD_SIZE) 0x80008000) { if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { printf("Timeout\n"); return -1; } /* show that we're waiting */ if ((now - last) > 1000) { /* every second */ putc('.'); last = now; } } return 0;}static int flash_erase_16(flash_info_t * info, int s_first, int s_last){ volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *) (info->start[0]); volatile CFG_FLASH_WORD_SIZE *addr2; int flag, prot, sect, l_sect; 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; } if (info->flash_id == FLASH_UNKNOWN) { printf("Can't erase unknown flash type - aborted\n"); 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!", prot); printf("\n"); l_sect = -1; /* Disable interrupts which might cause a timeout here */ flag = disable_interrupts(); /* Start erase on unprotected sectors */ for (sect = s_first; sect <= s_last; sect++) { if (info->protect[sect] == 0) { /* not protected */ addr2 = (CFG_FLASH_WORD_SIZE *) (info->start[sect]); addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0xAA00AA00; addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x55005500; addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0x80008000; addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0xAA00AA00; addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x55005500; addr2[0] = (CFG_FLASH_WORD_SIZE) 0x30003000; /* sector erase */ l_sect = sect; /* * Wait for each sector to complete, it's more * reliable. According to AMD Spec, you must * issue all erase commands within a specified * timeout. This has been seen to fail, especially * if printf()s are included (for debug)!! */ wait_for_DQ7_16(info, sect); } } /* re-enable interrupts if necessary */ if (flag) enable_interrupts(); /* wait at least 80us - let's wait 1 ms */ udelay(1000); /* reset to read mode */ addr = (CFG_FLASH_WORD_SIZE *) info->start[0]; addr[0] = (CFG_FLASH_WORD_SIZE) 0xF000F000; /* reset bank */ printf(" done\n"); return 0;}static int write_word_16(flash_info_t * info, ulong dest, ulong data){ volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *) (info->start[0]); volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *) dest; volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *) & data; ulong start; int i; /* Check if Flash is (sufficiently) erased */ for (i = 0; i < 4 / sizeof(CFG_FLASH_WORD_SIZE); i++) { if ((dest2[i] & swap16(data2[i])) != swap16(data2[i])) return (2); } for (i = 0; i < 4 / sizeof(CFG_FLASH_WORD_SIZE); i++) { int flag; /* Disable interrupts which might cause a timeout here */ flag = disable_interrupts(); addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0xAA00AA00; addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE) 0x55005500; addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE) 0xA000A000; dest2[i] = swap16(data2[i]); /* re-enable interrupts if necessary */ if (flag) enable_interrupts(); /* data polling for D7 */ start = get_timer(0); while ((dest2[i] & (CFG_FLASH_WORD_SIZE) 0x80008000) != (swap16(data2[i]) & (CFG_FLASH_WORD_SIZE) 0x80008000)) { if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { return (1); } } } return (0);}#endif /* CFG_FLASH_2ND_16BIT_DEV *//*----------------------------------------------------------------------- * Functions */static ulong flash_get_size(vu_long * addr, flash_info_t * info);static int write_word(flash_info_t * info, ulong dest, ulong data);/*----------------------------------------------------------------------- */unsigned long flash_init(void){ unsigned long total_b = 0; unsigned long size_b[CFG_MAX_FLASH_BANKS]; unsigned short index = 0; int i; DEBUGF("\n"); DEBUGF("FLASH: Index: %d\n", index); /* Init: no FLASHes known */ for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { flash_info[i].flash_id = FLASH_UNKNOWN; flash_info[i].sector_count = -1; flash_info[i].size = 0; /* check whether the address is 0 */ if (flash_addr_table[index][i] == 0) continue; /* call flash_get_size() to initialize sector address */ size_b[i] = flash_get_size((vu_long *) flash_addr_table[index][i], &flash_info[i]); flash_info[i].size = size_b[i]; if (flash_info[i].flash_id == FLASH_UNKNOWN) { printf("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", i, size_b[i], size_b[i] << 20); flash_info[i].sector_count = -1; flash_info[i].size = 0; } /* Monitor protection ON by default */ (void)flash_protect(FLAG_PROTECT_SET, CFG_MONITOR_BASE, CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, &flash_info[i]);#if defined(CFG_ENV_IS_IN_FLASH) (void)flash_protect(FLAG_PROTECT_SET, CFG_ENV_ADDR, CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, &flash_info[i]);#if defined(CFG_ENV_ADDR_REDUND) (void)flash_protect(FLAG_PROTECT_SET, CFG_ENV_ADDR_REDUND, CFG_ENV_ADDR_REDUND + CFG_ENV_SECT_SIZE - 1, &flash_info[i]);#endif#endif total_b += flash_info[i].size; } return total_b;}#endif /* ifdef CONFIG_CAM5200 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -