URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [orpmon/] [drivers/] [flash.c] - Rev 828
Go to most recent revision | Compare with Previous | Blame | View Log
#include "common.h" #include "support.h" #include "flash.h" /* Returns nonzero if there is an error */ int fl_init (void) { unsigned long tmp; REG32(FLASH_BASE_ADDR) = 0x00ff00ff; REG32(FLASH_BASE_ADDR) = 0x00900090; tmp = REG32(FLASH_BASE_ADDR) << 8; REG32(FLASH_BASE_ADDR) = 0x00900090; tmp = tmp | REG32(FLASH_BASE_ADDR + 4); debug("id = %08x ", tmp); if (tmp != 0x89188918) { printf ("bad ID\n"); return 1; } else debug ("good ID\n"); REG32(FLASH_BASE_ADDR) = 0x00ff00ff; return 0; } int check_error (unsigned long sr, unsigned long addr) { if ((sr & (FL_SR_ERASE_ERR << 16)) || (sr & FL_SR_ERASE_ERR)) { printf ("erase error at %08lx\n", addr); /* Clear status register */ REG32(FLASH_BASE_ADDR) = 0x05D00050; return 1; } else if ((sr & (FL_SR_PROG_ERR << 16)) || (sr & FL_SR_PROG_ERR)) { printf ("program error at %08lx\n", addr); /* Clear status register */ REG32(FLASH_BASE_ADDR) = 0x05D00050; return 1; } else if ((sr & (FL_SR_PROG_LV << 16)) || (sr & FL_SR_PROG_LV)) { printf ("low voltage error\n"); /* Clear status register */ REG32(FLASH_BASE_ADDR) = 0x05D00050; return 1; } else if ((sr & (FL_SR_LOCK << 16)) || (sr & FL_SR_LOCK)) { printf ("lock bit error at %08lx\n", addr); /* Clear status register */ REG32(FLASH_BASE_ADDR) = 0x05D00050; return 1; } return 0; } int fl_block_erase (unsigned long addr) { unsigned long sr; REG32(addr & ~(FLASH_BLOCK_SIZE - 1)) = 0x00200020; REG32(addr & ~(FLASH_BLOCK_SIZE - 1)) = 0x00D000D0; do { REG32(FLASH_BASE_ADDR) = 0x00700070; sr = REG32(FLASH_BASE_ADDR); } while (!(sr & (FL_SR_WSM_READY << 16)) || !(sr & FL_SR_WSM_READY)); REG32(FLASH_BASE_ADDR) = 0x00ff00ff; return check_error (sr, addr); } int fl_unlock_blocks (void) { unsigned long sr; printf ("Clearing all lock bits... "); REG32(FLASH_BASE_ADDR) = 0x00600060; REG32(FLASH_BASE_ADDR) = 0x00d000d0; do { REG32(FLASH_BASE_ADDR) = 0x00700070; sr = REG32(FLASH_BASE_ADDR); } while (!(sr & (FL_SR_WSM_READY << 16)) || !(sr & FL_SR_WSM_READY)); printf ("done\n"); return check_error (sr, FLASH_BASE_ADDR); } int fl_word_program (unsigned long addr, unsigned long val) { unsigned long sr; REG32(addr) = 0x00400040; REG32(addr) = val; do { REG32(FLASH_BASE_ADDR) = 0x00700070; sr = REG32(FLASH_BASE_ADDR); } while (!(sr & (FL_SR_WSM_READY << 16)) || !(sr & FL_SR_WSM_READY)); REG32(FLASH_BASE_ADDR) = 0x00ff00ff; return check_error (sr, addr); } /* erase = 1 (whole chip), erase = 2 (required only) */ int fl_program (unsigned long src_addr, unsigned long dst_addr, unsigned long len, int erase, int verify) { unsigned long tmp, taddr, tlen; unsigned long i; if (erase) { fl_unlock_blocks (); if (erase == 2) { taddr = dst_addr & ~(FLASH_BLOCK_SIZE - 1); tlen = (dst_addr + len + FLASH_BLOCK_SIZE - 1) / FLASH_BLOCK_SIZE; } else { taddr = FLASH_BASE_ADDR; tlen = FLASH_SIZE / FLASH_BLOCK_SIZE; } printf ("Erasing flash... "); for (i = 0, tmp = taddr; i < tlen; i++, tmp += FLASH_BLOCK_SIZE) if (fl_block_erase (tmp)) return 1; printf ("done\n"); if (verify) { printf ("Writing test pattern... "); for (tmp = taddr; tmp < taddr + tlen * FLASH_BLOCK_SIZE; i++, tmp += 4) if (fl_word_program (tmp, tmp)) return 1; printf ("done\n"); printf ("Checking... "); for (tmp = taddr; tmp < taddr + tlen * FLASH_BLOCK_SIZE; i++, tmp += 4) if (REG32(tmp) != tmp) { printf ("failed on location %08lx: %08lx\n", tmp, REG32(tmp)); return 1; } printf ("done\n"); } } REG32(FLASH_BASE_ADDR) = 0x00ff00ff; printf ("Copying from %08lx-%08lx to %08lx-%08lx\n", src_addr, src_addr + len - 1, dst_addr, dst_addr + len - 1); tlen = len / 8; tmp = 0; printf ("Programing"); for (i = 0; i < len; i += 4) { if (fl_word_program (dst_addr + i, REG32(src_addr + i))) return 1; if (i > tmp) { printf ("."); tmp += tlen; } } printf (" done\n"); if (verify) { printf ("Verifying"); tmp = 0; for (i = 0; i < len; i += 4) { if (REG32(src_addr + i) != REG32(dst_addr + i)) { printf ("error at %08lx: %08lx != %08lx\n", src_addr + i, REG32(src_addr + i), REG32(dst_addr + i)); return 1; } if (i > tmp) { printf ("."); tmp += tlen; } } } printf (" done\n"); return 0; }
Go to most recent revision | Compare with Previous | Blame | View Log