|
|
1.1 ! root 1: /* ! 2: * OpenBIOS - free your system! ! 3: * ( firmware/flash device driver for Linux ) ! 4: * ! 5: * programming.c - flash device programming and probing algorithms. ! 6: * ! 7: * This program is part of a free implementation of the IEEE 1275-1994 ! 8: * Standard for Boot (Initialization Configuration) Firmware. ! 9: * ! 10: * Copyright (C) 1998-2004 Stefan Reinauer, <[email protected]> ! 11: * ! 12: * This program is free software; you can redistribute it and/or modify ! 13: * it under the terms of the GNU General Public License as published by ! 14: * the Free Software Foundation; version 2 of the License. ! 15: * ! 16: * This program is distributed in the hope that it will be useful, ! 17: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 18: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 19: * GNU General Public License for more details. ! 20: * ! 21: * You should have received a copy of the GNU General Public License ! 22: * along with this program; if not, write to the Free Software ! 23: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA ! 24: * ! 25: */ ! 26: ! 27: // <-- C++ style comments are for experimental comments only. ! 28: // They will disappear as soon as I fixed all the stuff. ! 29: ! 30: /* #define DEBUG_PROBING */ ! 31: ! 32: #include <linux/config.h> ! 33: #include <linux/version.h> ! 34: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && defined(MODVERSIONS) ! 35: #include <linux/modversions.h> ! 36: #endif ! 37: ! 38: #include <linux/pci.h> ! 39: #include <linux/errno.h> ! 40: #include <linux/types.h> ! 41: #include <linux/vmalloc.h> ! 42: #include <linux/delay.h> ! 43: #include <linux/spinlock.h> ! 44: #include <asm/io.h> ! 45: #include <asm/delay.h> ! 46: #include <asm/uaccess.h> ! 47: ! 48: #include "bios.h" ! 49: #include "pcisets.h" ! 50: #include "flashchips.h" ! 51: #include "programming.h" ! 52: ! 53: struct flashdevice flashdevices[BIOS_MAXDEV]; ! 54: int flashcount; ! 55: ! 56: /* ! 57: * ****************************************** ! 58: * ! 59: * flashchip handling ! 60: * ! 61: * ****************************************** ! 62: */ ! 63: ! 64: ! 65: void flash_command (unsigned char *addr, unsigned char command) ! 66: #if 1 ! 67: { ! 68: flash_writeb(addr, 0x5555, 0xaa); ! 69: flash_writeb(addr, 0x2AAA, 0x55); ! 70: flash_writeb(addr, 0x5555, command); ! 71: } ! 72: void fwh_flash_command(unsigned char *addr, unsigned char command) ! 73: #endif ! 74: { ! 75: flash_writeb(addr, 0x75555, 0xaa); ! 76: flash_writeb(addr, 0x72aaa, 0x55); ! 77: flash_writeb(addr, 0x75555, command); ! 78: } ! 79: ! 80: #define CFLASH flashdevices[flashcount] ! 81: int flash_probe_address(void *address) ! 82: { ! 83: int flashnum=0, manufnum=0, sectors=0; ! 84: unsigned short flash_id, testflash; ! 85: unsigned long flags; ! 86: #ifdef DEBUG_PROBING ! 87: printk( KERN_DEBUG "BIOS: Probing for flash chip @0x%08lx\n", (unsigned long) address); ! 88: #endif ! 89: ! 90: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ! 91: save_flags(flags); ! 92: #endif ! 93: spin_lock_irqsave(&bios_lock, flags); ! 94: ! 95: testflash= (flash_readb(address, 0))+(flash_readb(address, 1)<<8); ! 96: ! 97: /* 1st method: Intel, Atmel listen to this.. */ ! 98: ! 99: flash_command(address, 0x90); ! 100: udelay(20); ! 101: ! 102: flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8); ! 103: ! 104: #ifdef DEBUG_PROBING ! 105: printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n", ! 106: testflash, flash_id); ! 107: #endif ! 108: ! 109: /* 2nd method: Winbond (I think this is Jedec standard) */ ! 110: ! 111: if (flash_id==testflash) { ! 112: #ifdef DEBUG_PROBING ! 113: printk (KERN_DEBUG "BIOS: Trying 2nd ID method.\n"); ! 114: #endif ! 115: flash_command(address, 0xf0); /* Reset */ ! 116: udelay(20); ! 117: ! 118: flash_command(address, 0x80); ! 119: flash_command(address, 0x60); ! 120: udelay(20); ! 121: ! 122: flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8); ! 123: #ifdef DEBUG_PROBING ! 124: printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n", ! 125: testflash, flash_id); ! 126: #endif ! 127: } ! 128: ! 129: /* 3rd Method: Some Winbonds seem to want this */ ! 130: ! 131: if (flash_id==testflash) { ! 132: #ifdef DEBUG_PROBING ! 133: printk (KERN_DEBUG "BIOS: Trying 3rd ID method.\n"); ! 134: #endif ! 135: flash_command(address, 0xf0); /* Reset again */ ! 136: udelay(20); ! 137: ! 138: flash_command(address, 0x80); ! 139: flash_command(address, 0x20); ! 140: udelay(20); ! 141: ! 142: flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8); ! 143: #ifdef DEBUG_PROBING ! 144: printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n", ! 145: testflash, flash_id); ! 146: #endif ! 147: } ! 148: ! 149: if (flash_id==0x7f7f && flash_readb(address, 0x100)==0x1c) { ! 150: /* We have an Eon flashchip. They keep their ! 151: * device id at 0x101 instead of 0x1 ! 152: */ ! 153: printk(KERN_INFO "BIOS: Eon flash device detected\n"); ! 154: flash_id=(flash_readb(address, 0x1))+(flash_readb(address, 0x101)<<8); ! 155: } ! 156: ! 157: flash_command(address, 0xf0); ! 158: udelay(20); ! 159: ! 160: spin_unlock_irqrestore(&bios_lock, flags); ! 161: ! 162: if (flash_id==testflash) return 0; /* Nothing found :-( */ ! 163: ! 164: while (flashchips[flashnum].id!=0) { ! 165: if (flash_id==flashchips[flashnum].id) ! 166: break; ! 167: flashnum++; ! 168: } ! 169: ! 170: while (manufacturers[manufnum].id!=0) { ! 171: if ((flash_id&0xff)==manufacturers[manufnum].id) ! 172: break; ! 173: manufnum++; ! 174: } ! 175: ! 176: if (flashchips[flashnum].id) { ! 177: while (flashchips[flashnum].sectors[sectors]<flashchips[flashnum].size) ! 178: sectors++; ! 179: } ! 180: ! 181: if (flashcount >= BIOS_MAXDEV) { ! 182: printk(KERN_DEBUG "BIOS: Too many flash devices found.\n"); ! 183: return -1; ! 184: } ! 185: ! 186: CFLASH.flashnum = flashnum; ! 187: CFLASH.manufnum = manufnum; ! 188: CFLASH.id = flash_id; ! 189: CFLASH.size = (flashchips[flashnum].size<<10); ! 190: CFLASH.sectors = sectors; ! 191: CFLASH.open_mode= 0; ! 192: CFLASH.open_cnt = 0; ! 193: ! 194: return 1; ! 195: } ! 196: ! 197: void flash_probe_area(unsigned long romaddr, unsigned long romsize, ! 198: int map_always) ! 199: { ! 200: unsigned long probeaddr; ! 201: unsigned char *mapped; ! 202: ! 203: mapped=ioremap(romaddr, romsize); ! 204: ! 205: devices[flashdevices[currflash].idx].activate(); ! 206: ! 207: probeaddr=(unsigned long)mapped; ! 208: ! 209: while ( probeaddr < (unsigned long)mapped + romsize - 0x5555 ) { ! 210: if ( flash_probe_address ((void *)probeaddr) != 1) { ! 211: probeaddr += 4*1024; ! 212: continue; ! 213: } ! 214: ! 215: CFLASH.offset = probeaddr-(unsigned long)mapped; ! 216: CFLASH.mapped = (unsigned long)mapped; ! 217: CFLASH.physical = romaddr+CFLASH.offset; ! 218: ! 219: printk( KERN_INFO "BIOS: flash device with size " ! 220: "%dk (ID 0x%04x) found.\n", ! 221: CFLASH.size >> 10, CFLASH.id); ! 222: ! 223: printk( KERN_INFO "BIOS: physical address " ! 224: "0x%08lx (va=0x%08lx+0x%lx).\n", ! 225: CFLASH.physical, (unsigned long)CFLASH.mapped, ! 226: CFLASH.offset); ! 227: ! 228: if (flashchips[CFLASH.flashnum].flags&f_fwh_compl) { ! 229: unsigned long t_lk; ! 230: unsigned int i=7; ! 231: printk(KERN_INFO "BIOS: FWH compliant " ! 232: "chip detected.\n"); ! 233: for (t_lk=0xffb80002; t_lk<=0xffbf0002; t_lk+=0x10000) ! 234: { ! 235: printk(KERN_INFO "Lock register %d " ! 236: "(0x%08lx): 0x%x\n", ! 237: i, t_lk, (unsigned int) ! 238: (readb(phys_to_virt(t_lk)))); ! 239: i--; ! 240: } ! 241: } ! 242: flashcount++; ! 243: currflash++; ! 244: #ifdef MULTIPLE_FLASH ! 245: probeaddr += flashdevices[flashcount-1].size; ! 246: flashdevices[flashcount].mapped=flashdevices[flashcount-1].mapped; ! 247: flashdevices[flashcount].data=flashdevices[flashcount-1].data; ! 248: continue; ! 249: #else ! 250: break; ! 251: #endif ! 252: } ! 253: ! 254: /* We might want to always map the memory ! 255: * region in certain cases ! 256: */ ! 257: ! 258: if (map_always) { ! 259: CFLASH.flashnum = 0; ! 260: CFLASH.manufnum = 0; ! 261: CFLASH.id = 0; ! 262: CFLASH.size = romsize; ! 263: CFLASH.sectors = 0; ! 264: CFLASH.open_mode= 0; ! 265: CFLASH.open_cnt = 0; ! 266: CFLASH.offset = 0; ! 267: CFLASH.mapped = (unsigned long)mapped; ! 268: CFLASH.physical = romaddr; ! 269: printk( KERN_INFO "BIOS: rom device with size " ! 270: "%dk registered.\n", CFLASH.size >> 10); ! 271: flashcount++; currflash++; ! 272: return; ! 273: } ! 274: ! 275: /* We found nothing in this area, so let's unmap it again */ ! 276: ! 277: if (flashcount && flashdevices[flashcount-1].mapped != (unsigned long)mapped) ! 278: iounmap(mapped); ! 279: ! 280: devices[flashdevices[currflash].idx].deactivate(); ! 281: } ! 282: ! 283: #undef CFLASH ! 284: ! 285: void flash_program (unsigned char *addr) ! 286: { ! 287: flash_command(addr, 0xa0); ! 288: } ! 289: ! 290: void flash_program_atmel (unsigned char *addr) ! 291: { ! 292: flash_command(addr, 0x80); ! 293: flash_command(addr, 0x20); ! 294: } ! 295: ! 296: int flash_erase (unsigned char *addr, unsigned int flashnum) ! 297: { ! 298: flash_command(addr, 0x80); ! 299: flash_command(addr, 0x10); ! 300: udelay(80); ! 301: return flash_ready_toggle(addr, 0); ! 302: } ! 303: ! 304: int flash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec) ! 305: { ! 306: unsigned int sector; ! 307: ! 308: if (!(flashchips[flashnum].flags & f_slow_sector_erase)) { ! 309: flash_command(addr, 0x80); ! 310: ! 311: if (flashchips[flashnum].flags&f_fwh_compl) { ! 312: flash_writeb(addr, 0x75555,0xaa); ! 313: flash_writeb(addr, 0x72aaa,0x55); ! 314: } else { ! 315: flash_writeb(addr, 0x5555,0xaa); ! 316: flash_writeb(addr, 0x2aaa,0x55); ! 317: } ! 318: ! 319: for (sector=startsec; sector <= endsec; sector++) { ! 320: flash_writeb (addr, flashchips[flashnum].sectors[sector]*1024, 0x30); ! 321: } ! 322: ! 323: udelay(150); // 80 max normally, wait 150usec to be sure ! 324: #if 0 ! 325: if (flashchips[flashnum].flags&f_fwh_compl) ! 326: #endif ! 327: return flash_ready_toggle(addr, flashchips[flashnum].sectors[sector-1]*1024); ! 328: #if 0 ! 329: else ! 330: return flash_ready_poll(addr, flashchips[flashnum].sectors[sector-1]*1024, 0xff); ! 331: #endif ! 332: } ! 333: ! 334: /* sectors must be sent the sector erase command for every sector */ ! 335: for (sector=startsec; sector <= endsec; sector++) { ! 336: flash_command(addr, 0x80); ! 337: if (flashchips[flashnum].flags&f_fwh_compl) { ! 338: flash_writeb(addr, 0x75555,0xaa); ! 339: flash_writeb(addr, 0x72aaa,0x55); ! 340: } else { ! 341: flash_writeb(addr, 0x5555,0xaa); ! 342: flash_writeb(addr, 0x2aaa,0x55); ! 343: } ! 344: ! 345: flash_writeb(addr, flashchips[flashnum].sectors[sector]*1024, 0x30); ! 346: udelay(150); ! 347: #if 0 ! 348: if (flashchips[flashnum].flags&f_fwh_compl) ! 349: #endif ! 350: flash_ready_toggle(addr, flashchips[flashnum].sectors[sector] *1024); ! 351: #if 0 ! 352: else ! 353: flash_ready_poll(addr, flashchips[flashnum].sectors[sector]*1024, 0xff); ! 354: #endif ! 355: } ! 356: ! 357: return 0; ! 358: ! 359: } ! 360: ! 361: /* waiting for the end of programming/erasure by using the toggle method. ! 362: * As long as there is a programming procedure going on, bit 6 of the last ! 363: * written byte is toggling it's state with each consecutive read. ! 364: * The toggling stops as soon as the procedure is completed. ! 365: * This function returns 0 if everything is ok, 1 if an error occured ! 366: * while programming was in progress. ! 367: */ ! 368: ! 369: int flash_ready_toggle (unsigned char *addr, unsigned int offset) ! 370: { ! 371: unsigned long int timeout=0; ! 372: unsigned char oldflag, flag; ! 373: int loop=1; ! 374: ! 375: oldflag=flash_readb(addr, offset) & 0x40; ! 376: ! 377: while (loop && (timeout<0x7fffffff)) { ! 378: flag=flash_readb(addr, offset) & 0x40; ! 379: ! 380: if (flag == oldflag) ! 381: loop=0; ! 382: ! 383: oldflag=flag; ! 384: timeout++; ! 385: } ! 386: ! 387: if (loop) { ! 388: printk(KERN_DEBUG "BIOS: operation timed out (Toggle)\n"); ! 389: return 1; ! 390: } ! 391: ! 392: return 0; ! 393: } ! 394: ! 395: /* This functions is similar to the above one. While a programming ! 396: * procedure is going on, bit 7 of the last written data byte is ! 397: * inverted. When the procedure is completed, bit 7 contains the ! 398: * correct data value ! 399: */ ! 400: ! 401: int flash_ready_poll (unsigned char *addr, unsigned int offset, unsigned char data) ! 402: { ! 403: unsigned long int timeout=0; ! 404: unsigned char flag; ! 405: ! 406: flag=flash_readb(addr, offset); ! 407: ! 408: while ( ( flag & 0x80) != ( data & 0x80)) { ! 409: if ( ( flag & 0x80 ) == ( data & 0x80 ) ) { ! 410: #ifdef DBGTIMEOUT ! 411: printk(KERN_DEBUG "BIOS: Timeout value (EOT Polling) %ld\n",timeout); ! 412: #endif ! 413: return 0; ! 414: } ! 415: flag=flash_readb(addr, offset); ! 416: if (timeout++>12800) { // 10 times more than usual. ! 417: printk(KERN_ERR "BIOS: EOT Polling timed out at 0x%08x." ! 418: " Try again or increase max. timeout.\n",offset); ! 419: return 1; ! 420: } ! 421: if ((flag & 0x80) == ( data & 0x80)) { ! 422: flag=flash_readb(addr, offset); ! 423: } ! 424: } ! 425: #ifdef DBGTIMEOUT ! 426: printk(KERN_DEBUG "BIOS: Timeout value (EOT Polling) %ld\n",timeout); ! 427: #endif ! 428: ! 429: flag=flash_readb(addr, offset); ! 430: if ( ( flag & 0x80 ) == ( data & 0x80 ) ) return 0; else return 1; ! 431: } ! 432: ! 433: ! 434: ! 435: void iflash_program_byte (unsigned char *addr, unsigned int offset, unsigned char data) ! 436: { ! 437: unsigned long int timeout=0; ! 438: unsigned char flag; ! 439: ! 440: flash_writeb (addr, offset, 0x40); ! 441: flash_writeb (addr, offset, data); ! 442: ! 443: flash_writeb (addr, offset, 0x70); /* Read Status */ ! 444: do { ! 445: flag=flash_readb (addr, offset); ! 446: if (timeout++>100) { // usually 2 or 3 :-) ! 447: printk(KERN_ERR "BIOS: Intel programming timed out at" ! 448: "0x%08x. Try again or increase max. timeout.\n",offset); ! 449: return; ! 450: } ! 451: } while ((flag&0x80) != 0x80); ! 452: ! 453: #ifdef DBGTIMEOUT ! 454: printk (KERN_DEBUG"BIOS: Timeout value (Intel byte program) %ld\n",timeout); ! 455: #endif ! 456: ! 457: if (flag&0x18) { ! 458: flash_writeb (addr, offset, 0x50); /* Reset Status Register */ ! 459: printk (KERN_ERR "BIOS: Error occured, please repeat write operation. (intel)\n"); ! 460: } ! 461: ! 462: flash_writeb (addr, offset, 0xff); ! 463: } ! 464: ! 465: ! 466: ! 467: int iflash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec) ! 468: { ! 469: unsigned long int timeout; ! 470: unsigned int sector, offset=0; ! 471: unsigned char flag; ! 472: ! 473: for (sector=startsec; sector<=endsec; sector++) { ! 474: offset=(flashchips[flashnum].sectors[sector]*1024); ! 475: flash_writeb (addr, offset, 0x20); ! 476: flash_writeb (addr, offset, 0xd0); ! 477: ! 478: flash_writeb (addr, offset, 0x70); /* Read Status */ ! 479: timeout=0; ! 480: do { ! 481: flag=flash_readb (addr, offset); ! 482: if (timeout++>1440000) { // usually 144000 ! 483: printk(KERN_ERR "BIOS: Intel sector erase timed out at 0x%08x. Try again or increase max. timeout.\n",offset); ! 484: return 1; ! 485: } ! 486: } while ((flag&0x80) != 0x80); ! 487: ! 488: #ifdef DBGTIMEOUT ! 489: printk (KERN_DEBUG "BIOS: Timeout value (Intel sector erase) %ld\n",timeout); ! 490: #endif ! 491: ! 492: if (flag&0x28) { ! 493: flash_writeb (addr, offset, 0x50); ! 494: flash_writeb (addr, offset, 0xff); ! 495: return 1; /* Error! */ ! 496: } ! 497: } ! 498: ! 499: flash_writeb (addr, offset, 0xff); ! 500: return 0; ! 501: } ! 502: ! 503: ! 504: ! 505: unsigned char flash_readb(unsigned char *addr, unsigned int offset) ! 506: { ! 507: #if defined(__alpha__) ! 508: if (flashdevices[currflash].data==(void *)0xfff80000) { ! 509: if (offset<0x80000) ! 510: outb(0x00,0x800); ! 511: else { ! 512: outb(0x01, 0x800); ! 513: offset-=0x80000; ! 514: } ! 515: } ! 516: #endif ! 517: return readb(addr+offset); ! 518: } ! 519: ! 520: ! 521: ! 522: void flash_writeb(unsigned char *addr, unsigned int offset, unsigned char data) ! 523: { ! 524: #if defined(__alpha__) ! 525: if (flashdevices[currflash].data==(void *)0xfff80000) { ! 526: if (offset<0x80000) ! 527: outb(0x00,0x800); ! 528: else { ! 529: outb(0x01, 0x800); ! 530: offset-=0x80000; ! 531: } ! 532: } ! 533: #endif ! 534: /* ! 535: printk(KERN_DEBUG "BIOS: writing 0x%02x to 0x%lx+0x%x\n", ! 536: data,bios,offset); ! 537: */ ! 538: writeb(data,addr+offset); ! 539: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.