Fix up parse word so that it can correctly handle empty arguments and (encode-bootpat...
[openbios.git] / utils / devbios / programming.c
blobe1b35a34b2bbf4535ae4305e5862b9d4d932000d
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.
10 * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org>
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.
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.
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
27 // <-- C++ style comments are for experimental comments only.
28 // They will disappear as soon as I fixed all the stuff.
30 /* #define DEBUG_PROBING */
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
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>
48 #include "bios.h"
49 #include "pcisets.h"
50 #include "flashchips.h"
51 #include "programming.h"
53 struct flashdevice flashdevices[BIOS_MAXDEV];
54 int flashcount;
57 * ******************************************
59 * flashchip handling
61 * ******************************************
65 void flash_command (unsigned char *addr, unsigned char command)
66 #if 1
68 flash_writeb(addr, 0x5555, 0xaa);
69 flash_writeb(addr, 0x2AAA, 0x55);
70 flash_writeb(addr, 0x5555, command);
72 void fwh_flash_command(unsigned char *addr, unsigned char command)
73 #endif
75 flash_writeb(addr, 0x75555, 0xaa);
76 flash_writeb(addr, 0x72aaa, 0x55);
77 flash_writeb(addr, 0x75555, command);
80 #define CFLASH flashdevices[flashcount]
81 int flash_probe_address(void *address)
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
90 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
91 save_flags(flags);
92 #endif
93 spin_lock_irqsave(&bios_lock, flags);
95 testflash= (flash_readb(address, 0))+(flash_readb(address, 1)<<8);
97 /* 1st method: Intel, Atmel listen to this.. */
99 flash_command(address, 0x90);
100 udelay(20);
102 flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8);
104 #ifdef DEBUG_PROBING
105 printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n",
106 testflash, flash_id);
107 #endif
109 /* 2nd method: Winbond (I think this is Jedec standard) */
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);
118 flash_command(address, 0x80);
119 flash_command(address, 0x60);
120 udelay(20);
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
129 /* 3rd Method: Some Winbonds seem to want this */
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);
138 flash_command(address, 0x80);
139 flash_command(address, 0x20);
140 udelay(20);
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
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
153 printk(KERN_INFO "BIOS: Eon flash device detected\n");
154 flash_id=(flash_readb(address, 0x1))+(flash_readb(address, 0x101)<<8);
157 flash_command(address, 0xf0);
158 udelay(20);
160 spin_unlock_irqrestore(&bios_lock, flags);
162 if (flash_id==testflash) return 0; /* Nothing found :-( */
164 while (flashchips[flashnum].id!=0) {
165 if (flash_id==flashchips[flashnum].id)
166 break;
167 flashnum++;
170 while (manufacturers[manufnum].id!=0) {
171 if ((flash_id&0xff)==manufacturers[manufnum].id)
172 break;
173 manufnum++;
176 if (flashchips[flashnum].id) {
177 while (flashchips[flashnum].sectors[sectors]<flashchips[flashnum].size)
178 sectors++;
181 if (flashcount >= BIOS_MAXDEV) {
182 printk(KERN_DEBUG "BIOS: Too many flash devices found.\n");
183 return -1;
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;
194 return 1;
197 void flash_probe_area(unsigned long romaddr, unsigned long romsize,
198 int map_always)
200 unsigned long probeaddr;
201 unsigned char *mapped;
203 mapped=ioremap(romaddr, romsize);
205 devices[flashdevices[currflash].idx].activate();
207 probeaddr=(unsigned long)mapped;
209 while ( probeaddr < (unsigned long)mapped + romsize - 0x5555 ) {
210 if ( flash_probe_address ((void *)probeaddr) != 1) {
211 probeaddr += 4*1024;
212 continue;
215 CFLASH.offset = probeaddr-(unsigned long)mapped;
216 CFLASH.mapped = (unsigned long)mapped;
217 CFLASH.physical = romaddr+CFLASH.offset;
219 printk( KERN_INFO "BIOS: flash device with size "
220 "%dk (ID 0x%04x) found.\n",
221 CFLASH.size >> 10, CFLASH.id);
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);
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)
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--;
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
254 /* We might want to always map the memory
255 * region in certain cases
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;
275 /* We found nothing in this area, so let's unmap it again */
277 if (flashcount && flashdevices[flashcount-1].mapped != (unsigned long)mapped)
278 iounmap(mapped);
280 devices[flashdevices[currflash].idx].deactivate();
283 #undef CFLASH
285 void flash_program (unsigned char *addr)
287 flash_command(addr, 0xa0);
290 void flash_program_atmel (unsigned char *addr)
292 flash_command(addr, 0x80);
293 flash_command(addr, 0x20);
296 int flash_erase (unsigned char *addr, unsigned int flashnum)
298 flash_command(addr, 0x80);
299 flash_command(addr, 0x10);
300 udelay(80);
301 return flash_ready_toggle(addr, 0);
304 int flash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec)
306 unsigned int sector;
308 if (!(flashchips[flashnum].flags & f_slow_sector_erase)) {
309 flash_command(addr, 0x80);
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);
319 for (sector=startsec; sector <= endsec; sector++) {
320 flash_writeb (addr, flashchips[flashnum].sectors[sector]*1024, 0x30);
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
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);
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
357 return 0;
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.
369 int flash_ready_toggle (unsigned char *addr, unsigned int offset)
371 unsigned long int timeout=0;
372 unsigned char oldflag, flag;
373 int loop=1;
375 oldflag=flash_readb(addr, offset) & 0x40;
377 while (loop && (timeout<0x7fffffff)) {
378 flag=flash_readb(addr, offset) & 0x40;
380 if (flag == oldflag)
381 loop=0;
383 oldflag=flag;
384 timeout++;
387 if (loop) {
388 printk(KERN_DEBUG "BIOS: operation timed out (Toggle)\n");
389 return 1;
392 return 0;
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
401 int flash_ready_poll (unsigned char *addr, unsigned int offset, unsigned char data)
403 unsigned long int timeout=0;
404 unsigned char flag;
406 flag=flash_readb(addr, offset);
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;
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;
421 if ((flag & 0x80) == ( data & 0x80)) {
422 flag=flash_readb(addr, offset);
425 #ifdef DBGTIMEOUT
426 printk(KERN_DEBUG "BIOS: Timeout value (EOT Polling) %ld\n",timeout);
427 #endif
429 flag=flash_readb(addr, offset);
430 if ( ( flag & 0x80 ) == ( data & 0x80 ) ) return 0; else return 1;
435 void iflash_program_byte (unsigned char *addr, unsigned int offset, unsigned char data)
437 unsigned long int timeout=0;
438 unsigned char flag;
440 flash_writeb (addr, offset, 0x40);
441 flash_writeb (addr, offset, data);
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;
451 } while ((flag&0x80) != 0x80);
453 #ifdef DBGTIMEOUT
454 printk (KERN_DEBUG"BIOS: Timeout value (Intel byte program) %ld\n",timeout);
455 #endif
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");
462 flash_writeb (addr, offset, 0xff);
467 int iflash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec)
469 unsigned long int timeout;
470 unsigned int sector, offset=0;
471 unsigned char flag;
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);
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;
486 } while ((flag&0x80) != 0x80);
488 #ifdef DBGTIMEOUT
489 printk (KERN_DEBUG "BIOS: Timeout value (Intel sector erase) %ld\n",timeout);
490 #endif
492 if (flag&0x28) {
493 flash_writeb (addr, offset, 0x50);
494 flash_writeb (addr, offset, 0xff);
495 return 1; /* Error! */
499 flash_writeb (addr, offset, 0xff);
500 return 0;
505 unsigned char flash_readb(unsigned char *addr, unsigned int offset)
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;
516 #endif
517 return readb(addr+offset);
522 void flash_writeb(unsigned char *addr, unsigned int offset, unsigned char data)
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;
533 #endif
535 printk(KERN_DEBUG "BIOS: writing 0x%02x to 0x%lx+0x%x\n",
536 data,bios,offset);
538 writeb(data,addr+offset);