blob: d03a36b94ac3be21432d03be23cd6ee10393e436 [file] [log] [blame]
Ollie Lho184a4042005-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
Ollie Lhocbbf1252004-03-17 22:22:08 +000013#include <sys/io.h>
14#include <stdio.h>
15#include <pci/pci.h>
16#include <stdlib.h>
Ollie Lho184a4042005-11-26 21:55:36 +000017#include <stdint.h>
18#include <string.h>
19#include "lbtable.h"
20#include "debug.h"
Ollie Lhocbbf1252004-03-17 22:22:08 +000021
Stefan Reinauer86de2832006-03-31 11:26:55 +000022// We keep this for the others.
23static struct pci_access *pacc;
24
Ollie Lho761bf1b2004-03-20 16:46:10 +000025static int enable_flash_sis630(struct pci_dev *dev, char *name)
Ollie Lhocbbf1252004-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);
Ollie Lho761bf1b2004-03-20 16:46:10 +000064 outb(0x02, 0x4f);
Ollie Lhocbbf1252004-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 */
Ollie Lho184a4042005-11-26 21:55:36 +000082 uint8_t old, new;
Ollie Lhocbbf1252004-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 */
Ollie Lho761bf1b2004-03-20 16:46:10 +000086
Ollie Lhocbbf1252004-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) {
Ollie Lho8b8897a2004-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);
Ollie Lhocbbf1252004-03-17 22:22:08 +000099 return -1;
100 }
101 return 0;
102}
103
Stefan Reinauer86de2832006-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)
Ronald G. Minnich6a967412004-09-28 20:09:06 +0000111{
112 /* register 4e.b gets or'ed with one */
Ollie Lho184a4042005-11-26 21:55:36 +0000113 uint8_t old, new;
Ronald G. Minnich6a967412004-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
Stefan Reinauer86de2832006-03-31 11:26:55 +0000118 old = pci_read_byte(dev, bios_cntl);
Ronald G. Minnich6a967412004-09-28 20:09:06 +0000119
120 new = old | 1;
121
122 if (new == old)
123 return 0;
124
Stefan Reinauer86de2832006-03-31 11:26:55 +0000125 pci_write_byte(dev, bios_cntl, new);
Ronald G. Minnich6a967412004-09-28 20:09:06 +0000126
Stefan Reinauer86de2832006-03-31 11:26:55 +0000127 if (pci_read_byte(dev, bios_cntl) != new) {
Ronald G. Minnich6a967412004-09-28 20:09:06 +0000128 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
Stefan Reinauer86de2832006-03-31 11:26:55 +0000129 bios_cntl, new, name);
Ronald G. Minnich6a967412004-09-28 20:09:06 +0000130 return -1;
131 }
132 return 0;
133}
134
Stefan Reinauer86de2832006-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
Ollie Lhocbbf1252004-03-17 22:22:08 +0000145static int enable_flash_vt8235(struct pci_dev *dev, char *name)
146{
Ollie Lho184a4042005-11-26 21:55:36 +0000147 uint8_t old, new, val;
Ollie Lhocbbf1252004-03-17 22:22:08 +0000148 unsigned int base;
149 int ok;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000150
Ollie Lhocbbf1252004-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) {
Ollie Lho8b8897a2004-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);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000168 }
169
170 /* enable GPIO15 which is connected to write protect. */
Ollie Lho8b8897a2004-03-27 00:18:15 +0000171 base = ((pci_read_byte(dev, 0x88) & 0x80) | pci_read_byte(dev, 0x89) << 8);
Ollie Lhocbbf1252004-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{
Ollie Lho184a4042005-11-26 21:55:36 +0000185 uint8_t val;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000186
Ollie Lhocbbf1252004-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) {
Ollie Lho8b8897a2004-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);
Ollie Lhocbbf1252004-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{
Ollie Lho184a4042005-11-26 21:55:36 +0000201 uint8_t new;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000202
Ollie Lhocbbf1252004-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) {
Ollie Lho8b8897a2004-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);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000210 return -1;
211 }
Ollie Lho184a4042005-11-26 21:55:36 +0000212
213 new = pci_read_byte(dev, 0x5b) | 0x20;
214 pci_write_byte(dev, 0x5b, new);
215
Ollie Lhocbbf1252004-03-17 22:22:08 +0000216 return 0;
217}
218
Ollie Lho184a4042005-11-26 21:55:36 +0000219
Ollie Lhocbbf1252004-03-17 22:22:08 +0000220static int enable_flash_sc1100(struct pci_dev *dev, char *name)
221{
Ollie Lho184a4042005-11-26 21:55:36 +0000222 uint8_t new;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000223
Ollie Lhocbbf1252004-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) {
Ollie Lho8b8897a2004-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);
Ollie Lhocbbf1252004-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{
Ollie Lho184a4042005-11-26 21:55:36 +0000238 uint8_t new, newer;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000239
Ollie Lhocbbf1252004-03-17 22:22:08 +0000240 new = pci_read_byte(dev, 0x45);
241
242 /* clear bit 5 */
Ollie Lho761bf1b2004-03-20 16:46:10 +0000243 new &= (~0x20);
Ollie Lhocbbf1252004-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) {
Ollie Lho8b8897a2004-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);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000253 printf("Stuck at 0x%x\n", newer);
254 return -1;
255 }
256 return 0;
257}
258
Ollie Lho761bf1b2004-03-20 16:46:10 +0000259static int enable_flash_amd8111(struct pci_dev *dev, char *name)
260{
Ollie Lhocbbf1252004-03-17 22:22:08 +0000261 /* register 4e.b gets or'ed with one */
Ollie Lho184a4042005-11-26 21:55:36 +0000262 uint8_t old, new;
Ollie Lhocbbf1252004-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
Ollie Lhod11f3612004-12-07 17:19:04 +0000267 /* enable decoding at 0xffb00000 to 0xffffffff */
Ollie Lhocbbf1252004-03-17 22:22:08 +0000268 old = pci_read_byte(dev, 0x43);
Ollie Lhod11f3612004-12-07 17:19:04 +0000269 new = old | 0xC0;
Ollie Lhocbbf1252004-03-17 22:22:08 +0000270 if (new != old) {
271 pci_write_byte(dev, 0x43, new);
272 if (pci_read_byte(dev, 0x43) != new) {
Ollie Lho8b8897a2004-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);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000275 }
276 }
277
Ollie Lho761bf1b2004-03-20 16:46:10 +0000278 old = pci_read_byte(dev, 0x40);
Ollie Lhocbbf1252004-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) {
Ollie Lho8b8897a2004-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);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000287 return -1;
288 }
289 return 0;
290}
291
Yinghai Lu952dfce2005-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 */
Ollie Lho184a4042005-11-26 21:55:36 +0000296 uint8_t old, new;
Yinghai Lu952dfce2005-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
Stefan Reinauer86de2832006-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
Ollie Lhocbbf1252004-03-17 22:22:08 +0000378typedef struct penable {
Ollie Lho761bf1b2004-03-20 16:46:10 +0000379 unsigned short vendor, device;
Ollie Lhocbbf1252004-03-17 22:22:08 +0000380 char *name;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000381 int (*doit) (struct pci_dev * dev, char *name);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000382} FLASH_ENABLE;
383
384static FLASH_ENABLE enables[] = {
Ollie Lho761bf1b2004-03-20 16:46:10 +0000385 {0x1039, 0x0630, "sis630", enable_flash_sis630},
386 {0x8086, 0x2480, "E7500", enable_flash_e7500},
Ronald G. Minnich6a967412004-09-28 20:09:06 +0000387 {0x8086, 0x24c0, "ICH4", enable_flash_ich4},
Scott Tsai023af762006-03-31 11:36:06 +0000388 {0x8086, 0x24cc, "ICH4-M", enable_flash_ich4},
Ronald G. Minnichd2c3a622006-02-24 17:10:10 +0000389 {0x8086, 0x24d0, "ICH5", enable_flash_ich4},
Stefan Reinauer86de2832006-03-31 11:26:55 +0000390 {0x8086, 0x27b8, "ICH7", enable_flash_ich7},
Ollie Lho761bf1b2004-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},
Ollie Lhocbbf1252004-03-17 22:22:08 +0000395 {0x1039, 0x0008, "SIS5595", enable_flash_sis5595},
396 {0x1022, 0x7468, "AMD8111", enable_flash_amd8111},
Stefan Reinauer86de2832006-03-31 11:26:55 +0000397 // this fallthrough looks broken.
Yinghai Lu952dfce2005-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.
Stefan Reinauer86de2832006-03-31 11:26:55 +0000401 {0x1002, 0x4377, "ATI SB400", enable_flash_sb400}, // ATI Technologies Inc IXP SB400 PCI-ISA Bridge (rev 80)
Ollie Lhocbbf1252004-03-17 22:22:08 +0000402};
Ollie Lho761bf1b2004-03-20 16:46:10 +0000403
Ollie Lho184a4042005-11-26 21:55:36 +0000404static int mbenable_island_aruma(void)
405{
Stefan Reinauer86de2832006-03-31 11:26:55 +0000406#define EFIR 0x2e /* Extended function index register, either 0x2e or 0x4e */
407#define EFDR EFIR + 1 /* Extended function data register, one plus the index reg. */
Ollie Lho184a4042005-11-26 21:55:36 +0000408 char b;
Stefan Reinauer86de2832006-03-31 11:26:55 +0000409
410/* Disable the flash write protect. The flash write protect is
411 * connected to the WinBond w83627hf GPIO 24.
412 */
Ollie Lho184a4042005-11-26 21:55:36 +0000413
414 /* get io privilege access winbond config space */
415 if (iopl(3) != 0) {
416 perror("Can not set io priviliage");
417 exit(1);
418 }
419
420 printf("Disabling mainboard flash write protection.\n");
421
422 outb(0x87, EFIR); // sequence to unlock extended functions
423 outb(0x87, EFIR);
424
425 outb(0x20, EFIR); // SIO device ID register
426 b = inb(EFDR);
427 printf_debug("W83627HF device ID = 0x%x\n",b);
428
429 if (b != 0x52) {
430 perror("Incorrect device ID, aborting write protect disable\n");
431 exit(1);
432 }
433
434 outb(0x2b, EFIR); // GPIO multiplexed pin reg.
435 b = inb(EFDR) | 0x10;
436 outb(0x2b, EFIR);
437 outb(b, EFDR); // select GPIO 24 instead of WDTO
438
439 outb(0x7, EFIR); // logical device select
440 outb(0x8, EFDR); // point to device 8, GPIO port 2
441
442 outb(0x30, EFIR); // logic device activation control
443 outb(0x1, EFDR); // activate
444
445 outb(0xf0, EFIR); // GPIO 20-27 I/O selection register
446 b = inb(EFDR) & ~0x10;
447 outb(0xf0, EFIR);
448 outb(b, EFDR); // set GPIO 24 as an output
449
450 outb(0xf1, EFIR); // GPIO 20-27 data register
451 b = inb(EFDR) | 0x10;
452 outb(0xf1, EFIR);
453 outb(b, EFDR); // set GPIO 24
454
455 outb(0xaa, EFIR); // command to exit extended functions
456
457 return 0;
458}
459
460typedef struct mbenable {
461 char *vendor, *part;
462 int (*doit)(void);
463} MAINBOARD_ENABLE;
464
465static MAINBOARD_ENABLE mbenables[] = {
466 { "ISLAND", "ARUMA", mbenable_island_aruma },
467};
468
Ollie Lhocbbf1252004-03-17 22:22:08 +0000469int enable_flash_write()
470{
471 int i;
Ollie Lhocbbf1252004-03-17 22:22:08 +0000472 struct pci_dev *dev = 0;
473 FLASH_ENABLE *enable = 0;
474
Ollie Lho761bf1b2004-03-20 16:46:10 +0000475 pacc = pci_alloc(); /* Get the pci_access structure */
Ollie Lhocbbf1252004-03-17 22:22:08 +0000476 /* Set all options you want -- here we stick with the defaults */
Ollie Lho761bf1b2004-03-20 16:46:10 +0000477 pci_init(pacc); /* Initialize the PCI library */
478 pci_scan_bus(pacc); /* We want to get the list of devices */
Ollie Lhocbbf1252004-03-17 22:22:08 +0000479
Ollie Lho184a4042005-11-26 21:55:36 +0000480
481 /* First look whether we have to do something for this
482 * motherboard.
483 */
484 for (i = 0; i < sizeof(mbenables) / sizeof(mbenables[0]); i++) {
485 if(lb_vendor && !strcmp(mbenables[i].vendor, lb_vendor) &&
486 lb_part && !strcmp(mbenables[i].part, lb_part)) {
487 mbenables[i].doit();
488 break;
489 }
490 }
491
Ollie Lhocbbf1252004-03-17 22:22:08 +0000492 /* now let's try to find the chipset we have ... */
Ollie Lho761bf1b2004-03-20 16:46:10 +0000493 for (i = 0; i < sizeof(enables) / sizeof(enables[0]) && (!dev);
494 i++) {
Ollie Lhocbbf1252004-03-17 22:22:08 +0000495 struct pci_filter f;
496 struct pci_dev *z;
497 /* the first param is unused. */
498 pci_filter_init((struct pci_access *) 0, &f);
499 f.vendor = enables[i].vendor;
500 f.device = enables[i].device;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000501 for (z = pacc->devices; z; z = z->next)
Ollie Lhocbbf1252004-03-17 22:22:08 +0000502 if (pci_filter_match(&f, z)) {
503 enable = &enables[i];
504 dev = z;
505 }
506 }
507
508 /* now do the deed. */
509 if (enable) {
510 printf("Enabling flash write on %s...", enable->name);
511 if (enable->doit(dev, enable->name) == 0)
512 printf("OK\n");
513 }
514 return 0;
515}