flashrom: further cleanups to enable_flash_cs5536
[coreboot.git] / util / flashrom / chipset_enable.c
1 /*
2  * This file is part of the flashrom project.
3  *
4  * Copyright (C) 2000 Silicon Integrated System Corporation
5  * Copyright (C) 2005-2007 coresystems GmbH <stepan@coresystems.de>
6  * Copyright (C) 2006 Uwe Hermann <uwe@hermann-uwe.de>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20  */
21
22 /*
23  * Contains the chipset specific flash enables.
24  */
25
26 #define _LARGEFILE64_SOURCE
27
28 #include <stdio.h>
29 #include <pci/pci.h>
30 #include <stdlib.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include "flash.h"
36
37 static int enable_flash_ali_m1533(struct pci_dev *dev, const char *name)
38 {
39         uint8_t tmp;
40
41         /*
42          * ROM Write enable, 0xFFFC0000-0xFFFDFFFF and
43          * 0xFFFE0000-0xFFFFFFFF ROM select enable.
44          */
45         tmp = pci_read_byte(dev, 0x47);
46         tmp |= 0x46;
47         pci_write_byte(dev, 0x47, tmp);
48
49         return 0;
50 }
51
52 static int enable_flash_sis630(struct pci_dev *dev, const char *name)
53 {
54         uint8_t b;
55
56         /* Enable 0xFFF8000~0xFFFF0000 decoding on SiS 540/630. */
57         b = pci_read_byte(dev, 0x40);
58         pci_write_byte(dev, 0x40, b | 0xb);
59
60         /* Flash write enable on SiS 540/630. */
61         b = pci_read_byte(dev, 0x45);
62         pci_write_byte(dev, 0x45, b | 0x40);
63
64         /* The same thing on SiS 950 Super I/O side... */
65
66         /* First probe for Super I/O on config port 0x2e. */
67         outb(0x87, 0x2e);
68         outb(0x01, 0x2e);
69         outb(0x55, 0x2e);
70         outb(0x55, 0x2e);
71
72         if (inb(0x2f) != 0x87) {
73                 /* If that failed, try config port 0x4e. */
74                 outb(0x87, 0x4e);
75                 outb(0x01, 0x4e);
76                 outb(0x55, 0x4e);
77                 outb(0xaa, 0x4e);
78                 if (inb(0x4f) != 0x87) {
79                         printf("Can not access SiS 950\n");
80                         return -1;
81                 }
82                 outb(0x24, 0x4e);
83                 b = inb(0x4f) | 0xfc;
84                 outb(0x24, 0x4e);
85                 outb(b, 0x4f);
86                 outb(0x02, 0x4e);
87                 outb(0x02, 0x4f);
88         }
89
90         outb(0x24, 0x2e);
91         printf("2f is %#x\n", inb(0x2f));
92         b = inb(0x2f) | 0xfc;
93         outb(0x24, 0x2e);
94         outb(b, 0x2f);
95
96         outb(0x02, 0x2e);
97         outb(0x02, 0x2f);
98
99         return 0;
100 }
101
102 /* Datasheet:
103  *   - Name: 82371AB PCI-TO-ISA / IDE XCELERATOR (PIIX4)
104  *   - URL: http://www.intel.com/design/intarch/datashts/290562.htm
105  *   - PDF: http://www.intel.com/design/intarch/datashts/29056201.pdf
106  *   - Order Number: 290562-001
107  */
108 static int enable_flash_piix4(struct pci_dev *dev, const char *name)
109 {
110         uint16_t old, new;
111         uint16_t xbcs = 0x4e;   /* X-Bus Chip Select register. */
112
113         old = pci_read_word(dev, xbcs);
114
115         /* Set bit 9: 1-Meg Extended BIOS Enable (PCI master accesses to
116          *            FFF00000-FFF7FFFF are forwarded to ISA).
117          * Set bit 7: Extended BIOS Enable (PCI master accesses to
118          *            FFF80000-FFFDFFFF are forwarded to ISA).
119          * Set bit 6: Lower BIOS Enable (PCI master, or ISA master accesses to
120          *            the lower 64-Kbyte BIOS block (E0000-EFFFF) at the top
121          *            of 1 Mbyte, or the aliases at the top of 4 Gbyte
122          *            (FFFE0000-FFFEFFFF) result in the generation of BIOSCS#.
123          * Note: Accesses to FFFF0000-FFFFFFFF are always forwarded to ISA.
124          * Set bit 2: BIOSCS# Write Enable (1=enable, 0=disable).
125          */
126         new = old | 0x2c4;
127
128         if (new == old)
129                 return 0;
130
131         pci_write_word(dev, xbcs, new);
132
133         if (pci_read_word(dev, xbcs) != new) {
134                 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", xbcs, new, name);
135                 return -1;
136         }
137
138         return 0;
139 }
140
141 /*
142  * See ie. page 375 of "Intel ICH7 External Design Specification"
143  * http://download.intel.com/design/chipsets/datashts/30701302.pdf
144  */
145 static int enable_flash_ich(struct pci_dev *dev, const char *name,
146                             int bios_cntl)
147 {
148         uint8_t old, new;
149
150         /*
151          * Note: the ICH0-ICH5 BIOS_CNTL register is actually 16 bit wide, but
152          * just treating it as 8 bit wide seems to work fine in practice.
153          */
154         old = pci_read_byte(dev, bios_cntl);
155
156         new = old | 1;
157
158         if (new == old)
159                 return 0;
160
161         pci_write_byte(dev, bios_cntl, new);
162
163         if (pci_read_byte(dev, bios_cntl) != new) {
164                 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", bios_cntl, new, name);
165                 return -1;
166         }
167
168         return 0;
169 }
170
171 static int enable_flash_ich_4e(struct pci_dev *dev, const char *name)
172 {
173         return enable_flash_ich(dev, name, 0x4e);
174 }
175
176 static int enable_flash_ich_dc(struct pci_dev *dev, const char *name)
177 {
178         return enable_flash_ich(dev, name, 0xdc);
179 }
180
181 static int enable_flash_vt823x(struct pci_dev *dev, const char *name)
182 {
183         uint8_t val;
184
185         /* ROM write enable */
186         val = pci_read_byte(dev, 0x40);
187         val |= 0x10;
188         pci_write_byte(dev, 0x40, val);
189
190         if (pci_read_byte(dev, 0x40) != val) {
191                 printf("\nWARNING: Failed to enable ROM Write on \"%s\"\n",
192                        name);
193                 return -1;
194         }
195
196         return 0;
197 }
198
199 static int enable_flash_cs5530(struct pci_dev *dev, const char *name)
200 {
201         uint8_t reg8;
202
203         #define DECODE_CONTROL_REG2             0x5b    /* F0 index 0x5b */
204         #define ROM_AT_LOGIC_CONTROL_REG        0x52    /* F0 index 0x52 */
205
206         #define LOWER_ROM_ADDRESS_RANGE         (1 << 0)
207         #define ROM_WRITE_ENABLE                (1 << 1)
208         #define UPPER_ROM_ADDRESS_RANGE         (1 << 2)
209         #define BIOS_ROM_POSITIVE_DECODE        (1 << 5)
210
211         /* Decode 0x000E0000-0x000FFFFF (128 KB), not just 64 KB, and
212          * decode 0xFF000000-0xFFFFFFFF (16 MB), not just 256 KB.
213          * Make the configured ROM areas writable.
214          */
215         reg8 = pci_read_byte(dev, ROM_AT_LOGIC_CONTROL_REG);
216         reg8 |= LOWER_ROM_ADDRESS_RANGE;
217         reg8 |= UPPER_ROM_ADDRESS_RANGE;
218         reg8 |= ROM_WRITE_ENABLE;
219         pci_write_byte(dev, ROM_AT_LOGIC_CONTROL_REG, reg8);
220
221         /* Set positive decode on ROM. */
222         reg8 = pci_read_byte(dev, DECODE_CONTROL_REG2);
223         reg8 |= BIOS_ROM_POSITIVE_DECODE;
224         pci_write_byte(dev, DECODE_CONTROL_REG2, reg8);
225
226         return 0;
227 }
228
229 /**
230  * Geode systems write protect the BIOS via RCONFs (cache settings similar
231  * to MTRRs). To unlock, change MSR 0x1808 top byte to 0x22. Reading and
232  * writing to MSRs, however requires instructions rdmsr/wrmsr, which are
233  * ring0 privileged instructions so only the kernel can do the read/write.
234  * This function, therefore, requires that the msr kernel module be loaded
235  * to access these instructions from user space using device /dev/cpu/0/msr.
236  *
237  * This hard-coded location could have potential problems on SMP machines
238  * since it assumes cpu0, but it is safe on the Geode which is not SMP.
239  *
240  * Geode systems also write protect the NOR flash chip itself via MSR_NORF_CTL.
241  * To enable write to NOR Boot flash for the benefit of systems that have such
242  * a setup, raise MSR 0x51400018 WE_CS3 (write enable Boot Flash Chip Select).
243  *
244  * This is probably not portable beyond Linux.
245  */
246 static int enable_flash_cs5536(struct pci_dev *dev, const char *name)
247 {
248         #define MSR_RCONF_DEFAULT       0x1808
249         #define MSR_NORF_CTL            0x51400018
250
251         int fd_msr;
252         unsigned char buf[8];
253
254         fd_msr = open("/dev/cpu/0/msr", O_RDWR);
255         if (!fd_msr) {
256                 perror("open msr");
257                 return -1;
258         }
259
260         if (lseek64(fd_msr, (off64_t) MSR_RCONF_DEFAULT, SEEK_SET) == -1) {
261                 perror("lseek64");
262                 printf("Cannot operate on MSR. Did you run 'modprobe msr'?\n");
263                 close(fd_msr);
264                 return -1;
265         }
266
267         if (read(fd_msr, buf, 8) != 8) {
268                 perror("read msr");
269                 close(fd_msr);
270                 return -1;
271         }
272
273         if (buf[7] != 0x22) {
274                 buf[7] &= 0xfb;
275                 if (lseek64(fd_msr, (off64_t) MSR_RCONF_DEFAULT, SEEK_SET) == -1) {
276                         perror("lseek64");
277                         close(fd_msr);
278                         return -1;
279                 }
280
281                 if (write(fd_msr, buf, 8) < 0) {
282                         perror("msr write");
283                         close(fd_msr);
284                         return -1;
285                 }
286         }
287
288         if (lseek64(fd_msr, (off64_t) MSR_NORF_CTL, SEEK_SET) == -1) {
289                 perror("lseek64");
290                 close(fd_msr);
291                 return -1;
292         }
293
294         if (read(fd_msr, buf, 8) != 8) {
295                 perror("read msr");
296                 close(fd_msr);
297                 return -1;
298         }
299
300         /* Raise WE_CS3 bit. */
301         buf[0] |= 0x08;
302
303         if (lseek64(fd_msr, (off64_t) MSR_NORF_CTL, SEEK_SET) == -1) {
304                 perror("lseek64");
305                 close(fd_msr);
306                 return -1;
307         }
308         if (write(fd_msr, buf, 8) < 0) {
309                 perror("msr write");
310                 close(fd_msr);
311                 return -1;
312         }
313
314         close(fd_msr);
315
316         #undef MSR_RCONF_DEFAULT
317         #undef MSR_NORF_CTL
318         return 0;
319 }
320
321 static int enable_flash_sc1100(struct pci_dev *dev, const char *name)
322 {
323         uint8_t new;
324
325         pci_write_byte(dev, 0x52, 0xee);
326
327         new = pci_read_byte(dev, 0x52);
328
329         if (new != 0xee) {
330                 printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x52, new, name);
331                 return -1;
332         }
333
334         return 0;
335 }
336
337 static int enable_flash_sis5595(struct pci_dev *dev, const char *name)
338 {
339         uint8_t new, newer;
340
341         new = pci_read_byte(dev, 0x45);
342
343         new &= (~0x20);         /* Clear bit 5. */
344         new |= 0x4;             /* Set bit 2. */
345
346         pci_write_byte(dev, 0x45, new);
347
348         newer = pci_read_byte(dev, 0x45);
349         if (newer != new) {
350                 printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x45, new, name);
351                 printf("Stuck at 0x%x\n", newer);
352                 return -1;
353         }
354
355         return 0;
356 }
357
358 static int enable_flash_amd8111(struct pci_dev *dev, const char *name)
359 {
360         uint8_t old, new;
361
362         /* Enable decoding at 0xffb00000 to 0xffffffff. */
363         old = pci_read_byte(dev, 0x43);
364         new = old | 0xC0;
365         if (new != old) {
366                 pci_write_byte(dev, 0x43, new);
367                 if (pci_read_byte(dev, 0x43) != new) {
368                         printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x43, new, name);
369                 }
370         }
371
372         old = pci_read_byte(dev, 0x40);
373         new = old | 0x01;
374         if (new == old)
375                 return 0;
376         pci_write_byte(dev, 0x40, new);
377
378         if (pci_read_byte(dev, 0x40) != new) {
379                 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x40, new, name);
380                 return -1;
381         }
382
383         return 0;
384 }
385
386 static int enable_flash_ck804(struct pci_dev *dev, const char *name)
387 {
388         uint8_t old, new;
389
390         old = pci_read_byte(dev, 0x88);
391         new = old | 0xc0;
392         if (new != old) {
393                 pci_write_byte(dev, 0x88, new);
394                 if (pci_read_byte(dev, 0x88) != new) {
395                         printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x88, new, name);
396                 }
397         }
398
399         old = pci_read_byte(dev, 0x6d);
400         new = old | 0x01;
401         if (new == old)
402                 return 0;
403         pci_write_byte(dev, 0x6d, new);
404
405         if (pci_read_byte(dev, 0x6d) != new) {
406                 printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x6d, new, name);
407                 return -1;
408         }
409
410         return 0;
411 }
412
413 /* ATI Technologies Inc IXP SB400 PCI-ISA Bridge (rev 80) */
414 static int enable_flash_sb400(struct pci_dev *dev, const char *name)
415 {
416         uint8_t tmp;
417         struct pci_filter f;
418         struct pci_dev *smbusdev;
419
420         /* Look for the SMBus device. */
421         pci_filter_init((struct pci_access *)0, &f);
422         f.vendor = 0x1002;
423         f.device = 0x4372;
424
425         for (smbusdev = pacc->devices; smbusdev; smbusdev = smbusdev->next) {
426                 if (pci_filter_match(&f, smbusdev)) {
427                         break;
428                 }
429         }
430
431         if (!smbusdev) {
432                 fprintf(stderr, "ERROR: SMBus device not found. Aborting.\n");
433                 exit(1);
434         }
435
436         /* Enable some SMBus stuff. */
437         tmp = pci_read_byte(smbusdev, 0x79);
438         tmp |= 0x01;
439         pci_write_byte(smbusdev, 0x79, tmp);
440
441         /* Change southbridge. */
442         tmp = pci_read_byte(dev, 0x48);
443         tmp |= 0x21;
444         pci_write_byte(dev, 0x48, tmp);
445
446         /* Now become a bit silly. */
447         tmp = inb(0xc6f);
448         outb(tmp, 0xeb);
449         outb(tmp, 0xeb);
450         tmp |= 0x40;
451         outb(tmp, 0xc6f);
452         outb(tmp, 0xeb);
453         outb(tmp, 0xeb);
454
455         return 0;
456 }
457
458 static int enable_flash_mcp55(struct pci_dev *dev, const char *name)
459 {
460         uint8_t old, new, byte;
461         uint16_t word;
462
463         /* Set the 0-16 MB enable bits. */
464         byte = pci_read_byte(dev, 0x88);
465         byte |= 0xff;           /* 256K */
466         pci_write_byte(dev, 0x88, byte);
467         byte = pci_read_byte(dev, 0x8c);
468         byte |= 0xff;           /* 1M */
469         pci_write_byte(dev, 0x8c, byte);
470         word = pci_read_word(dev, 0x90);
471         word |= 0x7fff;         /* 16M */
472         pci_write_word(dev, 0x90, word);
473
474         old = pci_read_byte(dev, 0x6d);
475         new = old | 0x01;
476         if (new == old)
477                 return 0;
478         pci_write_byte(dev, 0x6d, new);
479
480         if (pci_read_byte(dev, 0x6d) != new) {
481                 printf
482                     ("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
483                      0x6d, new, name);
484                 return -1;
485         }
486
487         return 0;
488 }
489
490 static int enable_flash_ht1000(struct pci_dev *dev, const char *name)
491 {
492         uint8_t byte;
493
494         /* Set the 4MB enable bit. */
495         byte = pci_read_byte(dev, 0x41);
496         byte |= 0x0e;
497         pci_write_byte(dev, 0x41, byte);
498
499         byte = pci_read_byte(dev, 0x43);
500         byte |= (1 << 4);
501         pci_write_byte(dev, 0x43, byte);
502
503         return 0;
504 }
505
506 typedef struct penable {
507         uint16_t vendor, device;
508         const char *name;
509         int (*doit) (struct pci_dev *dev, const char *name);
510 } FLASH_ENABLE;
511
512 static const FLASH_ENABLE enables[] = {
513         {0x1039, 0x0630, "SIS630", enable_flash_sis630},
514         {0x8086, 0x7110, "PIIX4/PIIX4E/PIIX4M", enable_flash_piix4},
515         {0x8086, 0x7198, "Intel 440MX", enable_flash_piix4},
516         {0x8086, 0x2410, "ICH", enable_flash_ich_4e},
517         {0x8086, 0x2420, "ICH0", enable_flash_ich_4e},
518         {0x8086, 0x2440, "ICH2", enable_flash_ich_4e},
519         {0x8086, 0x244c, "ICH2-M", enable_flash_ich_4e},
520         {0x8086, 0x2480, "ICH3-S", enable_flash_ich_4e},
521         {0x8086, 0x248c, "ICH3-M", enable_flash_ich_4e},
522         {0x8086, 0x24c0, "ICH4/ICH4-L", enable_flash_ich_4e},
523         {0x8086, 0x24cc, "ICH4-M", enable_flash_ich_4e},
524         {0x8086, 0x24d0, "ICH5/ICH5R", enable_flash_ich_4e},
525         {0x8086, 0x2640, "ICH6/ICH6R", enable_flash_ich_dc},
526         {0x8086, 0x2641, "ICH6-M", enable_flash_ich_dc},
527         {0x8086, 0x27b0, "ICH7DH", enable_flash_ich_dc},
528         {0x8086, 0x27b8, "ICH7/ICH7R", enable_flash_ich_dc},
529         {0x8086, 0x27b9, "ICH7M", enable_flash_ich_dc},
530         {0x8086, 0x27bd, "ICH7MDH", enable_flash_ich_dc},
531         {0x8086, 0x2810, "ICH8/ICH8R", enable_flash_ich_dc},
532         {0x8086, 0x2812, "ICH8DH", enable_flash_ich_dc},
533         {0x8086, 0x2814, "ICH8DO", enable_flash_ich_dc},
534         {0x1106, 0x8231, "VT8231", enable_flash_vt823x},
535         {0x1106, 0x3177, "VT8235", enable_flash_vt823x},
536         {0x1106, 0x3227, "VT8237", enable_flash_vt823x},
537         {0x1106, 0x8324, "CX700", enable_flash_vt823x},
538         {0x1106, 0x0686, "VT82C686", enable_flash_amd8111},
539         {0x1078, 0x0100, "CS5530/CS5530A", enable_flash_cs5530},
540         {0x100b, 0x0510, "SC1100", enable_flash_sc1100},
541         {0x1039, 0x0008, "SIS5595", enable_flash_sis5595},
542         {0x1022, 0x2080, "AMD GEODE CS5536", enable_flash_cs5536},
543         {0x1022, 0x7468, "AMD8111", enable_flash_amd8111},
544         {0x10B9, 0x1533, "ALi M1533", enable_flash_ali_m1533},
545         {0x10de, 0x0050, "NVIDIA CK804", enable_flash_ck804},   /* LPC */
546         {0x10de, 0x0051, "NVIDIA CK804", enable_flash_ck804},   /* Pro */
547         {0x10de, 0x00d3, "NVIDIA CK804", enable_flash_ck804},   /* Slave, should not be here, to fix known bug for A01. */
548         {0x10de, 0x0260, "NVidia MCP51", enable_flash_ck804},
549         {0x10de, 0x0261, "NVidia MCP51", enable_flash_ck804},
550         {0x10de, 0x0262, "NVidia MCP51", enable_flash_ck804},
551         {0x10de, 0x0263, "NVidia MCP51", enable_flash_ck804},
552         {0x10de, 0x0360, "NVIDIA MCP55", enable_flash_mcp55},   /* M57SLI-S4 */
553         {0x10de, 0x0361, "NVIDIA MCP55", enable_flash_mcp55},   /* LPC */
554         {0x10de, 0x0362, "NVIDIA MCP55", enable_flash_mcp55},   /* LPC */
555         {0x10de, 0x0363, "NVIDIA MCP55", enable_flash_mcp55},   /* LPC */
556         {0x10de, 0x0364, "NVIDIA MCP55", enable_flash_mcp55},   /* LPC */
557         {0x10de, 0x0365, "NVIDIA MCP55", enable_flash_mcp55},   /* LPC */
558         {0x10de, 0x0366, "NVIDIA MCP55", enable_flash_mcp55},   /* LPC */
559         {0x10de, 0x0367, "NVIDIA MCP55", enable_flash_mcp55},   /* Pro */
560         {0x1002, 0x4377, "ATI SB400", enable_flash_sb400},
561         {0x1166, 0x0205, "Broadcom HT-1000", enable_flash_ht1000},
562 };
563
564 int chipset_flash_enable(void)
565 {
566         struct pci_dev *dev = 0;
567         int ret = -2;           /* Nothing! */
568         int i;
569
570         /* Now let's try to find the chipset we have... */
571         /* TODO: Use ARRAY_SIZE. */
572         for (i = 0; i < sizeof(enables) / sizeof(enables[0]); i++) {
573                 dev = pci_dev_find(enables[i].vendor, enables[i].device);
574                 if (dev)
575                         break;
576         }
577
578         if (dev) {
579                 printf("Found chipset \"%s\", enabling flash write... ",
580                        enables[i].name);
581
582                 ret = enables[i].doit(dev, enables[i].name);
583                 if (ret)
584                         printf("FAILED!\n");
585                 else
586                         printf("OK.\n");
587         }
588
589         return ret;
590 }