blob: 91c5814537984a7eda27aa6357b11cc6ea59b430 [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
Ollie Lho761bf1b2004-03-20 16:46:10 +000022static int enable_flash_sis630(struct pci_dev *dev, char *name)
Ollie Lhocbbf1252004-03-17 22:22:08 +000023{
24 char b;
25
26 /* get io privilege access PCI configuration space */
27 if (iopl(3) != 0) {
28 perror("Can not set io priviliage");
29 exit(1);
30 }
31
32 /* Enable 0xFFF8000~0xFFFF0000 decoding on SiS 540/630 */
33 outl(0x80000840, 0x0cf8);
34 b = inb(0x0cfc) | 0x0b;
35 outb(b, 0xcfc);
36 /* Flash write enable on SiS 540/630 */
37 outl(0x80000845, 0x0cf8);
38 b = inb(0x0cfd) | 0x40;
39 outb(b, 0xcfd);
40
41 /* The same thing on SiS 950 SuperIO side */
42 outb(0x87, 0x2e);
43 outb(0x01, 0x2e);
44 outb(0x55, 0x2e);
45 outb(0x55, 0x2e);
46
47 if (inb(0x2f) != 0x87) {
48 outb(0x87, 0x4e);
49 outb(0x01, 0x4e);
50 outb(0x55, 0x4e);
51 outb(0xaa, 0x4e);
52 if (inb(0x4f) != 0x87) {
53 printf("Can not access SiS 950\n");
54 return -1;
55 }
56 outb(0x24, 0x4e);
57 b = inb(0x4f) | 0xfc;
58 outb(0x24, 0x4e);
59 outb(b, 0x4f);
60 outb(0x02, 0x4e);
Ollie Lho761bf1b2004-03-20 16:46:10 +000061 outb(0x02, 0x4f);
Ollie Lhocbbf1252004-03-17 22:22:08 +000062 }
63
64 outb(0x24, 0x2e);
65 printf("2f is %#x\n", inb(0x2f));
66 b = inb(0x2f) | 0xfc;
67 outb(0x24, 0x2e);
68 outb(b, 0x2f);
69
70 outb(0x02, 0x2e);
71 outb(0x02, 0x2f);
72
73 return 0;
74}
75
76static int enable_flash_e7500(struct pci_dev *dev, char *name)
77{
78 /* register 4e.b gets or'ed with one */
Ollie Lho184a4042005-11-26 21:55:36 +000079 uint8_t old, new;
Ollie Lhocbbf1252004-03-17 22:22:08 +000080 /* if it fails, it fails. There are so many variations of broken mobos
81 * that it is hard to argue that we should quit at this point.
82 */
Ollie Lho761bf1b2004-03-20 16:46:10 +000083
Ollie Lhocbbf1252004-03-17 22:22:08 +000084 old = pci_read_byte(dev, 0x4e);
85
86 new = old | 1;
87
88 if (new == old)
89 return 0;
90
91 pci_write_byte(dev, 0x4e, new);
92
93 if (pci_read_byte(dev, 0x4e) != new) {
Ollie Lho8b8897a2004-03-27 00:18:15 +000094 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
95 0x4e, new, name);
Ollie Lhocbbf1252004-03-17 22:22:08 +000096 return -1;
97 }
98 return 0;
99}
100
Ronald G. Minnich6a967412004-09-28 20:09:06 +0000101static int enable_flash_ich4(struct pci_dev *dev, char *name)
102{
103 /* register 4e.b gets or'ed with one */
Ollie Lho184a4042005-11-26 21:55:36 +0000104 uint8_t old, new;
Ronald G. Minnich6a967412004-09-28 20:09:06 +0000105 /* if it fails, it fails. There are so many variations of broken mobos
106 * that it is hard to argue that we should quit at this point.
107 */
108
109 old = pci_read_byte(dev, 0x4e);
110
111 new = old | 1;
112
113 if (new == old)
114 return 0;
115
116 pci_write_byte(dev, 0x4e, new);
117
118 if (pci_read_byte(dev, 0x4e) != new) {
119 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
120 0x4e, new, name);
121 return -1;
122 }
123 return 0;
124}
125
Ollie Lhocbbf1252004-03-17 22:22:08 +0000126static int enable_flash_vt8235(struct pci_dev *dev, char *name)
127{
Ollie Lho184a4042005-11-26 21:55:36 +0000128 uint8_t old, new, val;
Ollie Lhocbbf1252004-03-17 22:22:08 +0000129 unsigned int base;
130 int ok;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000131
Ollie Lhocbbf1252004-03-17 22:22:08 +0000132 /* get io privilege access PCI configuration space */
133 if (iopl(3) != 0) {
134 perror("Can not set io priviliage");
135 exit(1);
136 }
137
138 old = pci_read_byte(dev, 0x40);
139
140 new = old | 0x10;
141
142 if (new == old)
143 return 0;
144
145 ok = pci_write_byte(dev, 0x40, new);
146 if (ok != 0) {
Ollie Lho8b8897a2004-03-27 00:18:15 +0000147 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
148 old, new, name);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000149 }
150
151 /* enable GPIO15 which is connected to write protect. */
Ollie Lho8b8897a2004-03-27 00:18:15 +0000152 base = ((pci_read_byte(dev, 0x88) & 0x80) | pci_read_byte(dev, 0x89) << 8);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000153 val = inb(base + 0x4d);
154 val |= 0x80;
155 outb(val, base + 0x4d);
156
157 if (ok != 0) {
158 return -1;
159 } else {
160 return 0;
161 }
162}
163
164static int enable_flash_vt8231(struct pci_dev *dev, char *name)
165{
Ollie Lho184a4042005-11-26 21:55:36 +0000166 uint8_t val;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000167
Ollie Lhocbbf1252004-03-17 22:22:08 +0000168 val = pci_read_byte(dev, 0x40);
169 val |= 0x10;
170 pci_write_byte(dev, 0x40, val);
171
172 if (pci_read_byte(dev, 0x40) != val) {
Ollie Lho8b8897a2004-03-27 00:18:15 +0000173 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
174 0x40, val, name);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000175 return -1;
176 }
177 return 0;
178}
179
180static int enable_flash_cs5530(struct pci_dev *dev, char *name)
181{
Ollie Lho184a4042005-11-26 21:55:36 +0000182 uint8_t new;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000183
Ollie Lhocbbf1252004-03-17 22:22:08 +0000184 pci_write_byte(dev, 0x52, 0xee);
185
186 new = pci_read_byte(dev, 0x52);
187
188 if (new != 0xee) {
Ollie Lho8b8897a2004-03-27 00:18:15 +0000189 printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
190 0x52, new, name);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000191 return -1;
192 }
Ollie Lho184a4042005-11-26 21:55:36 +0000193
194 new = pci_read_byte(dev, 0x5b) | 0x20;
195 pci_write_byte(dev, 0x5b, new);
196
Ollie Lhocbbf1252004-03-17 22:22:08 +0000197 return 0;
198}
199
Ollie Lho184a4042005-11-26 21:55:36 +0000200
Ollie Lhocbbf1252004-03-17 22:22:08 +0000201static int enable_flash_sc1100(struct pci_dev *dev, char *name)
202{
Ollie Lho184a4042005-11-26 21:55:36 +0000203 uint8_t new;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000204
Ollie Lhocbbf1252004-03-17 22:22:08 +0000205 pci_write_byte(dev, 0x52, 0xee);
206
207 new = pci_read_byte(dev, 0x52);
208
209 if (new != 0xee) {
Ollie Lho8b8897a2004-03-27 00:18:15 +0000210 printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
211 0x52, new, name);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000212 return -1;
213 }
214 return 0;
215}
216
217static int enable_flash_sis5595(struct pci_dev *dev, char *name)
218{
Ollie Lho184a4042005-11-26 21:55:36 +0000219 uint8_t new, newer;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000220
Ollie Lhocbbf1252004-03-17 22:22:08 +0000221 new = pci_read_byte(dev, 0x45);
222
223 /* clear bit 5 */
Ollie Lho761bf1b2004-03-20 16:46:10 +0000224 new &= (~0x20);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000225 /* set bit 2 */
226 new |= 0x4;
227
228 pci_write_byte(dev, 0x45, new);
229
230 newer = pci_read_byte(dev, 0x45);
231 if (newer != new) {
Ollie Lho8b8897a2004-03-27 00:18:15 +0000232 printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
233 0x45, new, name);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000234 printf("Stuck at 0x%x\n", newer);
235 return -1;
236 }
237 return 0;
238}
239
Ollie Lho761bf1b2004-03-20 16:46:10 +0000240static int enable_flash_amd8111(struct pci_dev *dev, char *name)
241{
Ollie Lhocbbf1252004-03-17 22:22:08 +0000242 /* register 4e.b gets or'ed with one */
Ollie Lho184a4042005-11-26 21:55:36 +0000243 uint8_t old, new;
Ollie Lhocbbf1252004-03-17 22:22:08 +0000244 /* if it fails, it fails. There are so many variations of broken mobos
245 * that it is hard to argue that we should quit at this point.
246 */
247
Ollie Lhod11f3612004-12-07 17:19:04 +0000248 /* enable decoding at 0xffb00000 to 0xffffffff */
Ollie Lhocbbf1252004-03-17 22:22:08 +0000249 old = pci_read_byte(dev, 0x43);
Ollie Lhod11f3612004-12-07 17:19:04 +0000250 new = old | 0xC0;
Ollie Lhocbbf1252004-03-17 22:22:08 +0000251 if (new != old) {
252 pci_write_byte(dev, 0x43, new);
253 if (pci_read_byte(dev, 0x43) != new) {
Ollie Lho8b8897a2004-03-27 00:18:15 +0000254 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
255 0x43, new, name);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000256 }
257 }
258
Ollie Lho761bf1b2004-03-20 16:46:10 +0000259 old = pci_read_byte(dev, 0x40);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000260 new = old | 0x01;
261 if (new == old)
262 return 0;
263 pci_write_byte(dev, 0x40, new);
264
265 if (pci_read_byte(dev, 0x40) != new) {
Ollie Lho8b8897a2004-03-27 00:18:15 +0000266 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
267 0x40, new, name);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000268 return -1;
269 }
270 return 0;
271}
272
Yinghai Lu952dfce2005-07-06 17:13:46 +0000273//By yhlu
274static int enable_flash_ck804(struct pci_dev *dev, char *name)
275{
276 /* register 4e.b gets or'ed with one */
Ollie Lho184a4042005-11-26 21:55:36 +0000277 uint8_t old, new;
Yinghai Lu952dfce2005-07-06 17:13:46 +0000278 /* if it fails, it fails. There are so many variations of broken mobos
279 * that it is hard to argue that we should quit at this point.
280 */
281
282 //dump_pci_device(dev);
283
284 old = pci_read_byte(dev, 0x88);
285 new = old | 0xc0;
286 if (new != old) {
287 pci_write_byte(dev, 0x88, new);
288 if (pci_read_byte(dev, 0x88) != new) {
289 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
290 0x88, new, name);
291 }
292 }
293
294 old = pci_read_byte(dev, 0x6d);
295 new = old | 0x01;
296 if (new == old)
297 return 0;
298 pci_write_byte(dev, 0x6d, new);
299
300 if (pci_read_byte(dev, 0x6d) != new) {
301 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
302 0x6d, new, name);
303 return -1;
304 }
305 return 0;
306}
307
Ollie Lhocbbf1252004-03-17 22:22:08 +0000308typedef struct penable {
Ollie Lho761bf1b2004-03-20 16:46:10 +0000309 unsigned short vendor, device;
Ollie Lhocbbf1252004-03-17 22:22:08 +0000310 char *name;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000311 int (*doit) (struct pci_dev * dev, char *name);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000312} FLASH_ENABLE;
313
314static FLASH_ENABLE enables[] = {
Ollie Lho761bf1b2004-03-20 16:46:10 +0000315 {0x1039, 0x0630, "sis630", enable_flash_sis630},
316 {0x8086, 0x2480, "E7500", enable_flash_e7500},
Ronald G. Minnich6a967412004-09-28 20:09:06 +0000317 {0x8086, 0x24c0, "ICH4", enable_flash_ich4},
Ronald G. Minnichd2c3a622006-02-24 17:10:10 +0000318 {0x8086, 0x24d0, "ICH5", enable_flash_ich4},
Ollie Lho761bf1b2004-03-20 16:46:10 +0000319 {0x1106, 0x8231, "VT8231", enable_flash_vt8231},
320 {0x1106, 0x3177, "VT8235", enable_flash_vt8235},
321 {0x1078, 0x0100, "CS5530", enable_flash_cs5530},
322 {0x100b, 0x0510, "SC1100", enable_flash_sc1100},
Ollie Lhocbbf1252004-03-17 22:22:08 +0000323 {0x1039, 0x0008, "SIS5595", enable_flash_sis5595},
324 {0x1022, 0x7468, "AMD8111", enable_flash_amd8111},
Yinghai Lu952dfce2005-07-06 17:13:46 +0000325 {0x10de, 0x0050, "NVIDIA CK804", enable_flash_ck804}, // LPC
326 {0x10de, 0x0051, "NVIDIA CK804", enable_flash_ck804}, // Pro
327 {0x10de, 0x00d3, "NVIDIA CK804", enable_flash_ck804}, // Slave, should not be here, to fix known bug for A01.
Ollie Lhocbbf1252004-03-17 22:22:08 +0000328};
Ollie Lho761bf1b2004-03-20 16:46:10 +0000329
Ollie Lho184a4042005-11-26 21:55:36 +0000330static int mbenable_island_aruma(void)
331{
332#define EFIR 0x2e // Exteneded function index register, either 0x2e or 0x4e
333#define EFDR EFIR + 1 // Extended function data register, one plus the index reg.
334 char b;
335// Disable the flash write protect. The flash write protect is
336// connected to the WinBond w83627hf GPIO 24.
337
338 /* get io privilege access winbond config space */
339 if (iopl(3) != 0) {
340 perror("Can not set io priviliage");
341 exit(1);
342 }
343
344 printf("Disabling mainboard flash write protection.\n");
345
346 outb(0x87, EFIR); // sequence to unlock extended functions
347 outb(0x87, EFIR);
348
349 outb(0x20, EFIR); // SIO device ID register
350 b = inb(EFDR);
351 printf_debug("W83627HF device ID = 0x%x\n",b);
352
353 if (b != 0x52) {
354 perror("Incorrect device ID, aborting write protect disable\n");
355 exit(1);
356 }
357
358 outb(0x2b, EFIR); // GPIO multiplexed pin reg.
359 b = inb(EFDR) | 0x10;
360 outb(0x2b, EFIR);
361 outb(b, EFDR); // select GPIO 24 instead of WDTO
362
363 outb(0x7, EFIR); // logical device select
364 outb(0x8, EFDR); // point to device 8, GPIO port 2
365
366 outb(0x30, EFIR); // logic device activation control
367 outb(0x1, EFDR); // activate
368
369 outb(0xf0, EFIR); // GPIO 20-27 I/O selection register
370 b = inb(EFDR) & ~0x10;
371 outb(0xf0, EFIR);
372 outb(b, EFDR); // set GPIO 24 as an output
373
374 outb(0xf1, EFIR); // GPIO 20-27 data register
375 b = inb(EFDR) | 0x10;
376 outb(0xf1, EFIR);
377 outb(b, EFDR); // set GPIO 24
378
379 outb(0xaa, EFIR); // command to exit extended functions
380
381 return 0;
382}
383
384typedef struct mbenable {
385 char *vendor, *part;
386 int (*doit)(void);
387} MAINBOARD_ENABLE;
388
389static MAINBOARD_ENABLE mbenables[] = {
390 { "ISLAND", "ARUMA", mbenable_island_aruma },
391};
392
Ollie Lhocbbf1252004-03-17 22:22:08 +0000393int enable_flash_write()
394{
395 int i;
396 struct pci_access *pacc;
397 struct pci_dev *dev = 0;
398 FLASH_ENABLE *enable = 0;
399
Ollie Lho761bf1b2004-03-20 16:46:10 +0000400 pacc = pci_alloc(); /* Get the pci_access structure */
Ollie Lhocbbf1252004-03-17 22:22:08 +0000401 /* Set all options you want -- here we stick with the defaults */
Ollie Lho761bf1b2004-03-20 16:46:10 +0000402 pci_init(pacc); /* Initialize the PCI library */
403 pci_scan_bus(pacc); /* We want to get the list of devices */
Ollie Lhocbbf1252004-03-17 22:22:08 +0000404
Ollie Lho184a4042005-11-26 21:55:36 +0000405
406 /* First look whether we have to do something for this
407 * motherboard.
408 */
409 for (i = 0; i < sizeof(mbenables) / sizeof(mbenables[0]); i++) {
410 if(lb_vendor && !strcmp(mbenables[i].vendor, lb_vendor) &&
411 lb_part && !strcmp(mbenables[i].part, lb_part)) {
412 mbenables[i].doit();
413 break;
414 }
415 }
416
Ollie Lhocbbf1252004-03-17 22:22:08 +0000417 /* now let's try to find the chipset we have ... */
Ollie Lho761bf1b2004-03-20 16:46:10 +0000418 for (i = 0; i < sizeof(enables) / sizeof(enables[0]) && (!dev);
419 i++) {
Ollie Lhocbbf1252004-03-17 22:22:08 +0000420 struct pci_filter f;
421 struct pci_dev *z;
422 /* the first param is unused. */
423 pci_filter_init((struct pci_access *) 0, &f);
424 f.vendor = enables[i].vendor;
425 f.device = enables[i].device;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000426 for (z = pacc->devices; z; z = z->next)
Ollie Lhocbbf1252004-03-17 22:22:08 +0000427 if (pci_filter_match(&f, z)) {
428 enable = &enables[i];
429 dev = z;
430 }
431 }
432
433 /* now do the deed. */
434 if (enable) {
435 printf("Enabling flash write on %s...", enable->name);
436 if (enable->doit(dev, enable->name) == 0)
437 printf("OK\n");
438 }
439 return 0;
440}