From: Erik M. <er...@us...> - 2001-10-21 21:35:14
|
Update of /cvsroot/blob/blob/src/blob In directory usw-pr-cvs1:/tmp/cvs-serv16865 Added Files: intel16.c intel32.c amd32.c nullflash.c Log Message: New flash functions per flash type --- NEW FILE: intel16.c --- /* * intel16.c: Intel 16 bit flash driver * * Copyright (C) 2001 Erik Mouw (J.A...@it...) * Copyright (C) 1999 Jan-Derk Bakker (J.D...@it...) * * 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 * */ #ident "$Id: intel16.c,v 1.1 2001/10/21 21:35:11 erikm Exp $" #ifdef HAVE_CONFIG_H # include <blob/config.h> #endif #include <blob/errno.h> #include <blob/flash.h> #include <blob/util.h> /* flash commands for a single 16 bit intel flash chip */ #define READ_ARRAY 0x000000FF #define ERASE_SETUP 0x00000020 #define ERASE_CONFIRM 0x000000D0 #define PGM_SETUP 0x00000040 #define STATUS_READ 0x00000070 #define STATUS_CLEAR 0x00000050 #define STATUS_BUSY 0x00000080 #define STATUS_ERASE_ERR 0x00000020 #define STATUS_PGM_ERR 0x00000010 static int do_erase(u16 *addr) { u16 result; /* prepare for erase */ *addr = ERASE_SETUP; barrier(); /* erase block */ *addr = ERASE_CONFIRM; barrier(); /* status check */ do { *addr = STATUS_READ; barrier(); result = *addr; barrier(); } while((~result & STATUS_BUSY) != 0); /* put flash back into Read Array mode */ *addr = READ_ARRAY; barrier(); if((result & STATUS_ERASE_ERR) != 0) return -EFLASHERASE; return 0; } static int do_write(u16 *dst, const u16* src) { u16 result; /* setup flash for writing */ *dst = PGM_SETUP; barrier(); /* write data */ *dst = *src; barrier(); /* status check */ do { *dst = STATUS_READ; barrier(); result = *dst; barrier(); } while((~result & STATUS_BUSY) != 0); /* put flash back into Read Array mode */ *dst = READ_ARRAY; barrier(); if(((result & STATUS_PGM_ERR) != 0) || (*dst != *src)) return -EFLASHPGM; return 0; } /* erases a flash block at the given address */ /* we have to break this up in two erases at 16 bit aligned addresses * (if necessary) */ static int flash_erase_intel16(u32 *addr) { int result; u16 *addr16 = (u16*)addr; /* erase first block */ result = do_erase(addr16); if(result != 0) return result; addr16++; /* if the second address is not erased, also erase it */ if(*addr16 != 0xffff) result = do_erase(addr16); if(result != 0) return result; return 0; } /* write a flash block at a given location */ /* this has to be broken up into two consectutive 16 bit writes */ static int flash_write_intel16(u32 *dst, const u32* src) { u16 *dst16 = (u16 *)dst; u16 *src16 = (u16 *)src; int result; result = do_write(dst16, src16); if(result != 0) return result; dst16++; src16++; result = do_write(dst16, src16); if(result != 0) return result; return 0; } /* flash driver structure */ flash_driver_t intel16_flash_driver = { flash_erase: flash_erase_intel16, flash_write: flash_write_intel16, }; --- NEW FILE: intel32.c --- /* * intel32.c: Intel 32 bit (2x 16 bit) flash driver * * Copyright (C) 2001 Erik Mouw (J.A...@it...) * Copyright (C) 1999 Jan-Derk Bakker (J.D...@it...) * * 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 * */ #ident "$Id: intel32.c,v 1.1 2001/10/21 21:35:11 erikm Exp $" #ifdef HAVE_CONFIG_H # include <blob/config.h> #endif #include <blob/errno.h> #include <blob/flash.h> #include <blob/util.h> /* flash commands for two 16 bit intel flash chips */ #define READ_ARRAY 0x00FF00FF #define ERASE_SETUP 0x00200020 #define ERASE_CONFIRM 0x00D000D0 #define PGM_SETUP 0x00400040 #define STATUS_READ 0x00700070 #define STATUS_CLEAR 0x00500050 #define STATUS_BUSY 0x00800080 #define STATUS_ERASE_ERR 0x00200020 #define STATUS_PGM_ERR 0x00100010 /* erases a flash block at the given address */ static int flash_erase_intel32(u32 *addr) { u32 result; /* prepare for erase */ *addr = data_to_flash(ERASE_SETUP); barrier(); /* erase block */ *addr = data_to_flash(ERASE_CONFIRM); barrier(); /* status check */ do { *addr = data_to_flash(STATUS_READ); barrier(); result = data_from_flash(*addr); barrier(); } while((~result & STATUS_BUSY) != 0); /* put flash back into Read Array mode */ *addr = data_to_flash(READ_ARRAY); barrier(); if((result & STATUS_ERASE_ERR) != 0) return -EFLASHERASE; return 0; } /* write a flash block at a given location */ static int flash_write_intel32(u32 *dst, const u32* src) { u32 result; /* setup flash for writing */ *dst = data_to_flash(PGM_SETUP); barrier(); /* write data */ *dst = *src; barrier(); /* status check */ do { *dst = data_to_flash(STATUS_READ); barrier(); result = data_from_flash(*dst); barrier(); } while((~result & STATUS_BUSY) != 0); /* put flash back into Read Array mode */ *dst = data_to_flash(READ_ARRAY); barrier(); if(((result & STATUS_PGM_ERR) != 0) || (*dst != *src)) return -EFLASHPGM; return 0; } /* flash driver structure */ flash_driver_t intel32_flash_driver = { flash_erase: flash_erase_intel32, flash_write: flash_write_intel32, }; --- NEW FILE: amd32.c --- /* * amd32.c: AMD 32 bit (2x 16 bit) flash driver * * Copyright (C) 2001 Erik Mouw (J.A...@it...) * Copyright (C) 2001 Russ Dill (Rus...@as...) * * 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 * */ #ident "$Id: amd32.c,v 1.1 2001/10/21 21:35:11 erikm Exp $" #ifdef HAVE_CONFIG_H # include <blob/config.h> #endif #include <blob/errno.h> #include <blob/flash.h> #include <blob/util.h> /* flash commands for two 16 bit AMD flash chips */ #define READ_ARRAY 0x00F000F0 #define UNLOCK1 0x00AA00AA #define UNLOCK2 0x00550055 #define ERASE_SETUP 0x00800080 #define ERASE_CONFIRM 0x00300030 #define PGM_SETUP 0x00A000A0 #define UNLOCK_BYPASS 0x00200020 #define FLASH_ADDR1 (0x00000555 << 2) #define FLASH_ADDR2 (0x000002AA << 2) #define ERASE_DONE 0x00800080 #define RDY_MASK 0x00800080 #define STATUS_PGM_ERR 0x00200020 #define STATUS_ERASE_ERR 0x00000001 #define READY 1 #define ERR 2 #warning "Please check AMD flash code" static int flash_erase_amd32(u32 *addr) { u32 result; int chip1, chip2; /* prepare for erase */ *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1); barrier(); *(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2); barrier(); *(u32 *)FLASH_ADDR1 = data_to_flash(ERASE_SETUP); barrier(); /* erase command */ *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1); barrier(); *(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2); barrier(); *addr = data_to_flash(ERASE_CONFIRM); /* I just can't find clean ways of dealing with this flash... * The error bit is a *set* bit, so if its read, and bit 7 is 0, * but bit 5 is 1, its an error, however, after these status reads * are done, erased flash goes to 0xff...sooo...each chip has to * be caught where the bits are the status bits -- Russ */ /* Russ, why don't you do this like the LART does? Just check * the status of chips with a single compare. -- Erik */ chip1 = chip2 = 0; do { result = data_from_flash(*addr); barrier(); if (!chip1 && (result & 0xFFFF) & ERASE_DONE) chip1 = READY; if (!chip1 && (result & 0xFFFF) & STATUS_PGM_ERR) chip1 = ERR; if (!chip2 && (result >> 16) & ERASE_DONE) chip2 = READY; if (!chip2 && (result >> 16) & STATUS_PGM_ERR) chip2 = ERR; } while(!chip1 || !chip2); /* put flash back into Read Array mode */ *(u32 *)FLASH_ADDR1 = data_to_flash(READ_ARRAY); barrier(); if (chip1 == ERR || chip2 == ERR) return -EFLASHERASE; return 0; } static int flash_write_amd32(u32 *dst, const u32* src) { u32 result; int chip1, chip2; *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1); barrier(); *(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2); barrier(); *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK_BYPASS); barrier(); *dst = data_to_flash(PGM_SETUP); barrier(); *dst = *src; barrier(); /* This is a pretty similar situation to the erasing status below * Bit 7 is ~(data bit 7) until the flash is complete. If bit 5 * gets set before this happens, there is an error, but this could * happen near the clock edge, and bit 5 could be the actual data * before bit 7 changes, so we have to read again. -- Russ */ chip1 = chip2 = 0; do { result = data_from_flash(*dst); barrier(); if (!chip1 && ((result & 0x80) == (*src & 0x80))) chip1 = READY; if (!chip1 && ((result & 0xFFFF) & STATUS_PGM_ERR)) { result = data_from_flash(*dst); barrier(); if ((result & 0x80) == (*src & 0x80)) chip1 = READY; else chip1 = ERR; } if (!chip2 && ((result & (0x80 << 16)) == (*src & (0x80 << 16)))) chip2 = READY; if (!chip2 && ((result >> 16) & STATUS_PGM_ERR)) { result = data_from_flash(*dst); barrier(); if ((result & (0x80 << 16)) == (*src & (0x80 << 16))) chip2 = READY; else chip2 = ERR; } } while (!chip1 || !chip2); *(u32 *)FLASH_ADDR1 = data_to_flash(READ_ARRAY); barrier(); if (chip1 == ERR || chip2 == ERR || *dst != *src) return -EFLASHPGM; return 0; } /* flash driver structure */ flash_driver_t amd32_flash_driver = { flash_erase: flash_erase_amd32, flash_write: flash_write_amd32, }; --- NEW FILE: nullflash.c --- /* * nullflash.c: NULL flash driver * * Copyright (C) 2001 Erik Mouw (J.A...@it...) * * 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 * */ #ident "$Id: nullflash.c,v 1.1 2001/10/21 21:35:11 erikm Exp $" #ifdef HAVE_CONFIG_H # include <blob/config.h> #endif #include <blob/errno.h> #include <blob/flash.h> #include <blob/util.h> static int flash_erase_null(u32 *addr) { #ifdef BLOB_DEBUG printerrprefix(); SerialOutputString("No flash_erase() function\n"); #endif return -EFLASHERASE; } static int flash_write_null(u32 *dst, const u32* src) { #ifdef BLOB_DEBUG printerrprefix(); SerialOutputString("No flash_write() function\n"); #endif return -EFLASHPGM; } /* flash driver structure */ flash_driver_t null_flash_driver = { flash_erase: flash_erase_null, flash_write: flash_write_null, }; |