blob: 02d139e7d587471b597fbaf88eebd99b88a1b927 [file] [log] [blame]
ollie6a600992005-11-26 21:55:36 +00001/*
uweb25f1ea2007-08-29 17:52:32 +00002 * This file is part of the flashrom project.
ollie6a600992005-11-26 21:55:36 +00003 *
uweb25f1ea2007-08-29 17:52:32 +00004 * Copyright (C) 2000 Silicon Integrated System Corporation
stepan6d42c0f2009-08-12 09:27:45 +00005 * Copyright (C) 2005-2009 coresystems GmbH
uweb25f1ea2007-08-29 17:52:32 +00006 * Copyright (C) 2006 Uwe Hermann <uwe@hermann-uwe.de>
hailfingere76cfaf2009-12-17 15:20:01 +00007 * Copyright (C) 2007,2008,2009 Carl-Daniel Hailfinger
libva6245f02009-12-21 15:30:46 +00008 * Copyright (C) 2009 Kontron Modular Computers GmbH
ollie6a600992005-11-26 21:55:36 +00009 *
uweb25f1ea2007-08-29 17:52:32 +000010 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2 of the License.
ollie6a600992005-11-26 21:55:36 +000013 *
uweb25f1ea2007-08-29 17:52:32 +000014 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24/*
25 * Contains the chipset specific flash enables.
ollie6a600992005-11-26 21:55:36 +000026 */
27
jcrouse5915fea2007-11-13 16:45:22 +000028#define _LARGEFILE64_SOURCE
29
hailfingera83a5fe2010-05-30 22:24:40 +000030#include <unistd.h>
ollie5672ac62004-03-17 22:22:08 +000031#include <stdlib.h>
oxygene4a497262009-05-22 11:37:27 +000032#include <string.h>
jcrouse5915fea2007-11-13 16:45:22 +000033#include <sys/types.h>
34#include <sys/stat.h>
35#include <fcntl.h>
stepan927d4e22007-04-04 22:45:58 +000036#include "flash.h"
stepancb140092006-03-31 11:26:55 +000037
hailfinger324a9cc2010-05-26 01:45:41 +000038#if defined(__i386__) || defined(__x86_64__)
39
mkarcherf5f203f2010-06-13 10:16:12 +000040#define NOT_DONE_YET 1
41
uwe6ed6d952007-12-04 21:49:06 +000042static int enable_flash_ali_m1533(struct pci_dev *dev, const char *name)
uwe691ddb62007-05-20 16:16:13 +000043{
44 uint8_t tmp;
45
uwe6ed6d952007-12-04 21:49:06 +000046 /*
47 * ROM Write enable, 0xFFFC0000-0xFFFDFFFF and
48 * 0xFFFE0000-0xFFFFFFFF ROM select enable.
49 */
uwe691ddb62007-05-20 16:16:13 +000050 tmp = pci_read_byte(dev, 0x47);
51 tmp |= 0x46;
52 pci_write_byte(dev, 0x47, tmp);
53
54 return 0;
55}
56
hailfinger07e3ce02009-11-15 17:13:29 +000057static int enable_flash_sis85c496(struct pci_dev *dev, const char *name)
58{
59 uint8_t tmp;
60
61 tmp = pci_read_byte(dev, 0xd0);
62 tmp |= 0xf8;
63 pci_write_byte(dev, 0xd0, tmp);
64
65 return 0;
66}
67
68static int enable_flash_sis_mapping(struct pci_dev *dev, const char *name)
69{
70 uint8_t new, newer;
71
72 /* Extended BIOS enable = 1, Lower BIOS Enable = 1 */
73 /* This is 0xFFF8000~0xFFFF0000 decoding on SiS 540/630. */
74 new = pci_read_byte(dev, 0x40);
75 new &= (~0x04); /* No idea why we clear bit 2. */
76 new |= 0xb; /* 0x3 for some chipsets, bit 7 seems to be don't care. */
77 pci_write_byte(dev, 0x40, new);
78 newer = pci_read_byte(dev, 0x40);
79 if (newer != new) {
snelsone42c3802010-05-07 20:09:04 +000080 msg_pinfo("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x40, new, name);
81 msg_pinfo("Stuck at 0x%x\n", newer);
hailfinger07e3ce02009-11-15 17:13:29 +000082 return -1;
83 }
84 return 0;
85}
86
87static struct pci_dev *find_southbridge(uint16_t vendor, const char *name)
88{
89 struct pci_dev *sbdev;
90
91 sbdev = pci_dev_find_vendorclass(vendor, 0x0601);
92 if (!sbdev)
93 sbdev = pci_dev_find_vendorclass(vendor, 0x0680);
94 if (!sbdev)
95 sbdev = pci_dev_find_vendorclass(vendor, 0x0000);
96 if (!sbdev)
snelsone42c3802010-05-07 20:09:04 +000097 msg_perr("No southbridge found for %s!\n", name);
hailfinger07e3ce02009-11-15 17:13:29 +000098 if (sbdev)
snelsone42c3802010-05-07 20:09:04 +000099 msg_pdbg("Found southbridge %04x:%04x at %02x:%02x:%01x\n",
hailfinger07e3ce02009-11-15 17:13:29 +0000100 sbdev->vendor_id, sbdev->device_id,
101 sbdev->bus, sbdev->dev, sbdev->func);
102 return sbdev;
103}
104
105static int enable_flash_sis501(struct pci_dev *dev, const char *name)
106{
107 uint8_t tmp;
108 int ret = 0;
109 struct pci_dev *sbdev;
110
111 sbdev = find_southbridge(dev->vendor_id, name);
112 if (!sbdev)
113 return -1;
114
115 ret = enable_flash_sis_mapping(sbdev, name);
116
117 tmp = sio_read(0x22, 0x80);
118 tmp &= (~0x20);
119 tmp |= 0x4;
120 sio_write(0x22, 0x80, tmp);
121
122 tmp = sio_read(0x22, 0x70);
123 tmp &= (~0x20);
124 tmp |= 0x4;
125 sio_write(0x22, 0x70, tmp);
126
127 return ret;
128}
129
130static int enable_flash_sis5511(struct pci_dev *dev, const char *name)
131{
132 uint8_t tmp;
133 int ret = 0;
134 struct pci_dev *sbdev;
135
136 sbdev = find_southbridge(dev->vendor_id, name);
137 if (!sbdev)
138 return -1;
139
140 ret = enable_flash_sis_mapping(sbdev, name);
141
142 tmp = sio_read(0x22, 0x50);
143 tmp &= (~0x20);
144 tmp |= 0x4;
145 sio_write(0x22, 0x50, tmp);
146
147 return ret;
148}
149
hailfinger07e3ce02009-11-15 17:13:29 +0000150static int enable_flash_sis530(struct pci_dev *dev, const char *name)
151{
152 uint8_t new, newer;
153 int ret = 0;
154 struct pci_dev *sbdev;
155
156 sbdev = find_southbridge(dev->vendor_id, name);
157 if (!sbdev)
158 return -1;
159
160 ret = enable_flash_sis_mapping(sbdev, name);
161
162 new = pci_read_byte(sbdev, 0x45);
163 new &= (~0x20);
164 new |= 0x4;
165 pci_write_byte(sbdev, 0x45, new);
libv1a4a7132010-01-10 15:01:08 +0000166 newer = pci_read_byte(sbdev, 0x45);
hailfinger07e3ce02009-11-15 17:13:29 +0000167 if (newer != new) {
snelsone42c3802010-05-07 20:09:04 +0000168 msg_pinfo("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x45, new, name);
169 msg_pinfo("Stuck at 0x%x\n", newer);
hailfinger07e3ce02009-11-15 17:13:29 +0000170 ret = -1;
171 }
172
173 return ret;
174}
175
176static int enable_flash_sis540(struct pci_dev *dev, const char *name)
177{
178 uint8_t new, newer;
179 int ret = 0;
180 struct pci_dev *sbdev;
181
182 sbdev = find_southbridge(dev->vendor_id, name);
183 if (!sbdev)
184 return -1;
185
186 ret = enable_flash_sis_mapping(sbdev, name);
187
188 new = pci_read_byte(sbdev, 0x45);
189 new &= (~0x80);
190 new |= 0x40;
191 pci_write_byte(sbdev, 0x45, new);
libv1a4a7132010-01-10 15:01:08 +0000192 newer = pci_read_byte(sbdev, 0x45);
hailfinger07e3ce02009-11-15 17:13:29 +0000193 if (newer != new) {
snelsone42c3802010-05-07 20:09:04 +0000194 msg_pinfo("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x45, new, name);
195 msg_pinfo("Stuck at 0x%x\n", newer);
hailfinger07e3ce02009-11-15 17:13:29 +0000196 ret = -1;
197 }
198
199 return ret;
200}
201
uwe877ca432006-11-07 11:16:21 +0000202/* Datasheet:
203 * - Name: 82371AB PCI-TO-ISA / IDE XCELERATOR (PIIX4)
204 * - URL: http://www.intel.com/design/intarch/datashts/290562.htm
205 * - PDF: http://www.intel.com/design/intarch/datashts/29056201.pdf
206 * - Order Number: 290562-001
207 */
uwe6ed6d952007-12-04 21:49:06 +0000208static int enable_flash_piix4(struct pci_dev *dev, const char *name)
uwe12b38692006-11-05 18:26:08 +0000209{
210 uint16_t old, new;
uwef6641642007-05-09 10:17:44 +0000211 uint16_t xbcs = 0x4e; /* X-Bus Chip Select register. */
uwe12b38692006-11-05 18:26:08 +0000212
uwe56243f52009-12-08 17:26:24 +0000213 buses_supported = CHIP_BUSTYPE_PARALLEL;
214
uwe12b38692006-11-05 18:26:08 +0000215 old = pci_read_word(dev, xbcs);
216
217 /* Set bit 9: 1-Meg Extended BIOS Enable (PCI master accesses to
uwef6641642007-05-09 10:17:44 +0000218 * FFF00000-FFF7FFFF are forwarded to ISA).
uweb4e76662008-10-28 11:50:05 +0000219 * Note: This bit is reserved on PIIX/PIIX3/MPIIX.
uwef6641642007-05-09 10:17:44 +0000220 * Set bit 7: Extended BIOS Enable (PCI master accesses to
221 * FFF80000-FFFDFFFF are forwarded to ISA).
222 * Set bit 6: Lower BIOS Enable (PCI master, or ISA master accesses to
223 * the lower 64-Kbyte BIOS block (E0000-EFFFF) at the top
224 * of 1 Mbyte, or the aliases at the top of 4 Gbyte
225 * (FFFE0000-FFFEFFFF) result in the generation of BIOSCS#.
226 * Note: Accesses to FFFF0000-FFFFFFFF are always forwarded to ISA.
227 * Set bit 2: BIOSCS# Write Enable (1=enable, 0=disable).
228 */
uweb4e76662008-10-28 11:50:05 +0000229 if (dev->device_id == 0x122e || dev->device_id == 0x7000
230 || dev->device_id == 0x1234)
231 new = old | 0x00c4; /* PIIX/PIIX3/MPIIX: Bit 9 is reserved. */
uwe885bc822008-10-26 18:40:42 +0000232 else
233 new = old | 0x02c4;
uwe12b38692006-11-05 18:26:08 +0000234
235 if (new == old)
236 return 0;
237
238 pci_write_word(dev, xbcs, new);
239
240 if (pci_read_word(dev, xbcs) != new) {
snelsone42c3802010-05-07 20:09:04 +0000241 msg_pinfo("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", xbcs, new, name);
uwe12b38692006-11-05 18:26:08 +0000242 return -1;
243 }
uwebe4477b2007-08-23 16:08:21 +0000244
uwe12b38692006-11-05 18:26:08 +0000245 return 0;
246}
247
uwe6ed6d952007-12-04 21:49:06 +0000248/*
hailfinger7acfc8c2008-03-14 17:20:59 +0000249 * See ie. page 375 of "Intel I/O Controller Hub 7 (ICH7) Family Datasheet"
250 * http://download.intel.com/design/chipsets/datashts/30701303.pdf
uwe6ed6d952007-12-04 21:49:06 +0000251 */
252static int enable_flash_ich(struct pci_dev *dev, const char *name,
253 int bios_cntl)
rminnich1bcc2b22004-09-28 20:09:06 +0000254{
ollie6a600992005-11-26 21:55:36 +0000255 uint8_t old, new;
stepanca42a0b2006-09-06 15:48:48 +0000256
uwe6ed6d952007-12-04 21:49:06 +0000257 /*
258 * Note: the ICH0-ICH5 BIOS_CNTL register is actually 16 bit wide, but
uwef6641642007-05-09 10:17:44 +0000259 * just treating it as 8 bit wide seems to work fine in practice.
stepanca42a0b2006-09-06 15:48:48 +0000260 */
stepancb140092006-03-31 11:26:55 +0000261 old = pci_read_byte(dev, bios_cntl);
rminnich1bcc2b22004-09-28 20:09:06 +0000262
snelsone42c3802010-05-07 20:09:04 +0000263 msg_pdbg("\nBIOS Lock Enable: %sabled, ",
hailfinger7acfc8c2008-03-14 17:20:59 +0000264 (old & (1 << 1)) ? "en" : "dis");
snelsone42c3802010-05-07 20:09:04 +0000265 msg_pdbg("BIOS Write Enable: %sabled, ",
hailfinger7acfc8c2008-03-14 17:20:59 +0000266 (old & (1 << 0)) ? "en" : "dis");
snelsone42c3802010-05-07 20:09:04 +0000267 msg_pdbg("BIOS_CNTL is 0x%x\n", old);
hailfinger7acfc8c2008-03-14 17:20:59 +0000268
rminnich1bcc2b22004-09-28 20:09:06 +0000269 new = old | 1;
270
271 if (new == old)
272 return 0;
273
stepancb140092006-03-31 11:26:55 +0000274 pci_write_byte(dev, bios_cntl, new);
rminnich1bcc2b22004-09-28 20:09:06 +0000275
stepancb140092006-03-31 11:26:55 +0000276 if (pci_read_byte(dev, bios_cntl) != new) {
snelsone42c3802010-05-07 20:09:04 +0000277 msg_pinfo("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", bios_cntl, new, name);
rminnich1bcc2b22004-09-28 20:09:06 +0000278 return -1;
279 }
uwebe4477b2007-08-23 16:08:21 +0000280
rminnich1bcc2b22004-09-28 20:09:06 +0000281 return 0;
282}
283
uwe6ed6d952007-12-04 21:49:06 +0000284static int enable_flash_ich_4e(struct pci_dev *dev, const char *name)
stepancb140092006-03-31 11:26:55 +0000285{
hailfingerb301e652009-08-10 23:30:45 +0000286 /*
287 * Note: ICH5 has registers similar to FWH_SEL1, FWH_SEL2 and
288 * FWH_DEC_EN1, but they are called FB_SEL1, FB_SEL2, FB_DEC_EN1 and
289 * FB_DEC_EN2.
290 */
hailfinger1bf524e2010-06-20 11:04:26 +0000291 buses_supported = CHIP_BUSTYPE_FWH;
stepanca42a0b2006-09-06 15:48:48 +0000292 return enable_flash_ich(dev, name, 0x4e);
stepancb140092006-03-31 11:26:55 +0000293}
294
uwe6ed6d952007-12-04 21:49:06 +0000295static int enable_flash_ich_dc(struct pci_dev *dev, const char *name)
stepancb140092006-03-31 11:26:55 +0000296{
hailfingerb301e652009-08-10 23:30:45 +0000297 uint32_t fwh_conf;
298 int i;
hailfinger3553ccf2009-08-13 23:23:37 +0000299 char *idsel = NULL;
hailfingere76cfaf2009-12-17 15:20:01 +0000300 int tmp;
301 int max_decode_fwh_idsel = 0;
302 int max_decode_fwh_decode = 0;
303 int contiguous = 1;
hailfingerb301e652009-08-10 23:30:45 +0000304
hailfinger3553ccf2009-08-13 23:23:37 +0000305 if (programmer_param)
306 idsel = strstr(programmer_param, "fwh_idsel=");
307
308 if (idsel) {
309 idsel += strlen("fwh_idsel=");
310 fwh_conf = (uint32_t)strtoul(idsel, NULL, 0);
311
312 /* FIXME: Need to undo this on shutdown. */
snelsone42c3802010-05-07 20:09:04 +0000313 msg_pinfo("\nSetting IDSEL=0x%x for top 16 MB", fwh_conf);
hailfinger3553ccf2009-08-13 23:23:37 +0000314 pci_write_long(dev, 0xd0, fwh_conf);
315 pci_write_word(dev, 0xd4, fwh_conf);
hailfingere76cfaf2009-12-17 15:20:01 +0000316 /* FIXME: Decode settings are not changed. */
hailfinger3553ccf2009-08-13 23:23:37 +0000317 }
318
hailfingere76cfaf2009-12-17 15:20:01 +0000319 /* Ignore all legacy ranges below 1 MB.
320 * We currently only support flashing the chip which responds to
321 * IDSEL=0. To support IDSEL!=0, flashbase and decode size calculations
322 * have to be adjusted.
323 */
324 /* FWH_SEL1 */
325 fwh_conf = pci_read_long(dev, 0xd0);
326 for (i = 7; i >= 0; i--) {
327 tmp = (fwh_conf >> (i * 4)) & 0xf;
snelsone42c3802010-05-07 20:09:04 +0000328 msg_pdbg("\n0x%08x/0x%08x FWH IDSEL: 0x%x",
hailfingere76cfaf2009-12-17 15:20:01 +0000329 (0x1ff8 + i) * 0x80000,
330 (0x1ff0 + i) * 0x80000,
331 tmp);
332 if ((tmp == 0) && contiguous) {
333 max_decode_fwh_idsel = (8 - i) * 0x80000;
334 } else {
335 contiguous = 0;
336 }
337 }
338 /* FWH_SEL2 */
339 fwh_conf = pci_read_word(dev, 0xd4);
340 for (i = 3; i >= 0; i--) {
341 tmp = (fwh_conf >> (i * 4)) & 0xf;
snelsone42c3802010-05-07 20:09:04 +0000342 msg_pdbg("\n0x%08x/0x%08x FWH IDSEL: 0x%x",
hailfingere76cfaf2009-12-17 15:20:01 +0000343 (0xff4 + i) * 0x100000,
344 (0xff0 + i) * 0x100000,
345 tmp);
346 if ((tmp == 0) && contiguous) {
347 max_decode_fwh_idsel = (8 - i) * 0x100000;
348 } else {
349 contiguous = 0;
350 }
351 }
352 contiguous = 1;
353 /* FWH_DEC_EN1 */
354 fwh_conf = pci_read_word(dev, 0xd8);
355 for (i = 7; i >= 0; i--) {
356 tmp = (fwh_conf >> (i + 0x8)) & 0x1;
snelsone42c3802010-05-07 20:09:04 +0000357 msg_pdbg("\n0x%08x/0x%08x FWH decode %sabled",
hailfingere76cfaf2009-12-17 15:20:01 +0000358 (0x1ff8 + i) * 0x80000,
359 (0x1ff0 + i) * 0x80000,
360 tmp ? "en" : "dis");
mkarcher3d945082010-01-03 15:09:17 +0000361 if ((tmp == 1) && contiguous) {
hailfingere76cfaf2009-12-17 15:20:01 +0000362 max_decode_fwh_decode = (8 - i) * 0x80000;
363 } else {
364 contiguous = 0;
365 }
366 }
367 for (i = 3; i >= 0; i--) {
368 tmp = (fwh_conf >> i) & 0x1;
snelsone42c3802010-05-07 20:09:04 +0000369 msg_pdbg("\n0x%08x/0x%08x FWH decode %sabled",
hailfingere76cfaf2009-12-17 15:20:01 +0000370 (0xff4 + i) * 0x100000,
371 (0xff0 + i) * 0x100000,
372 tmp ? "en" : "dis");
mkarcher3d945082010-01-03 15:09:17 +0000373 if ((tmp == 1) && contiguous) {
hailfingere76cfaf2009-12-17 15:20:01 +0000374 max_decode_fwh_decode = (8 - i) * 0x100000;
375 } else {
376 contiguous = 0;
377 }
378 }
379 max_rom_decode.fwh = min(max_decode_fwh_idsel, max_decode_fwh_decode);
snelsone42c3802010-05-07 20:09:04 +0000380 msg_pdbg("\nMaximum FWH chip size: 0x%x bytes", max_rom_decode.fwh);
hailfingere76cfaf2009-12-17 15:20:01 +0000381
382 /* If we're called by enable_flash_ich_dc_spi, it will override
383 * buses_supported anyway.
384 */
385 buses_supported = CHIP_BUSTYPE_FWH;
stepanca42a0b2006-09-06 15:48:48 +0000386 return enable_flash_ich(dev, name, 0xdc);
stepancb140092006-03-31 11:26:55 +0000387}
388
libva6245f02009-12-21 15:30:46 +0000389static int enable_flash_poulsbo(struct pci_dev *dev, const char *name)
390{
391 uint16_t old, new;
392 int err;
393
394 if ((err = enable_flash_ich(dev, name, 0xd8)) != 0)
395 return err;
396
397 old = pci_read_byte(dev, 0xd9);
snelsone42c3802010-05-07 20:09:04 +0000398 msg_pdbg("BIOS Prefetch Enable: %sabled, ",
libva6245f02009-12-21 15:30:46 +0000399 (old & 1) ? "en" : "dis");
400 new = old & ~1;
401
402 if (new != old)
403 pci_write_byte(dev, 0xd9, new);
404
hailfinger1bf524e2010-06-20 11:04:26 +0000405 buses_supported = CHIP_BUSTYPE_FWH;
libva6245f02009-12-21 15:30:46 +0000406 return 0;
407}
408
409
stepan3bdf6182008-06-30 23:45:22 +0000410#define ICH_STRAP_RSVD 0x00
411#define ICH_STRAP_SPI 0x01
412#define ICH_STRAP_PCI 0x02
413#define ICH_STRAP_LPC 0x03
hailfinger62b38622008-05-14 14:51:22 +0000414
uwefa98ca12008-10-18 21:14:13 +0000415static int enable_flash_vt8237s_spi(struct pci_dev *dev, const char *name)
416{
ruik9bc51c02008-06-30 21:38:30 +0000417 uint32_t mmio_base;
418
hailfingere76cfaf2009-12-17 15:20:01 +0000419 /* Do we really need no write enable? */
ruik9bc51c02008-06-30 21:38:30 +0000420 mmio_base = (pci_read_long(dev, 0xbc)) << 8;
snelsone42c3802010-05-07 20:09:04 +0000421 msg_pdbg("MMIO base at = 0x%x\n", mmio_base);
stuge7c943ee2009-01-26 01:10:48 +0000422 spibar = physmap("VT8237S MMIO registers", mmio_base, 0x70);
ruik9bc51c02008-06-30 21:38:30 +0000423
snelsone42c3802010-05-07 20:09:04 +0000424 msg_pdbg("0x6c: 0x%04x (CLOCK/DEBUG)\n",
hailfinger38da6812009-05-17 15:49:24 +0000425 mmio_readw(spibar + 0x6c));
stepan3bdf6182008-06-30 23:45:22 +0000426
hailfingera916b422009-06-01 02:08:58 +0000427 /* Not sure if it speaks all these bus protocols. */
428 buses_supported = CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI;
hailfinger40167462009-05-31 17:57:34 +0000429 spi_controller = SPI_CONTROLLER_VIA;
ruik8ae0e3e2009-02-01 18:40:50 +0000430 ich_init_opcodes();
stepan3bdf6182008-06-30 23:45:22 +0000431
ruik9bc51c02008-06-30 21:38:30 +0000432 return 0;
433}
434
uwefa98ca12008-10-18 21:14:13 +0000435static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name,
436 int ich_generation)
hailfinger7acfc8c2008-03-14 17:20:59 +0000437{
stepan3bdf6182008-06-30 23:45:22 +0000438 int ret, i;
stepandbd3af12008-06-27 16:28:34 +0000439 uint8_t old, new, bbs, buc;
hailfingerbe0950f2008-11-03 00:20:22 +0000440 uint16_t spibar_offset, tmp2;
hailfinger7acfc8c2008-03-14 17:20:59 +0000441 uint32_t tmp, gcs;
hailfinger62b38622008-05-14 14:51:22 +0000442 void *rcrb;
hailfingerbe0950f2008-11-03 00:20:22 +0000443 //TODO: These names are incorrect for EP80579. For that, the solution would look like the commented line
444 //static const char *straps_names[] = {"SPI", "reserved", "reserved", "LPC" };
stepan3bdf6182008-06-30 23:45:22 +0000445 static const char *straps_names[] = { "reserved", "SPI", "PCI", "LPC" };
uwefa98ca12008-10-18 21:14:13 +0000446
stepan3bdf6182008-06-30 23:45:22 +0000447 /* Enable Flash Writes */
448 ret = enable_flash_ich_dc(dev, name);
hailfinger7acfc8c2008-03-14 17:20:59 +0000449
stepan3bdf6182008-06-30 23:45:22 +0000450 /* Get physical address of Root Complex Register Block */
451 tmp = pci_read_long(dev, 0xf0) & 0xffffc000;
snelsone42c3802010-05-07 20:09:04 +0000452 msg_pdbg("\nRoot Complex Register Block address = 0x%x\n", tmp);
stepan3bdf6182008-06-30 23:45:22 +0000453
454 /* Map RCBA to virtual memory */
stuge7c943ee2009-01-26 01:10:48 +0000455 rcrb = physmap("ICH RCRB", tmp, 0x4000);
stepan3bdf6182008-06-30 23:45:22 +0000456
hailfinger38da6812009-05-17 15:49:24 +0000457 gcs = mmio_readl(rcrb + 0x3410);
snelsone42c3802010-05-07 20:09:04 +0000458 msg_pdbg("GCS = 0x%x: ", gcs);
459 msg_pdbg("BIOS Interface Lock-Down: %sabled, ",
hailfinger7acfc8c2008-03-14 17:20:59 +0000460 (gcs & 0x1) ? "en" : "dis");
461 bbs = (gcs >> 10) & 0x3;
snelsone42c3802010-05-07 20:09:04 +0000462 msg_pdbg("BOOT BIOS Straps: 0x%x (%s)\n", bbs, straps_names[bbs]);
hailfinger62b38622008-05-14 14:51:22 +0000463
hailfinger38da6812009-05-17 15:49:24 +0000464 buc = mmio_readb(rcrb + 0x3414);
snelsone42c3802010-05-07 20:09:04 +0000465 msg_pdbg("Top Swap : %s\n",
uwefa98ca12008-10-18 21:14:13 +0000466 (buc & 1) ? "enabled (A16 inverted)" : "not enabled");
stepandbd3af12008-06-27 16:28:34 +0000467
stepan3bdf6182008-06-30 23:45:22 +0000468 /* It seems the ICH7 does not support SPI and LPC chips at the same
469 * time. At least not with our current code. So we prevent searching
470 * on ICH7 when the southbridge is strapped to LPC
471 */
472
473 if (ich_generation == 7 && bbs == ICH_STRAP_LPC) {
hailfingere76cfaf2009-12-17 15:20:01 +0000474 buses_supported = CHIP_BUSTYPE_FWH;
stepan3bdf6182008-06-30 23:45:22 +0000475 /* No further SPI initialization required */
476 return ret;
477 }
478
479 switch (ich_generation) {
480 case 7:
hailfingera916b422009-06-01 02:08:58 +0000481 buses_supported = CHIP_BUSTYPE_SPI;
hailfinger40167462009-05-31 17:57:34 +0000482 spi_controller = SPI_CONTROLLER_ICH7;
stepan3bdf6182008-06-30 23:45:22 +0000483 spibar_offset = 0x3020;
484 break;
485 case 8:
hailfingere76cfaf2009-12-17 15:20:01 +0000486 buses_supported = CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI;
hailfinger40167462009-05-31 17:57:34 +0000487 spi_controller = SPI_CONTROLLER_ICH9;
stepan3bdf6182008-06-30 23:45:22 +0000488 spibar_offset = 0x3020;
489 break;
490 case 9:
hailfinger8afaa232008-10-10 20:54:41 +0000491 case 10:
uwefa98ca12008-10-18 21:14:13 +0000492 default: /* Future version might behave the same */
hailfingere76cfaf2009-12-17 15:20:01 +0000493 buses_supported = CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI;
hailfinger40167462009-05-31 17:57:34 +0000494 spi_controller = SPI_CONTROLLER_ICH9;
stepan3bdf6182008-06-30 23:45:22 +0000495 spibar_offset = 0x3800;
496 break;
497 }
498
hailfinger62b38622008-05-14 14:51:22 +0000499 /* SPIBAR is at RCRB+0x3020 for ICH[78] and RCRB+0x3800 for ICH9. */
snelsone42c3802010-05-07 20:09:04 +0000500 msg_pdbg("SPIBAR = 0x%x + 0x%04x\n", tmp, spibar_offset);
stepandbd3af12008-06-27 16:28:34 +0000501
stepan3bdf6182008-06-30 23:45:22 +0000502 /* Assign Virtual Address */
uwefa98ca12008-10-18 21:14:13 +0000503 spibar = rcrb + spibar_offset;
hailfinger7acfc8c2008-03-14 17:20:59 +0000504
hailfinger40167462009-05-31 17:57:34 +0000505 switch (spi_controller) {
506 case SPI_CONTROLLER_ICH7:
snelsone42c3802010-05-07 20:09:04 +0000507 msg_pdbg("0x00: 0x%04x (SPIS)\n",
hailfinger38da6812009-05-17 15:49:24 +0000508 mmio_readw(spibar + 0));
snelsone42c3802010-05-07 20:09:04 +0000509 msg_pdbg("0x02: 0x%04x (SPIC)\n",
hailfinger38da6812009-05-17 15:49:24 +0000510 mmio_readw(spibar + 2));
snelsone42c3802010-05-07 20:09:04 +0000511 msg_pdbg("0x04: 0x%08x (SPIA)\n",
hailfinger38da6812009-05-17 15:49:24 +0000512 mmio_readl(spibar + 4));
uwefa98ca12008-10-18 21:14:13 +0000513 for (i = 0; i < 8; i++) {
stepandbd3af12008-06-27 16:28:34 +0000514 int offs;
515 offs = 8 + (i * 8);
snelsone42c3802010-05-07 20:09:04 +0000516 msg_pdbg("0x%02x: 0x%08x (SPID%d)\n", offs,
hailfinger38da6812009-05-17 15:49:24 +0000517 mmio_readl(spibar + offs), i);
snelsone42c3802010-05-07 20:09:04 +0000518 msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4,
hailfinger38da6812009-05-17 15:49:24 +0000519 mmio_readl(spibar + offs + 4), i);
stepandbd3af12008-06-27 16:28:34 +0000520 }
hailfingerb767c122010-05-28 15:53:08 +0000521 ichspi_bbar = mmio_readl(spibar + 0x50);
snelsone42c3802010-05-07 20:09:04 +0000522 msg_pdbg("0x50: 0x%08x (BBAR)\n",
hailfingerb767c122010-05-28 15:53:08 +0000523 ichspi_bbar);
snelsone42c3802010-05-07 20:09:04 +0000524 msg_pdbg("0x54: 0x%04x (PREOP)\n",
hailfinger38da6812009-05-17 15:49:24 +0000525 mmio_readw(spibar + 0x54));
snelsone42c3802010-05-07 20:09:04 +0000526 msg_pdbg("0x56: 0x%04x (OPTYPE)\n",
hailfinger38da6812009-05-17 15:49:24 +0000527 mmio_readw(spibar + 0x56));
snelsone42c3802010-05-07 20:09:04 +0000528 msg_pdbg("0x58: 0x%08x (OPMENU)\n",
hailfinger38da6812009-05-17 15:49:24 +0000529 mmio_readl(spibar + 0x58));
snelsone42c3802010-05-07 20:09:04 +0000530 msg_pdbg("0x5c: 0x%08x (OPMENU+4)\n",
hailfinger38da6812009-05-17 15:49:24 +0000531 mmio_readl(spibar + 0x5c));
uwefa98ca12008-10-18 21:14:13 +0000532 for (i = 0; i < 4; i++) {
stepandbd3af12008-06-27 16:28:34 +0000533 int offs;
534 offs = 0x60 + (i * 4);
snelsone42c3802010-05-07 20:09:04 +0000535 msg_pdbg("0x%02x: 0x%08x (PBR%d)\n", offs,
hailfinger38da6812009-05-17 15:49:24 +0000536 mmio_readl(spibar + offs), i);
stepandbd3af12008-06-27 16:28:34 +0000537 }
snelsone42c3802010-05-07 20:09:04 +0000538 msg_pdbg("\n");
hailfinger38da6812009-05-17 15:49:24 +0000539 if (mmio_readw(spibar) & (1 << 15)) {
snelsone42c3802010-05-07 20:09:04 +0000540 msg_pinfo("WARNING: SPI Configuration Lockdown activated.\n");
stepane1a13b92008-12-08 18:16:58 +0000541 ichspi_lock = 1;
stepandbd3af12008-06-27 16:28:34 +0000542 }
stuge7a651552008-12-15 02:32:11 +0000543 ich_init_opcodes();
stepan3bdf6182008-06-30 23:45:22 +0000544 break;
hailfinger40167462009-05-31 17:57:34 +0000545 case SPI_CONTROLLER_ICH9:
hailfinger38da6812009-05-17 15:49:24 +0000546 tmp2 = mmio_readw(spibar + 4);
snelsone42c3802010-05-07 20:09:04 +0000547 msg_pdbg("0x04: 0x%04x (HSFS)\n", tmp2);
548 msg_pdbg("FLOCKDN %i, ", (tmp2 >> 15 & 1));
549 msg_pdbg("FDV %i, ", (tmp2 >> 14) & 1);
550 msg_pdbg("FDOPSS %i, ", (tmp2 >> 13) & 1);
551 msg_pdbg("SCIP %i, ", (tmp2 >> 5) & 1);
552 msg_pdbg("BERASE %i, ", (tmp2 >> 3) & 3);
553 msg_pdbg("AEL %i, ", (tmp2 >> 2) & 1);
554 msg_pdbg("FCERR %i, ", (tmp2 >> 1) & 1);
555 msg_pdbg("FDONE %i\n", (tmp2 >> 0) & 1);
hailfingerbe0950f2008-11-03 00:20:22 +0000556
hailfinger38da6812009-05-17 15:49:24 +0000557 tmp = mmio_readl(spibar + 0x50);
snelsone42c3802010-05-07 20:09:04 +0000558 msg_pdbg("0x50: 0x%08x (FRAP)\n", tmp);
559 msg_pdbg("BMWAG %i, ", (tmp >> 24) & 0xff);
560 msg_pdbg("BMRAG %i, ", (tmp >> 16) & 0xff);
561 msg_pdbg("BRWA %i, ", (tmp >> 8) & 0xff);
562 msg_pdbg("BRRA %i\n", (tmp >> 0) & 0xff);
hailfingerbe0950f2008-11-03 00:20:22 +0000563
snelsone42c3802010-05-07 20:09:04 +0000564 msg_pdbg("0x54: 0x%08x (FREG0)\n",
hailfinger38da6812009-05-17 15:49:24 +0000565 mmio_readl(spibar + 0x54));
snelsone42c3802010-05-07 20:09:04 +0000566 msg_pdbg("0x58: 0x%08x (FREG1)\n",
hailfinger38da6812009-05-17 15:49:24 +0000567 mmio_readl(spibar + 0x58));
snelsone42c3802010-05-07 20:09:04 +0000568 msg_pdbg("0x5C: 0x%08x (FREG2)\n",
hailfinger38da6812009-05-17 15:49:24 +0000569 mmio_readl(spibar + 0x5C));
snelsone42c3802010-05-07 20:09:04 +0000570 msg_pdbg("0x60: 0x%08x (FREG3)\n",
hailfinger38da6812009-05-17 15:49:24 +0000571 mmio_readl(spibar + 0x60));
snelsone42c3802010-05-07 20:09:04 +0000572 msg_pdbg("0x64: 0x%08x (FREG4)\n",
hailfinger38da6812009-05-17 15:49:24 +0000573 mmio_readl(spibar + 0x64));
snelsone42c3802010-05-07 20:09:04 +0000574 msg_pdbg("0x74: 0x%08x (PR0)\n",
hailfinger38da6812009-05-17 15:49:24 +0000575 mmio_readl(spibar + 0x74));
snelsone42c3802010-05-07 20:09:04 +0000576 msg_pdbg("0x78: 0x%08x (PR1)\n",
hailfinger38da6812009-05-17 15:49:24 +0000577 mmio_readl(spibar + 0x78));
snelsone42c3802010-05-07 20:09:04 +0000578 msg_pdbg("0x7C: 0x%08x (PR2)\n",
hailfinger38da6812009-05-17 15:49:24 +0000579 mmio_readl(spibar + 0x7C));
snelsone42c3802010-05-07 20:09:04 +0000580 msg_pdbg("0x80: 0x%08x (PR3)\n",
hailfinger38da6812009-05-17 15:49:24 +0000581 mmio_readl(spibar + 0x80));
snelsone42c3802010-05-07 20:09:04 +0000582 msg_pdbg("0x84: 0x%08x (PR4)\n",
hailfinger38da6812009-05-17 15:49:24 +0000583 mmio_readl(spibar + 0x84));
snelsone42c3802010-05-07 20:09:04 +0000584 msg_pdbg("0x90: 0x%08x (SSFS, SSFC)\n",
hailfinger38da6812009-05-17 15:49:24 +0000585 mmio_readl(spibar + 0x90));
snelsone42c3802010-05-07 20:09:04 +0000586 msg_pdbg("0x94: 0x%04x (PREOP)\n",
hailfinger38da6812009-05-17 15:49:24 +0000587 mmio_readw(spibar + 0x94));
snelsone42c3802010-05-07 20:09:04 +0000588 msg_pdbg("0x96: 0x%04x (OPTYPE)\n",
hailfinger38da6812009-05-17 15:49:24 +0000589 mmio_readw(spibar + 0x96));
snelsone42c3802010-05-07 20:09:04 +0000590 msg_pdbg("0x98: 0x%08x (OPMENU)\n",
hailfinger38da6812009-05-17 15:49:24 +0000591 mmio_readl(spibar + 0x98));
snelsone42c3802010-05-07 20:09:04 +0000592 msg_pdbg("0x9C: 0x%08x (OPMENU+4)\n",
hailfinger38da6812009-05-17 15:49:24 +0000593 mmio_readl(spibar + 0x9C));
hailfingerb767c122010-05-28 15:53:08 +0000594 ichspi_bbar = mmio_readl(spibar + 0xA0);
snelsone42c3802010-05-07 20:09:04 +0000595 msg_pdbg("0xA0: 0x%08x (BBAR)\n",
hailfingerb767c122010-05-28 15:53:08 +0000596 ichspi_bbar);
snelsone42c3802010-05-07 20:09:04 +0000597 msg_pdbg("0xB0: 0x%08x (FDOC)\n",
hailfinger38da6812009-05-17 15:49:24 +0000598 mmio_readl(spibar + 0xB0));
stuge71659562009-01-18 06:39:32 +0000599 if (tmp2 & (1 << 15)) {
snelsone42c3802010-05-07 20:09:04 +0000600 msg_pinfo("WARNING: SPI Configuration Lockdown activated.\n");
stuge71659562009-01-18 06:39:32 +0000601 ichspi_lock = 1;
602 }
stuge4d1a5f92008-12-22 14:12:08 +0000603 ich_init_opcodes();
stepan3bdf6182008-06-30 23:45:22 +0000604 break;
605 default:
606 /* Nothing */
607 break;
stepandbd3af12008-06-27 16:28:34 +0000608 }
609
hailfinger7acfc8c2008-03-14 17:20:59 +0000610 old = pci_read_byte(dev, 0xdc);
snelsone42c3802010-05-07 20:09:04 +0000611 msg_pdbg("SPI Read Configuration: ");
hailfinger7acfc8c2008-03-14 17:20:59 +0000612 new = (old >> 2) & 0x3;
613 switch (new) {
614 case 0:
615 case 1:
616 case 2:
snelsone42c3802010-05-07 20:09:04 +0000617 msg_pdbg("prefetching %sabled, caching %sabled, ",
uwefa98ca12008-10-18 21:14:13 +0000618 (new & 0x2) ? "en" : "dis",
619 (new & 0x1) ? "dis" : "en");
hailfinger7acfc8c2008-03-14 17:20:59 +0000620 break;
621 default:
snelsone42c3802010-05-07 20:09:04 +0000622 msg_pdbg("invalid prefetching/caching settings, ");
hailfinger7acfc8c2008-03-14 17:20:59 +0000623 break;
624 }
hailfinger7acfc8c2008-03-14 17:20:59 +0000625
stepan3bdf6182008-06-30 23:45:22 +0000626 return ret;
627}
stepandbd3af12008-06-27 16:28:34 +0000628
hailfinger030d3142008-05-16 14:39:39 +0000629static int enable_flash_ich7(struct pci_dev *dev, const char *name)
hailfinger62b38622008-05-14 14:51:22 +0000630{
stepan3bdf6182008-06-30 23:45:22 +0000631 return enable_flash_ich_dc_spi(dev, name, 7);
hailfinger62b38622008-05-14 14:51:22 +0000632}
633
hailfinger030d3142008-05-16 14:39:39 +0000634static int enable_flash_ich8(struct pci_dev *dev, const char *name)
635{
stepan3bdf6182008-06-30 23:45:22 +0000636 return enable_flash_ich_dc_spi(dev, name, 8);
hailfinger030d3142008-05-16 14:39:39 +0000637}
638
hailfinger62b38622008-05-14 14:51:22 +0000639static int enable_flash_ich9(struct pci_dev *dev, const char *name)
640{
stepan3bdf6182008-06-30 23:45:22 +0000641 return enable_flash_ich_dc_spi(dev, name, 9);
hailfinger62b38622008-05-14 14:51:22 +0000642}
643
hailfinger8afaa232008-10-10 20:54:41 +0000644static int enable_flash_ich10(struct pci_dev *dev, const char *name)
645{
646 return enable_flash_ich_dc_spi(dev, name, 10);
647}
648
mkarcherf5f203f2010-06-13 10:16:12 +0000649static void via_do_byte_merge(void * arg)
650{
651 struct pci_dev * dev = arg;
652 uint8_t val;
653
654 msg_pdbg("Re-enabling byte merging\n");
655 val = pci_read_byte(dev, 0x71);
656 val |= 0x40;
657 pci_write_byte(dev, 0x71, val);
658}
659
660static int via_no_byte_merge(struct pci_dev *dev, const char *name)
661{
662 uint8_t val;
663
664 val = pci_read_byte(dev, 0x71);
665 if (val & 0x40)
666 {
667 msg_pdbg("Disabling byte merging\n");
668 val &= ~0x40;
669 pci_write_byte(dev, 0x71, val);
670 register_shutdown(via_do_byte_merge, dev);
671 }
672 return NOT_DONE_YET; /* need to find south bridge, too */
673}
674
uwe6ed6d952007-12-04 21:49:06 +0000675static int enable_flash_vt823x(struct pci_dev *dev, const char *name)
ollie5672ac62004-03-17 22:22:08 +0000676{
ollie6a600992005-11-26 21:55:36 +0000677 uint8_t val;
ollie5b621572004-03-20 16:46:10 +0000678
uwefa98ca12008-10-18 21:14:13 +0000679 /* enable ROM decode range (1MB) FFC00000 - FFFFFFFF */
stepan38b3cac2008-04-29 13:46:38 +0000680 pci_write_byte(dev, 0x41, 0x7f);
681
uwebe4477b2007-08-23 16:08:21 +0000682 /* ROM write enable */
ollie5672ac62004-03-17 22:22:08 +0000683 val = pci_read_byte(dev, 0x40);
684 val |= 0x10;
685 pci_write_byte(dev, 0x40, val);
686
687 if (pci_read_byte(dev, 0x40) != val) {
snelsone42c3802010-05-07 20:09:04 +0000688 msg_pinfo("\nWARNING: Failed to enable flash write on \"%s\"\n",
uwef6641642007-05-09 10:17:44 +0000689 name);
stepan927d4e22007-04-04 22:45:58 +0000690 return -1;
ollie5672ac62004-03-17 22:22:08 +0000691 }
uwe1f088472007-03-02 22:16:38 +0000692
libv53f58142009-12-23 00:54:26 +0000693 if (dev->device_id == 0x3227) { /* VT8237R */
694 /* All memory cycles, not just ROM ones, go to LPC. */
695 val = pci_read_byte(dev, 0x59);
696 val &= ~0x80;
697 pci_write_byte(dev, 0x59, val);
698 }
699
uwef6641642007-05-09 10:17:44 +0000700 return 0;
ollie5672ac62004-03-17 22:22:08 +0000701}
702
uwe6ed6d952007-12-04 21:49:06 +0000703static int enable_flash_cs5530(struct pci_dev *dev, const char *name)
ollie5672ac62004-03-17 22:22:08 +0000704{
uwe7a75a6a2007-06-06 21:35:45 +0000705 uint8_t reg8;
ollie5b621572004-03-20 16:46:10 +0000706
uwefa98ca12008-10-18 21:14:13 +0000707#define DECODE_CONTROL_REG2 0x5b /* F0 index 0x5b */
708#define ROM_AT_LOGIC_CONTROL_REG 0x52 /* F0 index 0x52 */
hailfingere76cfaf2009-12-17 15:20:01 +0000709#define CS5530_RESET_CONTROL_REG 0x44 /* F0 index 0x44 */
710#define CS5530_USB_SHADOW_REG 0x43 /* F0 index 0x43 */
ollie5672ac62004-03-17 22:22:08 +0000711
uwefa98ca12008-10-18 21:14:13 +0000712#define LOWER_ROM_ADDRESS_RANGE (1 << 0)
713#define ROM_WRITE_ENABLE (1 << 1)
714#define UPPER_ROM_ADDRESS_RANGE (1 << 2)
715#define BIOS_ROM_POSITIVE_DECODE (1 << 5)
hailfingere76cfaf2009-12-17 15:20:01 +0000716#define CS5530_ISA_MASTER (1 << 7)
717#define CS5530_ENABLE_SA2320 (1 << 2)
718#define CS5530_ENABLE_SA20 (1 << 6)
ollie5672ac62004-03-17 22:22:08 +0000719
hailfingere76cfaf2009-12-17 15:20:01 +0000720 buses_supported = CHIP_BUSTYPE_PARALLEL;
uwe7a75a6a2007-06-06 21:35:45 +0000721 /* Decode 0x000E0000-0x000FFFFF (128 KB), not just 64 KB, and
722 * decode 0xFF000000-0xFFFFFFFF (16 MB), not just 256 KB.
hailfingere76cfaf2009-12-17 15:20:01 +0000723 * FIXME: Should we really touch the low mapping below 1 MB? Flashrom
724 * ignores that region completely.
uwe7a75a6a2007-06-06 21:35:45 +0000725 * Make the configured ROM areas writable.
726 */
727 reg8 = pci_read_byte(dev, ROM_AT_LOGIC_CONTROL_REG);
728 reg8 |= LOWER_ROM_ADDRESS_RANGE;
729 reg8 |= UPPER_ROM_ADDRESS_RANGE;
730 reg8 |= ROM_WRITE_ENABLE;
731 pci_write_byte(dev, ROM_AT_LOGIC_CONTROL_REG, reg8);
stepan927d4e22007-04-04 22:45:58 +0000732
uwe7a75a6a2007-06-06 21:35:45 +0000733 /* Set positive decode on ROM. */
734 reg8 = pci_read_byte(dev, DECODE_CONTROL_REG2);
735 reg8 |= BIOS_ROM_POSITIVE_DECODE;
736 pci_write_byte(dev, DECODE_CONTROL_REG2, reg8);
stepan927d4e22007-04-04 22:45:58 +0000737
hailfingere76cfaf2009-12-17 15:20:01 +0000738 reg8 = pci_read_byte(dev, CS5530_RESET_CONTROL_REG);
739 if (reg8 & CS5530_ISA_MASTER) {
740 /* We have A0-A23 available. */
741 max_rom_decode.parallel = 16 * 1024 * 1024;
742 } else {
743 reg8 = pci_read_byte(dev, CS5530_USB_SHADOW_REG);
744 if (reg8 & CS5530_ENABLE_SA2320) {
745 /* We have A0-19, A20-A23 available. */
746 max_rom_decode.parallel = 16 * 1024 * 1024;
747 } else if (reg8 & CS5530_ENABLE_SA20) {
748 /* We have A0-19, A20 available. */
749 max_rom_decode.parallel = 2 * 1024 * 1024;
750 } else {
751 /* A20 and above are not active. */
752 max_rom_decode.parallel = 1024 * 1024;
753 }
754 }
755
ollie5672ac62004-03-17 22:22:08 +0000756 return 0;
757}
758
uwea730ed02008-02-08 10:10:57 +0000759/**
760 * Geode systems write protect the BIOS via RCONFs (cache settings similar
stepan6d42c0f2009-08-12 09:27:45 +0000761 * to MTRRs). To unlock, change MSR 0x1808 top byte to 0x22.
uwea730ed02008-02-08 10:10:57 +0000762 *
763 * Geode systems also write protect the NOR flash chip itself via MSR_NORF_CTL.
764 * To enable write to NOR Boot flash for the benefit of systems that have such
765 * a setup, raise MSR 0x51400018 WE_CS3 (write enable Boot Flash Chip Select).
uwea730ed02008-02-08 10:10:57 +0000766 */
uwe6ed6d952007-12-04 21:49:06 +0000767static int enable_flash_cs5536(struct pci_dev *dev, const char *name)
jcrouse5915fea2007-11-13 16:45:22 +0000768{
uwefa98ca12008-10-18 21:14:13 +0000769#define MSR_RCONF_DEFAULT 0x1808
770#define MSR_NORF_CTL 0x51400018
uwe5d33a482008-02-08 09:59:58 +0000771
stepan6d42c0f2009-08-12 09:27:45 +0000772 msr_t msr;
jcrouse5915fea2007-11-13 16:45:22 +0000773
stepan6d42c0f2009-08-12 09:27:45 +0000774 /* Geode only has a single core */
775 if (setup_cpu_msr(0))
jcrouse5915fea2007-11-13 16:45:22 +0000776 return -1;
stepan6d42c0f2009-08-12 09:27:45 +0000777
778 msr = rdmsr(MSR_RCONF_DEFAULT);
779 if ((msr.hi >> 24) != 0x22) {
780 msr.hi &= 0xfbffffff;
781 wrmsr(MSR_RCONF_DEFAULT, msr);
jcrouse5915fea2007-11-13 16:45:22 +0000782 }
uwea730ed02008-02-08 10:10:57 +0000783
stepan6d42c0f2009-08-12 09:27:45 +0000784 msr = rdmsr(MSR_NORF_CTL);
uwe5d33a482008-02-08 09:59:58 +0000785 /* Raise WE_CS3 bit. */
stepan6d42c0f2009-08-12 09:27:45 +0000786 msr.lo |= 0x08;
787 wrmsr(MSR_NORF_CTL, msr);
uwe5d33a482008-02-08 09:59:58 +0000788
stepan6d42c0f2009-08-12 09:27:45 +0000789 cleanup_cpu_msr();
uwe5d33a482008-02-08 09:59:58 +0000790
uwefa98ca12008-10-18 21:14:13 +0000791#undef MSR_RCONF_DEFAULT
792#undef MSR_NORF_CTL
jcrouse5915fea2007-11-13 16:45:22 +0000793 return 0;
794}
795
uwe6ed6d952007-12-04 21:49:06 +0000796static int enable_flash_sc1100(struct pci_dev *dev, const char *name)
ollie5672ac62004-03-17 22:22:08 +0000797{
ollie6a600992005-11-26 21:55:36 +0000798 uint8_t new;
ollie5b621572004-03-20 16:46:10 +0000799
ollie5672ac62004-03-17 22:22:08 +0000800 pci_write_byte(dev, 0x52, 0xee);
801
802 new = pci_read_byte(dev, 0x52);
803
804 if (new != 0xee) {
snelsone42c3802010-05-07 20:09:04 +0000805 msg_pinfo("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x52, new, name);
ollie5672ac62004-03-17 22:22:08 +0000806 return -1;
807 }
uwebe4477b2007-08-23 16:08:21 +0000808
ollie5672ac62004-03-17 22:22:08 +0000809 return 0;
810}
811
uwe30b2ebc2008-10-25 18:03:50 +0000812/* Works for AMD-8111, VIA VT82C586A/B, VIA VT82C686A/B. */
uwe6ed6d952007-12-04 21:49:06 +0000813static int enable_flash_amd8111(struct pci_dev *dev, const char *name)
ollie5b621572004-03-20 16:46:10 +0000814{
ollie6a600992005-11-26 21:55:36 +0000815 uint8_t old, new;
uwef6641642007-05-09 10:17:44 +0000816
uwe6ed6d952007-12-04 21:49:06 +0000817 /* Enable decoding at 0xffb00000 to 0xffffffff. */
ollie5672ac62004-03-17 22:22:08 +0000818 old = pci_read_byte(dev, 0x43);
olliefc9a03b2004-12-07 17:19:04 +0000819 new = old | 0xC0;
ollie5672ac62004-03-17 22:22:08 +0000820 if (new != old) {
821 pci_write_byte(dev, 0x43, new);
822 if (pci_read_byte(dev, 0x43) != new) {
snelsone42c3802010-05-07 20:09:04 +0000823 msg_pinfo("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x43, new, name);
ollie5672ac62004-03-17 22:22:08 +0000824 }
825 }
826
uwe30b2ebc2008-10-25 18:03:50 +0000827 /* Enable 'ROM write' bit. */
ollie5b621572004-03-20 16:46:10 +0000828 old = pci_read_byte(dev, 0x40);
ollie5672ac62004-03-17 22:22:08 +0000829 new = old | 0x01;
830 if (new == old)
831 return 0;
832 pci_write_byte(dev, 0x40, new);
833
834 if (pci_read_byte(dev, 0x40) != new) {
snelsone42c3802010-05-07 20:09:04 +0000835 msg_pinfo("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x40, new, name);
ollie5672ac62004-03-17 22:22:08 +0000836 return -1;
837 }
uwebe4477b2007-08-23 16:08:21 +0000838
ollie5672ac62004-03-17 22:22:08 +0000839 return 0;
840}
841
mjones9f59c792008-10-15 17:50:29 +0000842static int enable_flash_sb600(struct pci_dev *dev, const char *name)
843{
hailfinger1d225fe2009-05-05 22:50:07 +0000844 uint32_t tmp, prot;
mjones9f59c792008-10-15 17:50:29 +0000845 uint8_t reg;
hailfinger9fdfd872009-05-10 14:11:07 +0000846 struct pci_dev *smbus_dev;
847 int has_spi = 1;
mjones9f59c792008-10-15 17:50:29 +0000848
uwe17efbed2008-11-28 21:36:51 +0000849 /* Clear ROM protect 0-3. */
850 for (reg = 0x50; reg < 0x60; reg += 4) {
hailfinger1d225fe2009-05-05 22:50:07 +0000851 prot = pci_read_long(dev, reg);
852 /* No protection flags for this region?*/
853 if ((prot & 0x3) == 0)
854 continue;
snelsone42c3802010-05-07 20:09:04 +0000855 msg_pinfo("SB600 %s%sprotected from %u to %u\n",
hailfinger1d225fe2009-05-05 22:50:07 +0000856 (prot & 0x1) ? "write " : "",
857 (prot & 0x2) ? "read " : "",
858 (prot & 0xfffffc00),
859 (prot & 0xfffffc00) + ((prot & 0x3ff) << 8));
860 prot &= 0xfffffffc;
861 pci_write_byte(dev, reg, prot);
862 prot = pci_read_long(dev, reg);
hailfinger8c2c47c2009-05-06 13:51:44 +0000863 if (prot & 0x3)
snelsone42c3802010-05-07 20:09:04 +0000864 msg_perr("SB600 %s%sunprotect failed from %u to %u\n",
hailfinger8c2c47c2009-05-06 13:51:44 +0000865 (prot & 0x1) ? "write " : "",
866 (prot & 0x2) ? "read " : "",
867 (prot & 0xfffffc00),
868 (prot & 0xfffffc00) + ((prot & 0x3ff) << 8));
uwe17efbed2008-11-28 21:36:51 +0000869 }
870
hailfinger1d225fe2009-05-05 22:50:07 +0000871 /* Read SPI_BaseAddr */
872 tmp = pci_read_long(dev, 0xa0);
hailfinger783de7b2009-07-23 01:36:08 +0000873 tmp &= 0xffffffe0; /* remove bits 4-0 (reserved) */
snelsone42c3802010-05-07 20:09:04 +0000874 msg_pdbg("SPI base address is at 0x%x\n", tmp);
hailfinger1d225fe2009-05-05 22:50:07 +0000875
hailfinger9fdfd872009-05-10 14:11:07 +0000876 /* If the BAR has address 0, it is unlikely SPI is used. */
877 if (!tmp)
878 has_spi = 0;
879
hailfinger783de7b2009-07-23 01:36:08 +0000880 if (has_spi) {
881 /* Physical memory has to be mapped at page (4k) boundaries. */
882 sb600_spibar = physmap("SB600 SPI registers", tmp & 0xfffff000,
883 0x1000);
884 /* The low bits of the SPI base address are used as offset into
885 * the mapped page.
886 */
887 sb600_spibar += tmp & 0xfff;
888
889 tmp = pci_read_long(dev, 0xa0);
snelsone42c3802010-05-07 20:09:04 +0000890 msg_pdbg("AltSpiCSEnable=%i, SpiRomEnable=%i, "
hailfinger783de7b2009-07-23 01:36:08 +0000891 "AbortEnable=%i\n", tmp & 0x1, (tmp & 0x2) >> 1,
892 (tmp & 0x4) >> 2);
893 tmp = (pci_read_byte(dev, 0xba) & 0x4) >> 2;
snelsone42c3802010-05-07 20:09:04 +0000894 msg_pdbg("PrefetchEnSPIFromIMC=%i, ", tmp);
hailfinger783de7b2009-07-23 01:36:08 +0000895
896 tmp = pci_read_byte(dev, 0xbb);
snelsone42c3802010-05-07 20:09:04 +0000897 msg_pdbg("PrefetchEnSPIFromHost=%i, SpiOpEnInLpcMode=%i\n",
hailfinger783de7b2009-07-23 01:36:08 +0000898 tmp & 0x1, (tmp & 0x20) >> 5);
899 tmp = mmio_readl(sb600_spibar);
snelsone42c3802010-05-07 20:09:04 +0000900 msg_pdbg("SpiArbEnable=%i, SpiAccessMacRomEn=%i, "
hailfinger783de7b2009-07-23 01:36:08 +0000901 "SpiHostAccessRomEn=%i, ArbWaitCount=%i, "
902 "SpiBridgeDisable=%i, DropOneClkOnRd=%i\n",
903 (tmp >> 19) & 0x1, (tmp >> 22) & 0x1,
904 (tmp >> 23) & 0x1, (tmp >> 24) & 0x7,
905 (tmp >> 27) & 0x1, (tmp >> 28) & 0x1);
906 }
hailfinger1d225fe2009-05-05 22:50:07 +0000907
hailfinger9fdfd872009-05-10 14:11:07 +0000908 /* Look for the SMBus device. */
909 smbus_dev = pci_dev_find(0x1002, 0x4385);
910
hailfinger783de7b2009-07-23 01:36:08 +0000911 if (has_spi && !smbus_dev) {
snelsone42c3802010-05-07 20:09:04 +0000912 msg_perr("ERROR: SMBus device not found. Not enabling SPI.\n");
hailfinger9fdfd872009-05-10 14:11:07 +0000913 has_spi = 0;
hailfinger783de7b2009-07-23 01:36:08 +0000914 }
915 if (has_spi) {
hailfinger9fdfd872009-05-10 14:11:07 +0000916 /* Note about the bit tests below: If a bit is zero, the GPIO is SPI. */
917 /* GPIO11/SPI_DO and GPIO12/SPI_DI status */
918 reg = pci_read_byte(smbus_dev, 0xAB);
919 reg &= 0xC0;
snelsone42c3802010-05-07 20:09:04 +0000920 msg_pdbg("GPIO11 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_DO");
921 msg_pdbg("GPIO12 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_DI");
hailfinger9fdfd872009-05-10 14:11:07 +0000922 if (reg != 0x00)
923 has_spi = 0;
924 /* GPIO31/SPI_HOLD and GPIO32/SPI_CS status */
925 reg = pci_read_byte(smbus_dev, 0x83);
926 reg &= 0xC0;
snelsone42c3802010-05-07 20:09:04 +0000927 msg_pdbg("GPIO31 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_HOLD");
928 msg_pdbg("GPIO32 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_CS");
hailfingerf327d762009-05-15 23:36:23 +0000929 /* SPI_HOLD is not used on all boards, filter it out. */
930 if ((reg & 0x80) != 0x00)
hailfinger9fdfd872009-05-10 14:11:07 +0000931 has_spi = 0;
932 /* GPIO47/SPI_CLK status */
933 reg = pci_read_byte(smbus_dev, 0xA7);
934 reg &= 0x40;
snelsone42c3802010-05-07 20:09:04 +0000935 msg_pdbg("GPIO47 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_CLK");
hailfinger9fdfd872009-05-10 14:11:07 +0000936 if (reg != 0x00)
937 has_spi = 0;
938 }
939
hailfingera916b422009-06-01 02:08:58 +0000940 buses_supported = CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH;
941 if (has_spi) {
942 buses_supported |= CHIP_BUSTYPE_SPI;
hailfinger40167462009-05-31 17:57:34 +0000943 spi_controller = SPI_CONTROLLER_SB600;
hailfingera916b422009-06-01 02:08:58 +0000944 }
uwe17efbed2008-11-28 21:36:51 +0000945
hailfingerf327d762009-05-15 23:36:23 +0000946 /* Read ROM strap override register. */
947 OUTB(0x8f, 0xcd6);
948 reg = INB(0xcd7);
949 reg &= 0x0e;
snelsone42c3802010-05-07 20:09:04 +0000950 msg_pdbg("ROM strap override is %sactive", (reg & 0x02) ? "" : "not ");
hailfingerf327d762009-05-15 23:36:23 +0000951 if (reg & 0x02) {
952 switch ((reg & 0x0c) >> 2) {
953 case 0x00:
snelsone42c3802010-05-07 20:09:04 +0000954 msg_pdbg(": LPC");
hailfingerf327d762009-05-15 23:36:23 +0000955 break;
956 case 0x01:
snelsone42c3802010-05-07 20:09:04 +0000957 msg_pdbg(": PCI");
hailfingerf327d762009-05-15 23:36:23 +0000958 break;
959 case 0x02:
snelsone42c3802010-05-07 20:09:04 +0000960 msg_pdbg(": FWH");
hailfingerf327d762009-05-15 23:36:23 +0000961 break;
962 case 0x03:
snelsone42c3802010-05-07 20:09:04 +0000963 msg_pdbg(": SPI");
hailfingerf327d762009-05-15 23:36:23 +0000964 break;
965 }
966 }
snelsone42c3802010-05-07 20:09:04 +0000967 msg_pdbg("\n");
hailfingerf327d762009-05-15 23:36:23 +0000968
hailfinger1d225fe2009-05-05 22:50:07 +0000969 /* Force enable SPI ROM in SB600 PM register.
970 * If we enable SPI ROM here, we have to disable it after we leave.
hailfinger5a7cd6b2009-05-04 22:33:50 +0000971 * But how can we know which ROM we are going to handle? So we have
972 * to trade off. We only access LPC ROM if we boot via LPC ROM. And
hailfinger1d225fe2009-05-05 22:50:07 +0000973 * only SPI ROM if we boot via SPI ROM. If you want to access SPI on
974 * boards with LPC straps, you have to use the code below.
hailfinger5a7cd6b2009-05-04 22:33:50 +0000975 */
976 /*
uwe17efbed2008-11-28 21:36:51 +0000977 OUTB(0x8f, 0xcd6);
978 OUTB(0x0e, 0xcd7);
hailfinger5a7cd6b2009-05-04 22:33:50 +0000979 */
mjones9f59c792008-10-15 17:50:29 +0000980
981 return 0;
982}
983
libv95290b92009-05-26 09:48:28 +0000984static int enable_flash_nvidia_nforce2(struct pci_dev *dev, const char *name)
985{
uwe75f401f2009-06-02 19:54:22 +0000986 uint8_t tmp;
libv95290b92009-05-26 09:48:28 +0000987
uwe75f401f2009-06-02 19:54:22 +0000988 pci_write_byte(dev, 0x92, 0);
libv95290b92009-05-26 09:48:28 +0000989
uwe75f401f2009-06-02 19:54:22 +0000990 tmp = pci_read_byte(dev, 0x6d);
991 tmp |= 0x01;
992 pci_write_byte(dev, 0x6d, tmp);
libv95290b92009-05-26 09:48:28 +0000993
uwe75f401f2009-06-02 19:54:22 +0000994 return 0;
libv95290b92009-05-26 09:48:28 +0000995}
996
uwe6ed6d952007-12-04 21:49:06 +0000997static int enable_flash_ck804(struct pci_dev *dev, const char *name)
arch6a1225a2005-07-06 17:13:46 +0000998{
uwef6641642007-05-09 10:17:44 +0000999 uint8_t old, new;
arch6a1225a2005-07-06 17:13:46 +00001000
uwef6641642007-05-09 10:17:44 +00001001 old = pci_read_byte(dev, 0x88);
1002 new = old | 0xc0;
1003 if (new != old) {
1004 pci_write_byte(dev, 0x88, new);
1005 if (pci_read_byte(dev, 0x88) != new) {
snelsone42c3802010-05-07 20:09:04 +00001006 msg_pinfo("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x88, new, name);
uwef6641642007-05-09 10:17:44 +00001007 }
1008 }
arch6a1225a2005-07-06 17:13:46 +00001009
uwef6641642007-05-09 10:17:44 +00001010 old = pci_read_byte(dev, 0x6d);
1011 new = old | 0x01;
1012 if (new == old)
1013 return 0;
1014 pci_write_byte(dev, 0x6d, new);
1015
1016 if (pci_read_byte(dev, 0x6d) != new) {
snelsone42c3802010-05-07 20:09:04 +00001017 msg_pinfo("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x6d, new, name);
uwef6641642007-05-09 10:17:44 +00001018 return -1;
1019 }
uwebe4477b2007-08-23 16:08:21 +00001020
uwef6641642007-05-09 10:17:44 +00001021 return 0;
arch6a1225a2005-07-06 17:13:46 +00001022}
1023
uwe6ed6d952007-12-04 21:49:06 +00001024/* ATI Technologies Inc IXP SB400 PCI-ISA Bridge (rev 80) */
1025static int enable_flash_sb400(struct pci_dev *dev, const char *name)
stepancb140092006-03-31 11:26:55 +00001026{
uwef6641642007-05-09 10:17:44 +00001027 uint8_t tmp;
stepancb140092006-03-31 11:26:55 +00001028 struct pci_dev *smbusdev;
1029
uwe6ed6d952007-12-04 21:49:06 +00001030 /* Look for the SMBus device. */
hailfingere1cf8a22009-05-06 00:35:31 +00001031 smbusdev = pci_dev_find(0x1002, 0x4372);
stepan927d4e22007-04-04 22:45:58 +00001032
uwef6641642007-05-09 10:17:44 +00001033 if (!smbusdev) {
snelsone42c3802010-05-07 20:09:04 +00001034 msg_perr("ERROR: SMBus device not found. Aborting.\n");
stepancb140092006-03-31 11:26:55 +00001035 exit(1);
1036 }
stepan927d4e22007-04-04 22:45:58 +00001037
uwe6ed6d952007-12-04 21:49:06 +00001038 /* Enable some SMBus stuff. */
uwef6641642007-05-09 10:17:44 +00001039 tmp = pci_read_byte(smbusdev, 0x79);
1040 tmp |= 0x01;
stepancb140092006-03-31 11:26:55 +00001041 pci_write_byte(smbusdev, 0x79, tmp);
1042
uwe6ed6d952007-12-04 21:49:06 +00001043 /* Change southbridge. */
uwef6641642007-05-09 10:17:44 +00001044 tmp = pci_read_byte(dev, 0x48);
1045 tmp |= 0x21;
stepancb140092006-03-31 11:26:55 +00001046 pci_write_byte(dev, 0x48, tmp);
1047
uwe6ed6d952007-12-04 21:49:06 +00001048 /* Now become a bit silly. */
hailfingere1f062f2008-05-22 13:22:45 +00001049 tmp = INB(0xc6f);
1050 OUTB(tmp, 0xeb);
1051 OUTB(tmp, 0xeb);
uwef6641642007-05-09 10:17:44 +00001052 tmp |= 0x40;
hailfingere1f062f2008-05-22 13:22:45 +00001053 OUTB(tmp, 0xc6f);
1054 OUTB(tmp, 0xeb);
1055 OUTB(tmp, 0xeb);
stepancb140092006-03-31 11:26:55 +00001056
1057 return 0;
1058}
1059
uwe6ed6d952007-12-04 21:49:06 +00001060static int enable_flash_mcp55(struct pci_dev *dev, const char *name)
uwe9af0ce82007-01-22 20:21:17 +00001061{
mkarcher850a4972010-01-12 23:29:26 +00001062 uint8_t old, new, val;
1063 uint16_t wordval;
stepan927d4e22007-04-04 22:45:58 +00001064
uwe6ed6d952007-12-04 21:49:06 +00001065 /* Set the 0-16 MB enable bits. */
mkarcher850a4972010-01-12 23:29:26 +00001066 val = pci_read_byte(dev, 0x88);
1067 val |= 0xff; /* 256K */
1068 pci_write_byte(dev, 0x88, val);
1069 val = pci_read_byte(dev, 0x8c);
1070 val |= 0xff; /* 1M */
1071 pci_write_byte(dev, 0x8c, val);
1072 wordval = pci_read_word(dev, 0x90);
1073 wordval |= 0x7fff; /* 16M */
1074 pci_write_word(dev, 0x90, wordval);
stepan927d4e22007-04-04 22:45:58 +00001075
uwef6641642007-05-09 10:17:44 +00001076 old = pci_read_byte(dev, 0x6d);
1077 new = old | 0x01;
1078 if (new == old)
1079 return 0;
1080 pci_write_byte(dev, 0x6d, new);
uwe9af0ce82007-01-22 20:21:17 +00001081
uwef6641642007-05-09 10:17:44 +00001082 if (pci_read_byte(dev, 0x6d) != new) {
snelsone42c3802010-05-07 20:09:04 +00001083 msg_pinfo("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x6d, new, name);
uwef6641642007-05-09 10:17:44 +00001084 return -1;
1085 }
uwe9af0ce82007-01-22 20:21:17 +00001086
1087 return 0;
uwe9af0ce82007-01-22 20:21:17 +00001088}
1089
hailfinger2f294482010-02-18 12:24:38 +00001090/* This is a shot in the dark. Even if the code is totally bogus for some
1091 * chipsets, users will at least start to send in reports.
hailfinger0a9db8a2010-02-13 23:41:01 +00001092 */
hailfinger2f294482010-02-18 12:24:38 +00001093static int enable_flash_mcp6x_7x_common(struct pci_dev *dev, const char *name)
hailfinger0a9db8a2010-02-13 23:41:01 +00001094{
hailfinger2f294482010-02-18 12:24:38 +00001095 int ret = 0;
mkarcherd057ea92010-02-25 11:38:23 +00001096 uint8_t val;
hailfinger0a9db8a2010-02-13 23:41:01 +00001097 uint16_t status;
hailfinger2f294482010-02-18 12:24:38 +00001098 char *busname;
hailfinger0a9db8a2010-02-13 23:41:01 +00001099 uint32_t mcp_spibaraddr;
1100 void *mcp_spibar;
1101 struct pci_dev *smbusdev;
1102
hailfinger2f294482010-02-18 12:24:38 +00001103 msg_pinfo("This chipset is not really supported yet. Guesswork...\n");
1104
hailfinger0a9db8a2010-02-13 23:41:01 +00001105 /* dev is the ISA bridge. No idea what the stuff below does. */
mkarcherd057ea92010-02-25 11:38:23 +00001106 val = pci_read_byte(dev, 0x8a);
hailfinger2f294482010-02-18 12:24:38 +00001107 msg_pdbg("ISA/LPC bridge reg 0x8a contents: 0x%02x, bit 6 is %i, bit 5 "
mkarcherd057ea92010-02-25 11:38:23 +00001108 "is %i\n", val, (val >> 6) & 0x1, (val >> 5) & 0x1);
1109 switch ((val >> 5) & 0x3) {
hailfinger2f294482010-02-18 12:24:38 +00001110 case 0x0:
1111 buses_supported = CHIP_BUSTYPE_LPC;
1112 break;
1113 case 0x2:
1114 buses_supported = CHIP_BUSTYPE_SPI;
1115 break;
1116 default:
1117 buses_supported = CHIP_BUSTYPE_UNKNOWN;
1118 break;
1119 }
1120 busname = flashbuses_to_text(buses_supported);
1121 msg_pdbg("Guessed flash bus type is %s\n", busname);
1122 free(busname);
1123
1124 /* Force enable SPI and disable LPC? Not a good idea. */
hailfinger0a9db8a2010-02-13 23:41:01 +00001125#if 0
mkarcherd057ea92010-02-25 11:38:23 +00001126 val |= (1 << 6);
1127 val &= ~(1 << 5);
1128 pci_write_byte(dev, 0x8a, val);
hailfinger0a9db8a2010-02-13 23:41:01 +00001129#endif
1130
1131 /* Look for the SMBus device (SMBus PCI class) */
1132 smbusdev = pci_dev_find_vendorclass(0x10de, 0x0c05);
1133 if (!smbusdev) {
hailfinger2f294482010-02-18 12:24:38 +00001134 if (buses_supported & CHIP_BUSTYPE_SPI) {
1135 msg_perr("ERROR: SMBus device not found. Not enabling "
1136 "SPI.\n");
1137 buses_supported &= ~CHIP_BUSTYPE_SPI;
1138 ret = 1;
1139 } else {
1140 msg_pinfo("Odd. SMBus device not found.\n");
1141 }
1142 goto out_msg;
hailfinger0a9db8a2010-02-13 23:41:01 +00001143 }
1144 msg_pdbg("Found SMBus device %04x:%04x at %02x:%02x:%01x\n",
1145 smbusdev->vendor_id, smbusdev->device_id,
1146 smbusdev->bus, smbusdev->dev, smbusdev->func);
1147
1148 /* Locate the BAR where the SPI interface lives. */
1149 mcp_spibaraddr = pci_read_long(smbusdev, 0x74);
1150 msg_pdbg("SPI BAR is at 0x%08x, ", mcp_spibaraddr);
1151 /* We hope this has native alignment. We know the SPI interface (well,
1152 * a set of GPIOs that is connected to SPI flash) is at offset 0x530,
1153 * so we expect a size of at least 0x800. Clear the lower bits.
1154 * It is entirely possible that the BAR is 64k big and the low bits are
1155 * reserved for an entirely different purpose.
1156 */
1157 mcp_spibaraddr &= ~0x7ff;
1158 msg_pdbg("after clearing low bits BAR is at 0x%08x\n", mcp_spibaraddr);
1159
1160 /* Accessing a NULL pointer BAR is evil. Don't do it. */
hailfinger2f294482010-02-18 12:24:38 +00001161 if (mcp_spibaraddr && (buses_supported == CHIP_BUSTYPE_SPI)) {
hailfinger0a9db8a2010-02-13 23:41:01 +00001162 /* Map the BAR. Bytewise/wordwise access at 0x530 and 0x540. */
1163 mcp_spibar = physmap("MCP67 SPI", mcp_spibaraddr, 0x544);
1164
1165/* Guessed. If this is correct, migrate to a separate MCP67 SPI driver. */
1166#define MCP67_SPI_CS (1 << 1)
1167#define MCP67_SPI_SCK (1 << 2)
1168#define MCP67_SPI_MOSI (1 << 3)
1169#define MCP67_SPI_MISO (1 << 4)
1170#define MCP67_SPI_ENABLE (1 << 0)
1171#define MCP67_SPI_IDLE (1 << 8)
1172
1173 status = mmio_readw(mcp_spibar + 0x530);
1174 msg_pdbg("SPI control is 0x%04x, enable=%i, idle=%i\n",
1175 status, status & 0x1, (status >> 8) & 0x1);
1176 /* FIXME: Remove the physunmap once the SPI driver exists. */
1177 physunmap(mcp_spibar, 0x544);
hailfinger2f294482010-02-18 12:24:38 +00001178 } else if (!mcp_spibaraddr && (buses_supported & CHIP_BUSTYPE_SPI)) {
1179 msg_pdbg("Strange. MCP SPI BAR is invalid.\n");
1180 buses_supported &= ~CHIP_BUSTYPE_SPI;
1181 ret = 1;
1182 } else if (mcp_spibaraddr && !(buses_supported & CHIP_BUSTYPE_SPI)) {
1183 msg_pdbg("Strange. MCP SPI BAR is valid, but chipset apparently"
1184 " doesn't have SPI enabled.\n");
hailfinger0a9db8a2010-02-13 23:41:01 +00001185 } else {
hailfinger2f294482010-02-18 12:24:38 +00001186 msg_pdbg("MCP SPI is not used.\n");
hailfinger0a9db8a2010-02-13 23:41:01 +00001187 }
hailfinger2f294482010-02-18 12:24:38 +00001188out_msg:
hailfinger0a9db8a2010-02-13 23:41:01 +00001189 msg_pinfo("Please send the output of \"flashrom -V\" to "
1190 "flashrom@flashrom.org to help us finish support for your "
1191 "chipset. Thanks.\n");
1192
hailfinger2f294482010-02-18 12:24:38 +00001193 return ret;
1194}
1195
1196/**
1197 * The MCP61/MCP67 code is guesswork based on cleanroom reverse engineering.
1198 * Due to that, it only reads info and doesn't change any settings.
1199 * It is assumed that LPC chips need the MCP55 code and SPI chips need the
1200 * code provided in enable_flash_mcp6x_7x_common. Until we know for sure, call
1201 * enable_flash_mcp55 from this function only if enable_flash_mcp6x_7x_common
1202 * indicates the flash chip is LPC. Warning: enable_flash_mcp55
1203 * might make SPI flash inaccessible. The same caveat applies to SPI init
1204 * for LPC flash.
1205 */
1206static int enable_flash_mcp67(struct pci_dev *dev, const char *name)
1207{
1208 int result = 0;
1209
1210 result = enable_flash_mcp6x_7x_common(dev, name);
1211 if (result)
1212 return result;
1213
1214 /* Not sure if this is correct. No docs as usual. */
1215 switch (buses_supported) {
1216 case CHIP_BUSTYPE_LPC:
1217 result = enable_flash_mcp55(dev, name);
1218 break;
1219 case CHIP_BUSTYPE_SPI:
1220 msg_pinfo("SPI on this chipset is not supported yet.\n");
1221 buses_supported = CHIP_BUSTYPE_NONE;
1222 break;
1223 default:
1224 msg_pinfo("Something went wrong with bus type detection.\n");
1225 buses_supported = CHIP_BUSTYPE_NONE;
1226 break;
1227 }
hailfinger0a9db8a2010-02-13 23:41:01 +00001228
1229 return result;
1230}
1231
hailfinger0a9db8a2010-02-13 23:41:01 +00001232static int enable_flash_mcp7x(struct pci_dev *dev, const char *name)
1233{
hailfinger2f294482010-02-18 12:24:38 +00001234 int result = 0;
hailfinger0a9db8a2010-02-13 23:41:01 +00001235
hailfinger2f294482010-02-18 12:24:38 +00001236 result = enable_flash_mcp6x_7x_common(dev, name);
1237 if (result)
1238 return result;
hailfinger0a9db8a2010-02-13 23:41:01 +00001239
hailfinger2f294482010-02-18 12:24:38 +00001240 /* Not sure if this is correct. No docs as usual. */
1241 switch (buses_supported) {
1242 case CHIP_BUSTYPE_LPC:
1243 msg_pinfo("LPC on this chipset is not supported yet.\n");
1244 break;
1245 case CHIP_BUSTYPE_SPI:
1246 msg_pinfo("SPI on this chipset is not supported yet.\n");
1247 buses_supported = CHIP_BUSTYPE_NONE;
1248 break;
1249 default:
1250 msg_pinfo("Something went wrong with bus type detection.\n");
1251 buses_supported = CHIP_BUSTYPE_NONE;
1252 break;
hailfinger0a9db8a2010-02-13 23:41:01 +00001253 }
hailfinger0a9db8a2010-02-13 23:41:01 +00001254
hailfinger2f294482010-02-18 12:24:38 +00001255 return result;
hailfinger0a9db8a2010-02-13 23:41:01 +00001256}
1257
uwe6ed6d952007-12-04 21:49:06 +00001258static int enable_flash_ht1000(struct pci_dev *dev, const char *name)
stepanfaa9c542007-06-05 10:28:39 +00001259{
mkarcherd057ea92010-02-25 11:38:23 +00001260 uint8_t val;
stepanfaa9c542007-06-05 10:28:39 +00001261
uwefcce12f2007-06-05 15:02:18 +00001262 /* Set the 4MB enable bit. */
mkarcherd057ea92010-02-25 11:38:23 +00001263 val = pci_read_byte(dev, 0x41);
1264 val |= 0x0e;
1265 pci_write_byte(dev, 0x41, val);
stepanfaa9c542007-06-05 10:28:39 +00001266
mkarcherd057ea92010-02-25 11:38:23 +00001267 val = pci_read_byte(dev, 0x43);
1268 val |= (1 << 4);
1269 pci_write_byte(dev, 0x43, val);
stepanfaa9c542007-06-05 10:28:39 +00001270
stepanfaa9c542007-06-05 10:28:39 +00001271 return 0;
1272}
1273
stuge12ac08f2008-12-03 21:24:40 +00001274/**
1275 * Usually on the x86 architectures (and on other PC-like platforms like some
1276 * Alphas or Itanium) the system flash is mapped right below 4G. On the AMD
1277 * Elan SC520 only a small piece of the system flash is mapped there, but the
1278 * complete flash is mapped somewhere below 1G. The position can be determined
1279 * by the BOOTCS PAR register.
1280 */
1281static int get_flashbase_sc520(struct pci_dev *dev, const char *name)
1282{
1283 int i, bootcs_found = 0;
1284 uint32_t parx = 0;
1285 void *mmcr;
1286
1287 /* 1. Map MMCR */
stuge7c943ee2009-01-26 01:10:48 +00001288 mmcr = physmap("Elan SC520 MMCR", 0xfffef000, getpagesize());
stuge12ac08f2008-12-03 21:24:40 +00001289
1290 /* 2. Scan PAR0 (0x88) - PAR15 (0xc4) for
1291 * BOOTCS region (PARx[31:29] = 100b)e
1292 */
1293 for (i = 0x88; i <= 0xc4; i += 4) {
hailfinger38da6812009-05-17 15:49:24 +00001294 parx = mmio_readl(mmcr + i);
stuge12ac08f2008-12-03 21:24:40 +00001295 if ((parx >> 29) == 4) {
1296 bootcs_found = 1;
1297 break; /* BOOTCS found */
1298 }
1299 }
1300
1301 /* 3. PARx[25] = 1b --> flashbase[29:16] = PARx[13:0]
1302 * PARx[25] = 0b --> flashbase[29:12] = PARx[17:0]
1303 */
1304 if (bootcs_found) {
1305 if (parx & (1 << 25)) {
1306 parx &= (1 << 14) - 1; /* Mask [13:0] */
1307 flashbase = parx << 16;
1308 } else {
1309 parx &= (1 << 18) - 1; /* Mask [17:0] */
1310 flashbase = parx << 12;
1311 }
1312 } else {
snelsone42c3802010-05-07 20:09:04 +00001313 msg_pinfo("AMD Elan SC520 detected, but no BOOTCS. Assuming flash at 4G\n");
stuge12ac08f2008-12-03 21:24:40 +00001314 }
1315
1316 /* 4. Clean up */
hailfingerfab0bc92009-08-09 12:44:08 +00001317 physunmap(mmcr, getpagesize());
stuge12ac08f2008-12-03 21:24:40 +00001318 return 0;
1319}
1320
hailfinger324a9cc2010-05-26 01:45:41 +00001321#endif
1322
uwebda65372009-05-08 17:50:51 +00001323/* Please keep this list alphabetically sorted by vendor/device. */
uwe5f612c82009-05-16 23:42:17 +00001324const struct penable chipset_enables[] = {
hailfinger324a9cc2010-05-26 01:45:41 +00001325#if defined(__i386__) || defined(__x86_64__)
uwebda65372009-05-08 17:50:51 +00001326 {0x10B9, 0x1533, OK, "ALi", "M1533", enable_flash_ali_m1533},
1327 {0x1022, 0x7440, OK, "AMD", "AMD-768", enable_flash_amd8111},
1328 {0x1022, 0x7468, OK, "AMD", "AMD8111", enable_flash_amd8111},
1329 {0x1078, 0x0100, OK, "AMD", "CS5530(A)", enable_flash_cs5530},
1330 {0x1022, 0x2080, OK, "AMD", "CS5536", enable_flash_cs5536},
hailfinger411025f2009-09-23 02:09:23 +00001331 {0x1022, 0x2090, OK, "AMD", "CS5536", enable_flash_cs5536},
uwebda65372009-05-08 17:50:51 +00001332 {0x1022, 0x3000, OK, "AMD", "Elan SC520", get_flashbase_sc520},
1333 {0x1002, 0x438D, OK, "AMD", "SB600", enable_flash_sb600},
hailfinger0f49caa2009-09-01 22:13:42 +00001334 {0x1002, 0x439d, OK, "AMD", "SB700/SB710/SB750", enable_flash_sb600},
uwebda65372009-05-08 17:50:51 +00001335 {0x100b, 0x0510, NT, "AMD", "SC1100", enable_flash_sc1100},
1336 {0x1002, 0x4377, OK, "ATI", "SB400", enable_flash_sb400},
1337 {0x1166, 0x0205, OK, "Broadcom", "HT-1000", enable_flash_ht1000},
hailfinger7e8d9d22009-11-26 16:51:39 +00001338 {0x8086, 0x3b00, NT, "Intel", "3400 Desktop", enable_flash_ich10},
1339 {0x8086, 0x3b01, NT, "Intel", "3400 Mobile", enable_flash_ich10},
1340 {0x8086, 0x3b0d, NT, "Intel", "3400 Mobile SFF", enable_flash_ich10},
uwecb375402009-05-07 13:24:49 +00001341 {0x8086, 0x7198, OK, "Intel", "440MX", enable_flash_piix4},
uwebda65372009-05-08 17:50:51 +00001342 {0x8086, 0x25a1, OK, "Intel", "6300ESB", enable_flash_ich_4e},
1343 {0x8086, 0x2670, OK, "Intel", "631xESB/632xESB/3100", enable_flash_ich_dc},
1344 {0x8086, 0x5031, OK, "Intel", "EP80579", enable_flash_ich7},
uwecb375402009-05-07 13:24:49 +00001345 {0x8086, 0x2420, OK, "Intel", "ICH0", enable_flash_ich_4e},
uwebda65372009-05-08 17:50:51 +00001346 {0x8086, 0x3a18, OK, "Intel", "ICH10", enable_flash_ich10},
1347 {0x8086, 0x3a1a, OK, "Intel", "ICH10D", enable_flash_ich10},
1348 {0x8086, 0x3a14, OK, "Intel", "ICH10DO", enable_flash_ich10},
1349 {0x8086, 0x3a16, OK, "Intel", "ICH10R", enable_flash_ich10},
uwecb375402009-05-07 13:24:49 +00001350 {0x8086, 0x2440, OK, "Intel", "ICH2", enable_flash_ich_4e},
1351 {0x8086, 0x244c, OK, "Intel", "ICH2-M", enable_flash_ich_4e},
uwecb375402009-05-07 13:24:49 +00001352 {0x8086, 0x248c, OK, "Intel", "ICH3-M", enable_flash_ich_4e},
uwebda65372009-05-08 17:50:51 +00001353 {0x8086, 0x2480, OK, "Intel", "ICH3-S", enable_flash_ich_4e},
uwecb375402009-05-07 13:24:49 +00001354 {0x8086, 0x24c0, OK, "Intel", "ICH4/ICH4-L", enable_flash_ich_4e},
1355 {0x8086, 0x24cc, OK, "Intel", "ICH4-M", enable_flash_ich_4e},
1356 {0x8086, 0x24d0, OK, "Intel", "ICH5/ICH5R", enable_flash_ich_4e},
uwecb375402009-05-07 13:24:49 +00001357 {0x8086, 0x2640, OK, "Intel", "ICH6/ICH6R", enable_flash_ich_dc},
1358 {0x8086, 0x2641, OK, "Intel", "ICH6-M", enable_flash_ich_dc},
uwecb375402009-05-07 13:24:49 +00001359 {0x8086, 0x27b0, OK, "Intel", "ICH7DH", enable_flash_ich7},
1360 {0x8086, 0x27b8, OK, "Intel", "ICH7/ICH7R", enable_flash_ich7},
1361 {0x8086, 0x27b9, OK, "Intel", "ICH7M", enable_flash_ich7},
1362 {0x8086, 0x27bd, OK, "Intel", "ICH7MDH", enable_flash_ich7},
hailfinger3a5fff02010-01-19 02:19:27 +00001363 {0x8086, 0x27bc, OK, "Intel", "NM10", enable_flash_ich7},
uwebda65372009-05-08 17:50:51 +00001364 {0x8086, 0x2410, OK, "Intel", "ICH", enable_flash_ich_4e},
uwecb375402009-05-07 13:24:49 +00001365 {0x8086, 0x2812, OK, "Intel", "ICH8DH", enable_flash_ich8},
1366 {0x8086, 0x2814, OK, "Intel", "ICH8DO", enable_flash_ich8},
uwebda65372009-05-08 17:50:51 +00001367 {0x8086, 0x2810, OK, "Intel", "ICH8/ICH8R", enable_flash_ich8},
uwecb375402009-05-07 13:24:49 +00001368 {0x8086, 0x2815, OK, "Intel", "ICH8M", enable_flash_ich8},
uwebda65372009-05-08 17:50:51 +00001369 {0x8086, 0x2811, OK, "Intel", "ICH8M-E", enable_flash_ich8},
1370 {0x8086, 0x2918, OK, "Intel", "ICH9", enable_flash_ich9},
uwecb375402009-05-07 13:24:49 +00001371 {0x8086, 0x2912, OK, "Intel", "ICH9DH", enable_flash_ich9},
1372 {0x8086, 0x2914, OK, "Intel", "ICH9DO", enable_flash_ich9},
uwecb375402009-05-07 13:24:49 +00001373 {0x8086, 0x2919, OK, "Intel", "ICH9M", enable_flash_ich9},
uwebda65372009-05-08 17:50:51 +00001374 {0x8086, 0x2917, OK, "Intel", "ICH9M-E", enable_flash_ich9},
1375 {0x8086, 0x2916, OK, "Intel", "ICH9R", enable_flash_ich9},
hailfingerddc52962009-08-21 17:26:13 +00001376 {0x8086, 0x2910, OK, "Intel", "ICH9 Engineering Sample", enable_flash_ich9},
uwebda65372009-05-08 17:50:51 +00001377 {0x8086, 0x1234, NT, "Intel", "MPIIX", enable_flash_piix4},
1378 {0x8086, 0x7000, OK, "Intel", "PIIX3", enable_flash_piix4},
1379 {0x8086, 0x7110, OK, "Intel", "PIIX4/4E/4M", enable_flash_piix4},
1380 {0x8086, 0x122e, OK, "Intel", "PIIX", enable_flash_piix4},
libva6245f02009-12-21 15:30:46 +00001381 {0x8086, 0x8119, OK, "Intel", "Poulsbo", enable_flash_poulsbo},
libvfda283d2009-10-06 11:32:21 +00001382 {0x10de, 0x0030, OK, "NVIDIA", "nForce4/MCP4", enable_flash_nvidia_nforce2},
uwecb375402009-05-07 13:24:49 +00001383 {0x10de, 0x0050, OK, "NVIDIA", "CK804", enable_flash_ck804}, /* LPC */
1384 {0x10de, 0x0051, OK, "NVIDIA", "CK804", enable_flash_ck804}, /* Pro */
libv95290b92009-05-26 09:48:28 +00001385 {0x10de, 0x0060, OK, "NVIDIA", "NForce2", enable_flash_nvidia_nforce2},
mkarcherd2189b42010-06-12 23:07:26 +00001386 {0x10de, 0x00e0, OK, "NVIDIA", "NForce3", enable_flash_nvidia_nforce2},
uwe332b7662008-03-13 18:52:51 +00001387 /* Slave, should not be here, to fix known bug for A01. */
uwecb375402009-05-07 13:24:49 +00001388 {0x10de, 0x00d3, OK, "NVIDIA", "CK804", enable_flash_ck804},
1389 {0x10de, 0x0260, NT, "NVIDIA", "MCP51", enable_flash_ck804},
1390 {0x10de, 0x0261, NT, "NVIDIA", "MCP51", enable_flash_ck804},
1391 {0x10de, 0x0262, NT, "NVIDIA", "MCP51", enable_flash_ck804},
1392 {0x10de, 0x0263, NT, "NVIDIA", "MCP51", enable_flash_ck804},
1393 {0x10de, 0x0360, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* M57SLI*/
hailfingerdcdcf5c2010-05-22 07:27:16 +00001394 /* 10de:0361 is present in Tyan S2915 OEM systems, but not connected to
1395 * the flash chip. Instead, 10de:0364 is connected to the flash chip.
1396 * Until we have PCI device class matching or some fallback mechanism,
1397 * this is needed to get flashrom working on Tyan S2915 and maybe other
1398 * dual-MCP55 boards.
1399 */
1400#if 0
1401 {0x10de, 0x0361, NT, "NVIDIA", "MCP55", enable_flash_mcp55}, /* LPC */
1402#endif
uwecb375402009-05-07 13:24:49 +00001403 {0x10de, 0x0362, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* LPC */
1404 {0x10de, 0x0363, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* LPC */
1405 {0x10de, 0x0364, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* LPC */
1406 {0x10de, 0x0365, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* LPC */
1407 {0x10de, 0x0366, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* LPC */
1408 {0x10de, 0x0367, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* Pro */
hailfinger2f294482010-02-18 12:24:38 +00001409 {0x10de, 0x03e0, NT, "NVIDIA", "MCP61", enable_flash_mcp67},
1410 {0x10de, 0x03e1, NT, "NVIDIA", "MCP61", enable_flash_mcp67},
1411 {0x10de, 0x03e2, NT, "NVIDIA", "MCP61", enable_flash_mcp67},
1412 {0x10de, 0x03e3, NT, "NVIDIA", "MCP61", enable_flash_mcp67},
hailfinger0a9db8a2010-02-13 23:41:01 +00001413 {0x10de, 0x0440, NT, "NVIDIA", "MCP65", enable_flash_mcp7x},
1414 {0x10de, 0x0441, NT, "NVIDIA", "MCP65", enable_flash_mcp7x},
1415 {0x10de, 0x0442, NT, "NVIDIA", "MCP65", enable_flash_mcp7x},
1416 {0x10de, 0x0443, NT, "NVIDIA", "MCP65", enable_flash_mcp7x},
1417 {0x10de, 0x0548, OK, "NVIDIA", "MCP67", enable_flash_mcp67},
1418 {0x10de, 0x075c, NT, "NVIDIA", "MCP78S", enable_flash_mcp7x},
1419 {0x10de, 0x075d, NT, "NVIDIA", "MCP78S", enable_flash_mcp7x},
1420 {0x10de, 0x07d7, NT, "NVIDIA", "MCP73", enable_flash_mcp7x},
1421 {0x10de, 0x0aac, NT, "NVIDIA", "MCP79", enable_flash_mcp7x},
1422 {0x10de, 0x0aad, NT, "NVIDIA", "MCP79", enable_flash_mcp7x},
1423 {0x10de, 0x0aae, NT, "NVIDIA", "MCP79", enable_flash_mcp7x},
1424 {0x10de, 0x0aaf, NT, "NVIDIA", "MCP79", enable_flash_mcp7x},
hailfingereb468c42009-11-15 17:20:21 +00001425 {0x1039, 0x0496, NT, "SiS", "85C496+497", enable_flash_sis85c496},
1426 {0x1039, 0x0406, NT, "SiS", "501/5101/5501", enable_flash_sis501},
1427 {0x1039, 0x5511, NT, "SiS", "5511", enable_flash_sis5511},
libv1a4a7132010-01-10 15:01:08 +00001428 {0x1039, 0x5596, NT, "SiS", "5596", enable_flash_sis5511},
hailfingereb468c42009-11-15 17:20:21 +00001429 {0x1039, 0x5571, NT, "SiS", "5571", enable_flash_sis530},
1430 {0x1039, 0x5591, NT, "SiS", "5591/5592", enable_flash_sis530},
1431 {0x1039, 0x5597, NT, "SiS", "5597/5598/5581/5120", enable_flash_sis530},
1432 {0x1039, 0x0530, NT, "SiS", "530", enable_flash_sis530},
1433 {0x1039, 0x5600, NT, "SiS", "600", enable_flash_sis530},
1434 {0x1039, 0x0620, NT, "SiS", "620", enable_flash_sis530},
1435 {0x1039, 0x0540, NT, "SiS", "540", enable_flash_sis540},
libv9163dbb2009-12-09 07:43:13 +00001436 {0x1039, 0x0630, NT, "SiS", "630", enable_flash_sis540},
1437 {0x1039, 0x0635, NT, "SiS", "635", enable_flash_sis540},
1438 {0x1039, 0x0640, NT, "SiS", "640", enable_flash_sis540},
1439 {0x1039, 0x0645, NT, "SiS", "645", enable_flash_sis540},
1440 {0x1039, 0x0646, NT, "SiS", "645DX", enable_flash_sis540},
1441 {0x1039, 0x0648, NT, "SiS", "648", enable_flash_sis540},
1442 {0x1039, 0x0650, NT, "SiS", "650", enable_flash_sis540},
1443 {0x1039, 0x0651, NT, "SiS", "651", enable_flash_sis540},
1444 {0x1039, 0x0655, NT, "SiS", "655", enable_flash_sis540},
1445 {0x1039, 0x0730, NT, "SiS", "730", enable_flash_sis540},
1446 {0x1039, 0x0733, NT, "SiS", "733", enable_flash_sis540},
1447 {0x1039, 0x0735, OK, "SiS", "735", enable_flash_sis540},
1448 {0x1039, 0x0740, NT, "SiS", "740", enable_flash_sis540},
1449 {0x1039, 0x0745, NT, "SiS", "745", enable_flash_sis540},
1450 {0x1039, 0x0746, NT, "SiS", "746", enable_flash_sis540},
1451 {0x1039, 0x0748, NT, "SiS", "748", enable_flash_sis540},
1452 {0x1039, 0x0755, NT, "SiS", "755", enable_flash_sis540},
mkarcherf5f203f2010-06-13 10:16:12 +00001453 /* VIA northbridges */
1454 {0x1106, 0x0585, NT, "VIA", "VT82C585VPX", via_no_byte_merge},
1455 {0x1106, 0x0595, NT, "VIA", "VT82C595", via_no_byte_merge},
1456 {0x1106, 0x0597, NT, "VIA", "VT82C597", via_no_byte_merge},
1457 {0x1106, 0x0691, NT, "VIA", "VT82C69x", via_no_byte_merge}, /* 691, 693a, 694t, 694x checked */
1458 {0x1106, 0x0601, NT, "VIA", "VT8601/VT8601A", via_no_byte_merge},
1459 {0x1106, 0x8601, NT, "VIA", "VT8601T", via_no_byte_merge},
1460 /* VIA southbridges */
uwebda65372009-05-08 17:50:51 +00001461 {0x1106, 0x8324, OK, "VIA", "CX700", enable_flash_vt823x},
1462 {0x1106, 0x8231, NT, "VIA", "VT8231", enable_flash_vt823x},
hailfinger394bd712009-06-18 12:42:46 +00001463 {0x1106, 0x3074, NT, "VIA", "VT8233", enable_flash_vt823x},
hailfingerf91ce8f2009-12-23 21:29:18 +00001464 {0x1106, 0x3147, OK, "VIA", "VT8233A", enable_flash_vt823x},
uwebda65372009-05-08 17:50:51 +00001465 {0x1106, 0x3177, OK, "VIA", "VT8235", enable_flash_vt823x},
1466 {0x1106, 0x3227, OK, "VIA", "VT8237", enable_flash_vt823x},
1467 {0x1106, 0x3337, OK, "VIA", "VT8237A", enable_flash_vt823x},
1468 {0x1106, 0x3372, OK, "VIA", "VT8237S", enable_flash_vt8237s_spi},
uweffdcfcd2009-06-15 00:03:37 +00001469 {0x1106, 0x8353, OK, "VIA", "VX800", enable_flash_vt8237s_spi},
uwe4f206f42009-09-25 01:05:06 +00001470 {0x1106, 0x0596, OK, "VIA", "VT82C596", enable_flash_amd8111},
uwebda65372009-05-08 17:50:51 +00001471 {0x1106, 0x0586, OK, "VIA", "VT82C586A/B", enable_flash_amd8111},
1472 {0x1106, 0x0686, NT, "VIA", "VT82C686A/B", enable_flash_amd8111},
hailfinger324a9cc2010-05-26 01:45:41 +00001473#endif
uwe5f612c82009-05-16 23:42:17 +00001474 {},
ollie5672ac62004-03-17 22:22:08 +00001475};
ollie5b621572004-03-20 16:46:10 +00001476
uwef6641642007-05-09 10:17:44 +00001477int chipset_flash_enable(void)
ollie5672ac62004-03-17 22:22:08 +00001478{
uwef6641642007-05-09 10:17:44 +00001479 struct pci_dev *dev = 0;
uwe6ed6d952007-12-04 21:49:06 +00001480 int ret = -2; /* Nothing! */
uwef6641642007-05-09 10:17:44 +00001481 int i;
ollie5672ac62004-03-17 22:22:08 +00001482
uwe6ed6d952007-12-04 21:49:06 +00001483 /* Now let's try to find the chipset we have... */
uwe5f612c82009-05-16 23:42:17 +00001484 for (i = 0; chipset_enables[i].vendor_name != NULL; i++) {
1485 dev = pci_dev_find(chipset_enables[i].vendor_id,
1486 chipset_enables[i].device_id);
mkarcherf5f203f2010-06-13 10:16:12 +00001487 if (!dev)
1488 continue;
1489 if (ret != -2) {
1490 msg_pinfo("WARNING: unexpected second chipset match: "
1491 "\"%s %s\"\nignoring, please report lspci and "
1492 "board URL to flashrom@flashrom.org!\n",
1493 chipset_enables[i].vendor_name,
1494 chipset_enables[i].device_name);
1495 continue;
1496 }
snelsone42c3802010-05-07 20:09:04 +00001497 msg_pinfo("Found chipset \"%s %s\", enabling flash write... ",
uwe5f612c82009-05-16 23:42:17 +00001498 chipset_enables[i].vendor_name,
1499 chipset_enables[i].device_name);
hailfinger664cf482010-05-22 07:31:50 +00001500 msg_pdbg("chipset PCI ID is %04x:%04x, ",
1501 chipset_enables[i].vendor_id,
1502 chipset_enables[i].device_id);
uwef6641642007-05-09 10:17:44 +00001503
uwe5f612c82009-05-16 23:42:17 +00001504 ret = chipset_enables[i].doit(dev,
1505 chipset_enables[i].device_name);
mkarcherf5f203f2010-06-13 10:16:12 +00001506 if (ret == NOT_DONE_YET) {
1507 ret = -2;
1508 msg_pinfo("OK - searching further chips.\n");
1509 } else if (ret < 0)
snelsone42c3802010-05-07 20:09:04 +00001510 msg_pinfo("FAILED!\n");
mkarcherf5f203f2010-06-13 10:16:12 +00001511 else if(ret == 0)
snelsone42c3802010-05-07 20:09:04 +00001512 msg_pinfo("OK.\n");
uwef6641642007-05-09 10:17:44 +00001513 }
mkarcherf5f203f2010-06-13 10:16:12 +00001514
snelsone42c3802010-05-07 20:09:04 +00001515 msg_pinfo("This chipset supports the following protocols: %s.\n",
uwe9e6811e2009-06-28 21:47:57 +00001516 flashbuses_to_text(buses_supported));
uwef6641642007-05-09 10:17:44 +00001517
1518 return ret;
ollie5672ac62004-03-17 22:22:08 +00001519}