?? flash.c
字號:
/* * board/eva/flash.c * * (C) Copyright 2002 * Sangmoon Kim, Etin Systems, dogoil@etinsys.com. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <asm/processor.h>#include <asm/pci_io.h>#include <mpc824x.h>int (*do_flash_erase)(flash_info_t*, uint32_t, uint32_t);int (*write_dword)(flash_info_t*, ulong, uint64_t);typedef uint64_t cfi_word;#define cfi_read(flash, addr) *((volatile cfi_word*)(flash->start[0] + addr))#define cfi_write(flash, val, addr) \ move64((cfi_word*)&val, \ (cfi_word*)(flash->start[0] + addr))#define CMD(x) ((((cfi_word)x)<<48)|(((cfi_word)x)<<32)|(((cfi_word)x)<<16)|(((cfi_word)x)))static void write32(unsigned long addr, uint32_t value){ *(volatile uint32_t*)(addr) = value; asm volatile("sync");}static uint32_t read32(unsigned long addr){ uint32_t value; value = *(volatile uint32_t*)addr; asm volatile("sync"); return value;}static cfi_word cfi_cmd(flash_info_t *flash, uint8_t cmd, uint32_t addr){ uint32_t base = flash->start[0]; uint32_t val=(cmd << 16) | cmd; addr <<= 3; write32(base + addr, val); return addr;}static uint16_t cfi_read_query(flash_info_t *flash, uint32_t addr){ uint32_t base = flash->start[0]; addr <<= 3; return (uint16_t)read32(base + addr);}flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */static void move64(uint64_t *src, uint64_t *dest){ asm volatile("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ "stfd 0, 0(4)" /* *dest = fpr0 */ : : : "fr0" ); /* Clobbers fr0 */ return;}static int cfi_write_dword(flash_info_t *flash, ulong dest, cfi_word data){ unsigned long start; cfi_word status = 0; status = cfi_read(flash, dest); data &= status; cfi_cmd(flash, 0x40, 0); cfi_write(flash, data, dest); udelay(10); start = get_timer (0); for(;;) { status = cfi_read(flash, dest); status &= CMD(0x80); if(status == CMD(0x80)) break; if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { cfi_cmd(flash, 0xff, 0); return 1; } udelay(1); } cfi_cmd(flash, 0xff, 0); return 0;}static int jedec_write_dword (flash_info_t *flash, ulong dest, cfi_word data){ ulong start; cfi_word status = 0; status = cfi_read(flash, dest); if(status != CMD(0xffff)) return 2; cfi_cmd(flash, 0xaa, 0x555); cfi_cmd(flash, 0x55, 0x2aa); cfi_cmd(flash, 0xa0, 0x555); cfi_write(flash, data, dest); udelay(10); start = get_timer (0); status = ~data; while(status != data) { if (get_timer(start) > CFG_FLASH_WRITE_TOUT) return 1; status = cfi_read(flash, dest); udelay(1); } return 0;}static __inline__ unsigned long get_msr(void){ unsigned long msr; __asm__ __volatile__ ("mfmsr %0" : "=r" (msr) :); return msr;}static __inline__ void set_msr(unsigned long msr){ __asm__ __volatile__ ("mtmsr %0" : : "r" (msr));}int write_buff (flash_info_t *flash, uchar *src, ulong addr, ulong cnt){ ulong wp; int i, s, l, rc; cfi_word data; uint8_t *t = (uint8_t*)&data; unsigned long base = flash->start[0]; uint32_t msr; if (flash->flash_id == FLASH_UNKNOWN) return 4; return 0; addr -= base; msr = get_msr(); set_msr(msr|MSR_FP); wp = (addr & ~7); /* get lower word aligned address */ if((addr-wp) != 0) { data = cfi_read(flash, wp); s = addr & 7; l = ( cnt < (8-s) ) ? cnt : (8-s); for(i = 0; i < l; i++) t[s+i] = *src++; if ((rc = write_dword(flash, wp, data)) != 0) goto DONE; wp += 8; cnt -= l; } while (cnt >= 8) { for (i = 0; i < 8; i++) t[i] = *src++; if ((rc = write_dword(flash, wp, data)) != 0) goto DONE; wp += 8; cnt -= 8; } if (cnt == 0) { rc = 0; goto DONE; } data = cfi_read(flash, wp); for(i = 0; i < cnt; i++) t[i] = *src++; rc = write_dword(flash, wp, data);DONE: set_msr(msr); return rc;}static int cfi_erase_oneblock(flash_info_t *flash, uint32_t sect){ int sa; int flag; ulong start, last, now; cfi_word status; flag = disable_interrupts(); sa = (flash->start[sect] - flash->start[0]); write32(flash->start[sect], 0x00200020); write32(flash->start[sect], 0x00d000d0); if (flag) enable_interrupts(); udelay(1000); start = get_timer (0); last = start; for (;;) { status = cfi_read(flash, sa); status &= CMD(0x80); if (status == CMD(0x80)) break; if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { cfi_cmd(flash, 0xff, 0); printf ("Timeout\n"); return ERR_TIMOUT; } if ((now - last) > 1000) { serial_putc ('.'); last = now; } udelay(10); } cfi_cmd(flash, 0xff, 0); return ERR_OK;}static int cfi_erase(flash_info_t *flash, uint32_t s_first, uint32_t s_last){ int sect; int rc = ERR_OK; for (sect = s_first; sect <= s_last; sect++) { if (flash->protect[sect] == 0) { rc = cfi_erase_oneblock(flash, sect); if (rc != ERR_OK) break; } } printf (" done\n"); return rc;}static int jedec_erase(flash_info_t *flash, uint32_t s_first, uint32_t s_last){ int sect; cfi_word status; int sa = -1; int flag; ulong start, last, now; flag = disable_interrupts(); cfi_cmd(flash, 0xaa, 0x555); cfi_cmd(flash, 0x55, 0x2aa); cfi_cmd(flash, 0x80, 0x555); cfi_cmd(flash, 0xaa, 0x555); cfi_cmd(flash, 0x55, 0x2aa); for ( sect = s_first; sect <= s_last; sect++) { if (flash->protect[sect] == 0) { sa = flash->start[sect] - flash->start[0]; write32(flash->start[sect], 0x00300030); } } if (flag) enable_interrupts(); if (sa < 0) goto DONE; udelay (1000); start = get_timer (0); last = start; for(;;) { status = cfi_read(flash, sa); if (status == CMD(0xffff)) break; if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { printf ("Timeout\n"); return ERR_TIMOUT; } if ((now - last) > 1000) { serial_putc ('.'); last = now; } udelay(10); }DONE: cfi_cmd(flash, 0xf0, 0); printf (" done\n"); return ERR_OK;}int flash_erase (flash_info_t *flash, int s_first, int s_last){ int sect; int prot; if ((s_first < 0) || (s_first > s_last)) { if (flash->flash_id == FLASH_UNKNOWN) printf ("- missing\n"); else printf ("- no sectors to erase\n"); return ERR_NOT_ERASED; } if (flash->flash_id == FLASH_UNKNOWN) { printf ("Can't erase unknown flash type - aborted\n"); return ERR_NOT_ERASED; } prot = 0; for (sect = s_first; sect <= s_last; sect++) if (flash->protect[sect]) prot++; if (prot) printf ("- Warning: %d protected sectors will not be erased!\n", prot); else printf ("\n"); return do_flash_erase(flash, s_first, s_last);}struct jedec_flash_info { const uint16_t mfr_id; const uint16_t dev_id; const char *name; const int DevSize; const int InterfaceDesc; const int NumEraseRegions; const ulong regions[4];};#define ERASEINFO(size,blocks) (size<<8)|(blocks-1)#define SIZE_1MiB 20#define SIZE_2MiB 21
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -