blob: e110f2a604e85d3123ac568932bc2186865e1e3e [file] [log] [blame]
ollie6a600992005-11-26 21:55:36 +00001/*
2 * flash rom utility: enable flash writes
3 *
4 * Copyright (C) 2000-2004 ???
5 * Copyright (C) 2005 coresystems GmbH <stepan@openbios.org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2
10 *
11 */
12
ollie5672ac62004-03-17 22:22:08 +000013#include <sys/io.h>
14#include <stdio.h>
15#include <pci/pci.h>
16#include <stdlib.h>
ollie6a600992005-11-26 21:55:36 +000017#include <stdint.h>
18#include <string.h>
19#include "lbtable.h"
20#include "debug.h"
ollie5672ac62004-03-17 22:22:08 +000021
stepancb140092006-03-31 11:26:55 +000022// We keep this for the others.
23static struct pci_access *pacc;
24
ollie5b621572004-03-20 16:46:10 +000025static int enable_flash_sis630(struct pci_dev *dev, char *name)
ollie5672ac62004-03-17 22:22:08 +000026{
27 char b;
28
29 /* get io privilege access PCI configuration space */
30 if (iopl(3) != 0) {
31 perror("Can not set io priviliage");
32 exit(1);
33 }
34
35 /* Enable 0xFFF8000~0xFFFF0000 decoding on SiS 540/630 */
36 outl(0x80000840, 0x0cf8);
37 b = inb(0x0cfc) | 0x0b;
38 outb(b, 0xcfc);
39 /* Flash write enable on SiS 540/630 */
40 outl(0x80000845, 0x0cf8);
41 b = inb(0x0cfd) | 0x40;
42 outb(b, 0xcfd);
43
44 /* The same thing on SiS 950 SuperIO side */
45 outb(0x87, 0x2e);
46 outb(0x01, 0x2e);
47 outb(0x55, 0x2e);
48 outb(0x55, 0x2e);
49
50 if (inb(0x2f) != 0x87) {
51 outb(0x87, 0x4e);
52 outb(0x01, 0x4e);
53 outb(0x55, 0x4e);
54 outb(0xaa, 0x4e);
55 if (inb(0x4f) != 0x87) {
56 printf("Can not access SiS 950\n");
57 return -1;
58 }
59 outb(0x24, 0x4e);
60 b = inb(0x4f) | 0xfc;
61 outb(0x24, 0x4e);
62 outb(b, 0x4f);
63 outb(0x02, 0x4e);
ollie5b621572004-03-20 16:46:10 +000064 outb(0x02, 0x4f);
ollie5672ac62004-03-17 22:22:08 +000065 }
66
67 outb(0x24, 0x2e);
68 printf("2f is %#x\n", inb(0x2f));
69 b = inb(0x2f) | 0xfc;
70 outb(0x24, 0x2e);
71 outb(b, 0x2f);
72
73 outb(0x02, 0x2e);
74 outb(0x02, 0x2f);
75
76 return 0;
77}
78
79static int enable_flash_e7500(struct pci_dev *dev, char *name)
80{
81 /* register 4e.b gets or'ed with one */
ollie6a600992005-11-26 21:55:36 +000082 uint8_t old, new;
ollie5672ac62004-03-17 22:22:08 +000083 /* if it fails, it fails. There are so many variations of broken mobos
84 * that it is hard to argue that we should quit at this point.
85 */
ollie5b621572004-03-20 16:46:10 +000086
ollie5672ac62004-03-17 22:22:08 +000087 old = pci_read_byte(dev, 0x4e);
88
89 new = old | 1;
90
91 if (new == old)
92 return 0;
93
94 pci_write_byte(dev, 0x4e, new);
95
96 if (pci_read_byte(dev, 0x4e) != new) {
ollief1845bd2004-03-27 00:18:15 +000097 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
98 0x4e, new, name);
ollie5672ac62004-03-17 22:22:08 +000099 return -1;
100 }
101 return 0;
102}
103
stepancb140092006-03-31 11:26:55 +0000104enum {
105 ICH4_BIOS_CNTL = 0x4e,
106 /* see page 375 of "Intel ICH7 External Design Specification"
107 * http://download.intel.com/design/chipsets/datashts/30701302.pdf */
108 ICH7_BIOS_CNTL = 0xdc,
109};
110static int enable_flash_ich(struct pci_dev *dev, char *name, int bios_cntl)
rminnich1bcc2b22004-09-28 20:09:06 +0000111{
112 /* register 4e.b gets or'ed with one */
ollie6a600992005-11-26 21:55:36 +0000113 uint8_t old, new;
rminnich1bcc2b22004-09-28 20:09:06 +0000114 /* if it fails, it fails. There are so many variations of broken mobos
115 * that it is hard to argue that we should quit at this point.
116 */
117
stepancb140092006-03-31 11:26:55 +0000118 old = pci_read_byte(dev, bios_cntl);
rminnich1bcc2b22004-09-28 20:09:06 +0000119
120 new = old | 1;
121
122 if (new == old)
123 return 0;
124
stepancb140092006-03-31 11:26:55 +0000125 pci_write_byte(dev, bios_cntl, new);
rminnich1bcc2b22004-09-28 20:09:06 +0000126
stepancb140092006-03-31 11:26:55 +0000127 if (pci_read_byte(dev, bios_cntl) != new) {
rminnich1bcc2b22004-09-28 20:09:06 +0000128 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
stepancb140092006-03-31 11:26:55 +0000129 bios_cntl, new, name);
rminnich1bcc2b22004-09-28 20:09:06 +0000130 return -1;
131 }
132 return 0;
133}
134
stepancb140092006-03-31 11:26:55 +0000135static int enable_flash_ich4(struct pci_dev *dev, char *name)
136{
137 return enable_flash_ich(dev, name, ICH4_BIOS_CNTL);
138}
139
140static int enable_flash_ich7(struct pci_dev *dev, char *name)
141{
142 return enable_flash_ich(dev, name, ICH7_BIOS_CNTL);
143}
144
ollie5672ac62004-03-17 22:22:08 +0000145static int enable_flash_vt8235(struct pci_dev *dev, char *name)
146{
ollie6a600992005-11-26 21:55:36 +0000147 uint8_t old, new, val;
ollie5672ac62004-03-17 22:22:08 +0000148 unsigned int base;
149 int ok;
ollie5b621572004-03-20 16:46:10 +0000150
ollie5672ac62004-03-17 22:22:08 +0000151 /* get io privilege access PCI configuration space */
152 if (iopl(3) != 0) {
153 perror("Can not set io priviliage");
154 exit(1);
155 }
156
157 old = pci_read_byte(dev, 0x40);
158
159 new = old | 0x10;
160
161 if (new == old)
162 return 0;
163
164 ok = pci_write_byte(dev, 0x40, new);
165 if (ok != 0) {
ollief1845bd2004-03-27 00:18:15 +0000166 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
167 old, new, name);
ollie5672ac62004-03-17 22:22:08 +0000168 }
169
170 /* enable GPIO15 which is connected to write protect. */
ollief1845bd2004-03-27 00:18:15 +0000171 base = ((pci_read_byte(dev, 0x88) & 0x80) | pci_read_byte(dev, 0x89) << 8);
ollie5672ac62004-03-17 22:22:08 +0000172 val = inb(base + 0x4d);
173 val |= 0x80;
174 outb(val, base + 0x4d);
175
176 if (ok != 0) {
177 return -1;
178 } else {
179 return 0;
180 }
181}
182
183static int enable_flash_vt8231(struct pci_dev *dev, char *name)
184{
ollie6a600992005-11-26 21:55:36 +0000185 uint8_t val;
ollie5b621572004-03-20 16:46:10 +0000186
ollie5672ac62004-03-17 22:22:08 +0000187 val = pci_read_byte(dev, 0x40);
188 val |= 0x10;
189 pci_write_byte(dev, 0x40, val);
190
191 if (pci_read_byte(dev, 0x40) != val) {
ollief1845bd2004-03-27 00:18:15 +0000192 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
193 0x40, val, name);
ollie5672ac62004-03-17 22:22:08 +0000194 return -1;
195 }
196 return 0;
197}
198
199static int enable_flash_cs5530(struct pci_dev *dev, char *name)
200{
ollie6a600992005-11-26 21:55:36 +0000201 uint8_t new;
ollie5b621572004-03-20 16:46:10 +0000202
ollie5672ac62004-03-17 22:22:08 +0000203 pci_write_byte(dev, 0x52, 0xee);
204
205 new = pci_read_byte(dev, 0x52);
206
207 if (new != 0xee) {
ollief1845bd2004-03-27 00:18:15 +0000208 printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
209 0x52, new, name);
ollie5672ac62004-03-17 22:22:08 +0000210 return -1;
211 }
ollie6a600992005-11-26 21:55:36 +0000212
213 new = pci_read_byte(dev, 0x5b) | 0x20;
214 pci_write_byte(dev, 0x5b, new);
215
ollie5672ac62004-03-17 22:22:08 +0000216 return 0;
217}
218
ollie6a600992005-11-26 21:55:36 +0000219
ollie5672ac62004-03-17 22:22:08 +0000220static int enable_flash_sc1100(struct pci_dev *dev, char *name)
221{
ollie6a600992005-11-26 21:55:36 +0000222 uint8_t new;
ollie5b621572004-03-20 16:46:10 +0000223
ollie5672ac62004-03-17 22:22:08 +0000224 pci_write_byte(dev, 0x52, 0xee);
225
226 new = pci_read_byte(dev, 0x52);
227
228 if (new != 0xee) {
ollief1845bd2004-03-27 00:18:15 +0000229 printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
230 0x52, new, name);
ollie5672ac62004-03-17 22:22:08 +0000231 return -1;
232 }
233 return 0;
234}
235
236static int enable_flash_sis5595(struct pci_dev *dev, char *name)
237{
ollie6a600992005-11-26 21:55:36 +0000238 uint8_t new, newer;
ollie5b621572004-03-20 16:46:10 +0000239
ollie5672ac62004-03-17 22:22:08 +0000240 new = pci_read_byte(dev, 0x45);
241
242 /* clear bit 5 */
ollie5b621572004-03-20 16:46:10 +0000243 new &= (~0x20);
ollie5672ac62004-03-17 22:22:08 +0000244 /* set bit 2 */
245 new |= 0x4;
246
247 pci_write_byte(dev, 0x45, new);
248
249 newer = pci_read_byte(dev, 0x45);
250 if (newer != new) {
ollief1845bd2004-03-27 00:18:15 +0000251 printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
252 0x45, new, name);
ollie5672ac62004-03-17 22:22:08 +0000253 printf("Stuck at 0x%x\n", newer);
254 return -1;
255 }
256 return 0;
257}
258
ollie5b621572004-03-20 16:46:10 +0000259static int enable_flash_amd8111(struct pci_dev *dev, char *name)
260{
ollie5672ac62004-03-17 22:22:08 +0000261 /* register 4e.b gets or'ed with one */
ollie6a600992005-11-26 21:55:36 +0000262 uint8_t old, new;
ollie5672ac62004-03-17 22:22:08 +0000263 /* if it fails, it fails. There are so many variations of broken mobos
264 * that it is hard to argue that we should quit at this point.
265 */
266
olliefc9a03b2004-12-07 17:19:04 +0000267 /* enable decoding at 0xffb00000 to 0xffffffff */
ollie5672ac62004-03-17 22:22:08 +0000268 old = pci_read_byte(dev, 0x43);
olliefc9a03b2004-12-07 17:19:04 +0000269 new = old | 0xC0;
ollie5672ac62004-03-17 22:22:08 +0000270 if (new != old) {
271 pci_write_byte(dev, 0x43, new);
272 if (pci_read_byte(dev, 0x43) != new) {
ollief1845bd2004-03-27 00:18:15 +0000273 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
274 0x43, new, name);
ollie5672ac62004-03-17 22:22:08 +0000275 }
276 }
277
ollie5b621572004-03-20 16:46:10 +0000278 old = pci_read_byte(dev, 0x40);
ollie5672ac62004-03-17 22:22:08 +0000279 new = old | 0x01;
280 if (new == old)
281 return 0;
282 pci_write_byte(dev, 0x40, new);
283
284 if (pci_read_byte(dev, 0x40) != new) {
ollief1845bd2004-03-27 00:18:15 +0000285 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
286 0x40, new, name);
ollie5672ac62004-03-17 22:22:08 +0000287 return -1;
288 }
289 return 0;
290}
291
arch6a1225a2005-07-06 17:13:46 +0000292//By yhlu
293static int enable_flash_ck804(struct pci_dev *dev, char *name)
294{
295 /* register 4e.b gets or'ed with one */
ollie6a600992005-11-26 21:55:36 +0000296 uint8_t old, new;
arch6a1225a2005-07-06 17:13:46 +0000297 /* if it fails, it fails. There are so many variations of broken mobos
298 * that it is hard to argue that we should quit at this point.
299 */
300
301 //dump_pci_device(dev);
302
303 old = pci_read_byte(dev, 0x88);
304 new = old | 0xc0;
305 if (new != old) {
306 pci_write_byte(dev, 0x88, new);
307 if (pci_read_byte(dev, 0x88) != new) {
308 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
309 0x88, new, name);
310 }
311 }
312
313 old = pci_read_byte(dev, 0x6d);
314 new = old | 0x01;
315 if (new == old)
316 return 0;
317 pci_write_byte(dev, 0x6d, new);
318
319 if (pci_read_byte(dev, 0x6d) != new) {
320 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
321 0x6d, new, name);
322 return -1;
323 }
324 return 0;
325}
326
stepancb140092006-03-31 11:26:55 +0000327static int enable_flash_sb400(struct pci_dev *dev, char *name)
328{
329 uint8_t tmp;
330
331 struct pci_filter f;
332 struct pci_dev *smbusdev;
333
334 /* get io privilege access */
335 if (iopl(3) != 0) {
336 perror("Can not set io priviliage");
337 exit(1);
338 }
339
340 /* then look for the smbus device */
341 pci_filter_init((struct pci_access *) 0, &f);
342 f.vendor = 0x1002;
343 f.device = 0x4372;
344
345 for (smbusdev = pacc->devices; smbusdev; smbusdev = smbusdev->next) {
346 if (pci_filter_match(&f, smbusdev)) {
347 break;
348 }
349 }
350
351 if(!smbusdev) {
352 perror("smbus device not found. aborting\n");
353 exit(1);
354 }
355
356 // enable some smbus stuff
357 tmp=pci_read_byte(smbusdev, 0x79);
358 tmp|=0x01;
359 pci_write_byte(smbusdev, 0x79, tmp);
360
361 // change southbridge
362 tmp=pci_read_byte(dev, 0x48);
363 tmp|=0x21;
364 pci_write_byte(dev, 0x48, tmp);
365
366 // now become a bit silly.
367 tmp=inb(0xc6f);
368 outb(tmp,0xeb);
369 outb(tmp, 0xeb);
370 tmp|=0x40;
371 outb(tmp, 0xc6f);
372 outb(tmp, 0xeb);
373 outb(tmp, 0xeb);
374
375 return 0;
376}
377
ollie5672ac62004-03-17 22:22:08 +0000378typedef struct penable {
ollie5b621572004-03-20 16:46:10 +0000379 unsigned short vendor, device;
ollie5672ac62004-03-17 22:22:08 +0000380 char *name;
ollie5b621572004-03-20 16:46:10 +0000381 int (*doit) (struct pci_dev * dev, char *name);
ollie5672ac62004-03-17 22:22:08 +0000382} FLASH_ENABLE;
383
384static FLASH_ENABLE enables[] = {
ollie5b621572004-03-20 16:46:10 +0000385 {0x1039, 0x0630, "sis630", enable_flash_sis630},
386 {0x8086, 0x2480, "E7500", enable_flash_e7500},
rminnich1bcc2b22004-09-28 20:09:06 +0000387 {0x8086, 0x24c0, "ICH4", enable_flash_ich4},
stepana9750de2006-03-31 11:36:06 +0000388 {0x8086, 0x24cc, "ICH4-M", enable_flash_ich4},
rminnich6d3e1312006-02-24 17:10:10 +0000389 {0x8086, 0x24d0, "ICH5", enable_flash_ich4},
stepancb140092006-03-31 11:26:55 +0000390 {0x8086, 0x27b8, "ICH7", enable_flash_ich7},
ollie5b621572004-03-20 16:46:10 +0000391 {0x1106, 0x8231, "VT8231", enable_flash_vt8231},
392 {0x1106, 0x3177, "VT8235", enable_flash_vt8235},
393 {0x1078, 0x0100, "CS5530", enable_flash_cs5530},
394 {0x100b, 0x0510, "SC1100", enable_flash_sc1100},
ollie5672ac62004-03-17 22:22:08 +0000395 {0x1039, 0x0008, "SIS5595", enable_flash_sis5595},
396 {0x1022, 0x7468, "AMD8111", enable_flash_amd8111},
stepancb140092006-03-31 11:26:55 +0000397 // this fallthrough looks broken.
arch6a1225a2005-07-06 17:13:46 +0000398 {0x10de, 0x0050, "NVIDIA CK804", enable_flash_ck804}, // LPC
399 {0x10de, 0x0051, "NVIDIA CK804", enable_flash_ck804}, // Pro
400 {0x10de, 0x00d3, "NVIDIA CK804", enable_flash_ck804}, // Slave, should not be here, to fix known bug for A01.
stepan64cc2862006-07-31 23:37:17 +0000401 {0x10de, 0x0261, "NVIDIA C51", enable_flash_ck804},
stepancb140092006-03-31 11:26:55 +0000402 {0x1002, 0x4377, "ATI SB400", enable_flash_sb400}, // ATI Technologies Inc IXP SB400 PCI-ISA Bridge (rev 80)
ollie5672ac62004-03-17 22:22:08 +0000403};
ollie5b621572004-03-20 16:46:10 +0000404
ollie6a600992005-11-26 21:55:36 +0000405static int mbenable_island_aruma(void)
406{
stepancb140092006-03-31 11:26:55 +0000407#define EFIR 0x2e /* Extended function index register, either 0x2e or 0x4e */
408#define EFDR EFIR + 1 /* Extended function data register, one plus the index reg. */
ollie6a600992005-11-26 21:55:36 +0000409 char b;
stepancb140092006-03-31 11:26:55 +0000410
411/* Disable the flash write protect. The flash write protect is
412 * connected to the WinBond w83627hf GPIO 24.
413 */
ollie6a600992005-11-26 21:55:36 +0000414
415 /* get io privilege access winbond config space */
416 if (iopl(3) != 0) {
417 perror("Can not set io priviliage");
418 exit(1);
419 }
420
421 printf("Disabling mainboard flash write protection.\n");
422
423 outb(0x87, EFIR); // sequence to unlock extended functions
424 outb(0x87, EFIR);
425
426 outb(0x20, EFIR); // SIO device ID register
427 b = inb(EFDR);
428 printf_debug("W83627HF device ID = 0x%x\n",b);
429
430 if (b != 0x52) {
431 perror("Incorrect device ID, aborting write protect disable\n");
432 exit(1);
433 }
434
435 outb(0x2b, EFIR); // GPIO multiplexed pin reg.
436 b = inb(EFDR) | 0x10;
437 outb(0x2b, EFIR);
438 outb(b, EFDR); // select GPIO 24 instead of WDTO
439
440 outb(0x7, EFIR); // logical device select
441 outb(0x8, EFDR); // point to device 8, GPIO port 2
442
443 outb(0x30, EFIR); // logic device activation control
444 outb(0x1, EFDR); // activate
445
446 outb(0xf0, EFIR); // GPIO 20-27 I/O selection register
447 b = inb(EFDR) & ~0x10;
448 outb(0xf0, EFIR);
449 outb(b, EFDR); // set GPIO 24 as an output
450
451 outb(0xf1, EFIR); // GPIO 20-27 data register
452 b = inb(EFDR) | 0x10;
453 outb(0xf1, EFIR);
454 outb(b, EFDR); // set GPIO 24
455
456 outb(0xaa, EFIR); // command to exit extended functions
457
458 return 0;
459}
460
461typedef struct mbenable {
462 char *vendor, *part;
463 int (*doit)(void);
464} MAINBOARD_ENABLE;
465
466static MAINBOARD_ENABLE mbenables[] = {
467 { "ISLAND", "ARUMA", mbenable_island_aruma },
468};
469
ollie5672ac62004-03-17 22:22:08 +0000470int enable_flash_write()
471{
472 int i;
ollie5672ac62004-03-17 22:22:08 +0000473 struct pci_dev *dev = 0;
474 FLASH_ENABLE *enable = 0;
475
ollie5b621572004-03-20 16:46:10 +0000476 pacc = pci_alloc(); /* Get the pci_access structure */
ollie5672ac62004-03-17 22:22:08 +0000477 /* Set all options you want -- here we stick with the defaults */
ollie5b621572004-03-20 16:46:10 +0000478 pci_init(pacc); /* Initialize the PCI library */
479 pci_scan_bus(pacc); /* We want to get the list of devices */
ollie5672ac62004-03-17 22:22:08 +0000480
ollie6a600992005-11-26 21:55:36 +0000481
482 /* First look whether we have to do something for this
483 * motherboard.
484 */
485 for (i = 0; i < sizeof(mbenables) / sizeof(mbenables[0]); i++) {
486 if(lb_vendor && !strcmp(mbenables[i].vendor, lb_vendor) &&
487 lb_part && !strcmp(mbenables[i].part, lb_part)) {
488 mbenables[i].doit();
489 break;
490 }
491 }
492
ollie5672ac62004-03-17 22:22:08 +0000493 /* now let's try to find the chipset we have ... */
ollie5b621572004-03-20 16:46:10 +0000494 for (i = 0; i < sizeof(enables) / sizeof(enables[0]) && (!dev);
495 i++) {
ollie5672ac62004-03-17 22:22:08 +0000496 struct pci_filter f;
497 struct pci_dev *z;
498 /* the first param is unused. */
499 pci_filter_init((struct pci_access *) 0, &f);
500 f.vendor = enables[i].vendor;
501 f.device = enables[i].device;
ollie5b621572004-03-20 16:46:10 +0000502 for (z = pacc->devices; z; z = z->next)
ollie5672ac62004-03-17 22:22:08 +0000503 if (pci_filter_match(&f, z)) {
504 enable = &enables[i];
505 dev = z;
506 }
507 }
508
stepan0917aa52006-08-25 19:21:42 +0000509 if (!enable) {
510 printf("Warning: Unknown system. Flash detection "
511 "will most likely fail.\n");
512 return 1;
ollie5672ac62004-03-17 22:22:08 +0000513 }
stepan0917aa52006-08-25 19:21:42 +0000514
515 /* now do the deed. */
516 printf("Enabling flash write on %s...", enable->name);
517 if (enable->doit(dev, enable->name) == 0)
518 printf("OK\n");
ollie5672ac62004-03-17 22:22:08 +0000519 return 0;
520}