blob: dcf1b3c5b1f68bc90846e8fc2c69f955b4c33405 [file] [log] [blame]
Jason Wanga3f04be2008-11-28 21:36:51 +00001/*
2 * This file is part of the flashrom project.
3 *
Jason Wang13f98ce2008-11-29 15:07:15 +00004 * Copyright (C) 2008 Wang Qingpei <Qingpei.Wang@amd.com>
5 * Copyright (C) 2008 Joe Bao <Zheng.Bao@amd.com>
Uwe Hermann97e8f222009-04-13 21:35:49 +00006 * Copyright (C) 2008 Advanced Micro Devices, Inc.
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +00007 * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
Jason Wanga3f04be2008-11-28 21:36:51 +00008 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * 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
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000024#if defined(__i386__) || defined(__x86_64__)
25
Rudolf Marek70e14592013-07-25 22:58:56 +000026#include <string.h>
27#include <stdlib.h>
Jason Wanga3f04be2008-11-28 21:36:51 +000028#include "flash.h"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000029#include "programmer.h"
Patrick Georgi32508eb2012-07-20 20:35:14 +000030#include "hwaccess.h"
Jason Wanga3f04be2008-11-28 21:36:51 +000031#include "spi.h"
32
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +000033/* This struct is unused, but helps visualize the SB600 SPI BAR layout.
34 *struct sb600_spi_controller {
35 * unsigned int spi_cntrl0; / * 00h * /
36 * unsigned int restrictedcmd1; / * 04h * /
37 * unsigned int restrictedcmd2; / * 08h * /
38 * unsigned int spi_cntrl1; / * 0ch * /
39 * unsigned int spi_cmdvalue0; / * 10h * /
40 * unsigned int spi_cmdvalue1; / * 14h * /
41 * unsigned int spi_cmdvalue2; / * 18h * /
42 * unsigned int spi_fakeid; / * 1Ch * /
43 *};
44 */
Jason Wanga3f04be2008-11-28 21:36:51 +000045
Michael Karcherb05b9e12010-07-22 18:04:19 +000046static uint8_t *sb600_spibar = NULL;
Stefan Tauner463dd692013-08-08 12:00:19 +000047enum amd_chipset {
48 CHIPSET_AMD_UNKNOWN,
49 CHIPSET_SB6XX,
50 CHIPSET_SB7XX, /* SP5100 too */
51 CHIPSET_SB89XX, /* Hudson-1 too */
52 CHIPSET_HUDSON234,
53 CHIPSET_YANGTZE,
54};
55static enum amd_chipset amd_gen = CHIPSET_AMD_UNKNOWN;
56
57static void determine_generation(struct pci_dev *dev)
58{
59 amd_gen = CHIPSET_AMD_UNKNOWN;
60 if (dev->device_id == 0x780e) {
61 /* The PCI ID of the LPC bridge doesn't change between Hudson-2/3/4 and Yangtze (Kabini/Temash)
62 * although they use different SPI interfaces. */
63#ifdef USE_YANGTZE_HEURISTICS
64 /* This heuristic accesses the SPI interface MMIO BAR at locations beyond those supported by
65 * Hudson in the hope of getting 0xff readback on older chipsets and non-0xff readback on
66 * Yangtze (and newer, compatible chipsets). */
67 int i;
68 msg_pdbg("Checking for AMD Yangtze (Kabini/Temash) or later... ");
69 for (i = 0x20; i <= 0x4f; i++) {
70 if (mmio_readb(sb600_spibar + i) != 0xff) {
71 amd_gen = CHIPSET_YANGTZE;
72 msg_pdbg("found.\n");
73 return;
74 }
75 }
76 msg_pdbg("not found. Assuming Hudson.\n");
77 amd_gen = CHIPSET_HUDSON234;
78#else
79 struct pci_dev *smbus_dev = pci_dev_find(0x1022, 0x780B);
80 if (smbus_dev == NULL) {
81 msg_pdbg("No SMBus device with ID 1022:780B found.\n");
82 return;
83 }
84 uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID);
85 if (rev >= 0x11 && rev <= 0x15) {
86 amd_gen = CHIPSET_HUDSON234;
87 msg_pdbg("Hudson-2/3/4 detected.\n");
88 } else if (rev >= 0x39 && rev <= 0x3A) {
89 amd_gen = CHIPSET_YANGTZE;
90 msg_pdbg("Yangtze detected.\n");
91 } else {
92 msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n"
93 "Please report this to flashrom@flashrom.org and include this log and\n"
94 "the output of lspci -nnvx, thanks!.\n", rev);
95 }
96#endif
97 }
98}
Jason Wanga3f04be2008-11-28 21:36:51 +000099
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +0000100static void reset_internal_fifo_pointer(void)
Jason Wanga3f04be2008-11-28 21:36:51 +0000101{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000102 mmio_writeb(mmio_readb(sb600_spibar + 2) | 0x10, sb600_spibar + 2);
Jason Wanga3f04be2008-11-28 21:36:51 +0000103
Rudolf Marek70e14592013-07-25 22:58:56 +0000104 /* FIXME: This loop needs a timeout and a clearer message. */
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000105 while (mmio_readb(sb600_spibar + 0xD) & 0x7)
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000106 msg_pspew("reset\n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000107}
108
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000109static int compare_internal_fifo_pointer(uint8_t want)
110{
111 uint8_t tmp;
112
113 tmp = mmio_readb(sb600_spibar + 0xd) & 0x07;
114 want &= 0x7;
115 if (want != tmp) {
Rudolf Marek70e14592013-07-25 22:58:56 +0000116 msg_perr("FIFO pointer corruption! Pointer is %d, wanted %d\n", tmp, want);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000117 msg_perr("Something else is accessing the flash chip and "
118 "causes random corruption.\nPlease stop all "
119 "applications and drivers and IPMI which access the "
120 "flash chip.\n");
121 return 1;
122 } else {
123 msg_pspew("SB600 FIFO pointer is %d, wanted %d\n", tmp, want);
124 return 0;
125 }
126}
127
128static int reset_compare_internal_fifo_pointer(uint8_t want)
129{
130 int ret;
131
132 ret = compare_internal_fifo_pointer(want);
133 reset_internal_fifo_pointer();
134 return ret;
135}
136
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +0000137static void execute_command(void)
Jason Wanga3f04be2008-11-28 21:36:51 +0000138{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000139 mmio_writeb(mmio_readb(sb600_spibar + 2) | 1, sb600_spibar + 2);
Jason Wanga3f04be2008-11-28 21:36:51 +0000140
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000141 while (mmio_readb(sb600_spibar + 2) & 1)
Jason Wanga3f04be2008-11-28 21:36:51 +0000142 ;
143}
144
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000145static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt,
146 unsigned int readcnt,
147 const unsigned char *writearr,
148 unsigned char *readarr)
Jason Wanga3f04be2008-11-28 21:36:51 +0000149{
150 int count;
151 /* First byte is cmd which can not being sent through FIFO. */
152 unsigned char cmd = *writearr++;
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000153 unsigned int readoffby1;
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000154 unsigned char readwrite;
Jason Wanga3f04be2008-11-28 21:36:51 +0000155
156 writecnt--;
157
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000158 msg_pspew("%s, cmd=%x, writecnt=%x, readcnt=%x\n",
159 __func__, cmd, writecnt, readcnt);
Jason Wanga3f04be2008-11-28 21:36:51 +0000160
161 if (readcnt > 8) {
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000162 msg_pinfo("%s, SB600 SPI controller can not receive %d bytes, "
Carl-Daniel Hailfinger142e30f2009-07-14 10:26:56 +0000163 "it is limited to 8 bytes\n", __func__, readcnt);
164 return SPI_INVALID_LENGTH;
Jason Wanga3f04be2008-11-28 21:36:51 +0000165 }
166
167 if (writecnt > 8) {
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000168 msg_pinfo("%s, SB600 SPI controller can not send %d bytes, "
Carl-Daniel Hailfinger142e30f2009-07-14 10:26:56 +0000169 "it is limited to 8 bytes\n", __func__, writecnt);
170 return SPI_INVALID_LENGTH;
Jason Wanga3f04be2008-11-28 21:36:51 +0000171 }
172
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000173 /* This is a workaround for a bug in SB600 and SB700. If we only send
174 * an opcode and no additional data/address, the SPI controller will
175 * read one byte too few from the chip. Basically, the last byte of
176 * the chip response is discarded and will not end up in the FIFO.
177 * It is unclear if the CS# line is set high too early as well.
178 */
179 readoffby1 = (writecnt) ? 0 : 1;
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000180 readwrite = (readcnt + readoffby1) << 4 | (writecnt);
181 mmio_writeb(readwrite, sb600_spibar + 1);
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000182 mmio_writeb(cmd, sb600_spibar + 0);
Jason Wanga3f04be2008-11-28 21:36:51 +0000183
184 /* Before we use the FIFO, reset it first. */
185 reset_internal_fifo_pointer();
186
187 /* Send the write byte to FIFO. */
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000188 msg_pspew("Writing: ");
Jason Wanga3f04be2008-11-28 21:36:51 +0000189 for (count = 0; count < writecnt; count++, writearr++) {
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000190 msg_pspew("[%02x]", *writearr);
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000191 mmio_writeb(*writearr, sb600_spibar + 0xC);
Jason Wanga3f04be2008-11-28 21:36:51 +0000192 }
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000193 msg_pspew("\n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000194
195 /*
196 * We should send the data by sequence, which means we need to reset
197 * the FIFO pointer to the first byte we want to send.
198 */
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000199 if (reset_compare_internal_fifo_pointer(writecnt))
200 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000201
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000202 msg_pspew("Executing: \n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000203 execute_command();
204
205 /*
206 * After the command executed, we should find out the index of the
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000207 * received byte. Here we just reset the FIFO pointer and skip the
208 * writecnt.
209 * It would be possible to increase the FIFO pointer by one instead
210 * of reading and discarding one byte from the FIFO.
211 * The FIFO is implemented on top of an 8 byte ring buffer and the
212 * buffer is never cleared. For every byte that is shifted out after
213 * the opcode, the FIFO already stores the response from the chip.
214 * Usually, the chip will respond with 0x00 or 0xff.
Jason Wanga3f04be2008-11-28 21:36:51 +0000215 */
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000216 if (reset_compare_internal_fifo_pointer(writecnt + readcnt))
217 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000218
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000219 /* Skip the bytes we sent. */
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000220 msg_pspew("Skipping: ");
Jason Wanga3f04be2008-11-28 21:36:51 +0000221 for (count = 0; count < writecnt; count++) {
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000222 cmd = mmio_readb(sb600_spibar + 0xC);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000223 msg_pspew("[%02x]", cmd);
Jason Wanga3f04be2008-11-28 21:36:51 +0000224 }
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000225 msg_pspew("\n");
226 if (compare_internal_fifo_pointer(writecnt))
227 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000228
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000229 msg_pspew("Reading: ");
Jason Wanga3f04be2008-11-28 21:36:51 +0000230 for (count = 0; count < readcnt; count++, readarr++) {
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000231 *readarr = mmio_readb(sb600_spibar + 0xC);
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000232 msg_pspew("[%02x]", *readarr);
Jason Wanga3f04be2008-11-28 21:36:51 +0000233 }
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000234 msg_pspew("\n");
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000235 if (reset_compare_internal_fifo_pointer(readcnt + writecnt))
236 return SPI_PROGRAMMER_ERROR;
237
238 if (mmio_readb(sb600_spibar + 1) != readwrite) {
239 msg_perr("Unexpected change in SB600 read/write count!\n");
240 msg_perr("Something else is accessing the flash chip and "
241 "causes random corruption.\nPlease stop all "
242 "applications and drivers and IPMI which access the "
243 "flash chip.\n");
244 return SPI_PROGRAMMER_ERROR;
245 }
Jason Wanga3f04be2008-11-28 21:36:51 +0000246
247 return 0;
248}
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000249
Rudolf Marek70e14592013-07-25 22:58:56 +0000250static int sb600_handle_imc(struct pci_dev *dev, bool amd_imc_force)
251{
252 /* Handle IMC everywhere but sb600 which does not have one. */
253 if (dev->device_id == 0x438d)
254 return 0;
255
256 /* TODO: we should not only look at IntegratedImcPresent (LPC Dev 20, Func 3, 40h) but also at
257 * IMCEnable(Strap) and Override EcEnable(Strap) (sb8xx, sb9xx?, a50: Misc_Reg: 80h-87h;
258 * sb7xx, sp5100: PM_Reg: B0h-B1h) etc. */
259 uint8_t reg = pci_read_byte(dev, 0x40);
260 if ((reg & (1 << 7)) == 0) {
261 msg_pdbg("IMC is not active.\n");
262 return 0;
263 }
264
265 if (!amd_imc_force)
266 programmer_may_write = 0;
Stefan Tauner463dd692013-08-08 12:00:19 +0000267 msg_pinfo("Writes have been disabled for safety reasons because the presence of the IMC\n"
268 "was detected and it could interfere with accessing flash memory. Flashrom will\n"
269 "try to disable it temporarily but even then this might not be safe:\n"
Rudolf Marek70e14592013-07-25 22:58:56 +0000270 "when it is reenabled and after a reboot it expects to find working code\n"
271 "in the flash and it is unpredictable what happens if there is none.\n"
272 "\n"
273 "To be safe make sure that there is a working IMC firmware at the right\n"
274 "location in the image you intend to write and do not attempt to erase.\n"
275 "\n"
276 "You can enforce write support with the amd_imc_force programmer option.\n");
277 if (amd_imc_force)
278 msg_pinfo("Continuing with write support because the user forced us to!\n");
279
280 return amd_imc_shutdown(dev);
281}
282
Michael Karcherb9dbe482011-05-11 17:07:07 +0000283static const struct spi_programmer spi_programmer_sb600 = {
284 .type = SPI_CONTROLLER_SB600,
285 .max_data_read = 8,
286 .max_data_write = 5,
287 .command = sb600_spi_send_command,
288 .multicommand = default_spi_send_multicommand,
289 .read = default_spi_read,
290 .write_256 = default_spi_write_256,
Nico Huber7bca1262012-06-15 22:28:12 +0000291 .write_aai = default_spi_write_aai,
Michael Karcherb9dbe482011-05-11 17:07:07 +0000292};
293
Michael Karcherb05b9e12010-07-22 18:04:19 +0000294int sb600_probe_spi(struct pci_dev *dev)
295{
296 struct pci_dev *smbus_dev;
297 uint32_t tmp;
298 uint8_t reg;
Rudolf Marek70e14592013-07-25 22:58:56 +0000299 bool amd_imc_force = false;
Mathias Krausea60faab2011-01-17 07:50:42 +0000300 static const char *const speed_names[4] = {
Stefan Tauner0466c812013-06-16 10:30:08 +0000301 "66/reserved", "33", "22", "16.5"
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000302 };
303
Rudolf Marek70e14592013-07-25 22:58:56 +0000304 char *arg = extract_programmer_param("amd_imc_force");
305 if (arg && !strcmp(arg, "yes")) {
306 amd_imc_force = true;
307 msg_pspew("amd_imc_force enabled.\n");
308 } else if (arg && !strlen(arg)) {
309 msg_perr("Missing argument for amd_imc_force.\n");
310 free(arg);
311 return ERROR_FATAL;
312 } else if (arg) {
313 msg_perr("Unknown argument for amd_imc_force: \"%s\" (not \"yes\").\n", arg);
314 free(arg);
315 return ERROR_FATAL;
316 }
317 free(arg);
318
Michael Karcherb05b9e12010-07-22 18:04:19 +0000319 /* Read SPI_BaseAddr */
320 tmp = pci_read_long(dev, 0xa0);
321 tmp &= 0xffffffe0; /* remove bits 4-0 (reserved) */
322 msg_pdbg("SPI base address is at 0x%x\n", tmp);
323
324 /* If the BAR has address 0, it is unlikely SPI is used. */
325 if (!tmp)
326 return 0;
327
328 /* Physical memory has to be mapped at page (4k) boundaries. */
Stefan Tauner7fb5aa02013-08-14 15:48:44 +0000329 sb600_spibar = rphysmap("SB600 SPI registers", tmp & 0xfffff000, 0x1000);
330 if (sb600_spibar == ERROR_PTR)
331 return 1;
332
Michael Karcherb05b9e12010-07-22 18:04:19 +0000333 /* The low bits of the SPI base address are used as offset into
334 * the mapped page.
335 */
336 sb600_spibar += tmp & 0xfff;
337
Stefan Tauner463dd692013-08-08 12:00:19 +0000338 determine_generation(dev);
339
340 if (amd_gen == CHIPSET_YANGTZE) {
341 msg_perr("SPI on Kabini/Temash and newer chipsets are not yet supported.\n"
342 "Please try a newer version of flashrom.\n");
343 return ERROR_NONFATAL;
344 }
345
Michael Karcherb05b9e12010-07-22 18:04:19 +0000346 tmp = pci_read_long(dev, 0xa0);
347 msg_pdbg("AltSpiCSEnable=%i, SpiRomEnable=%i, "
348 "AbortEnable=%i\n", tmp & 0x1, (tmp & 0x2) >> 1,
349 (tmp & 0x4) >> 2);
350 tmp = (pci_read_byte(dev, 0xba) & 0x4) >> 2;
351 msg_pdbg("PrefetchEnSPIFromIMC=%i, ", tmp);
352
353 tmp = pci_read_byte(dev, 0xbb);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000354 /* FIXME: Set bit 3,6,7 if not already set.
355 * Set bit 5, otherwise SPI accesses are pointless in LPC mode.
356 * See doc 42413 AMD SB700/710/750 RPR.
357 */
Michael Karcherb05b9e12010-07-22 18:04:19 +0000358 msg_pdbg("PrefetchEnSPIFromHost=%i, SpiOpEnInLpcMode=%i\n",
359 tmp & 0x1, (tmp & 0x20) >> 5);
360 tmp = mmio_readl(sb600_spibar);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000361 /* FIXME: If SpiAccessMacRomEn or SpiHostAccessRomEn are zero on
362 * SB700 or later, reads and writes will be corrupted. Abort in this
363 * case. Make sure to avoid this check on SB600.
364 */
Stefan Tauner0466c812013-06-16 10:30:08 +0000365 msg_pdbg("(0x%08" PRIx32 ") fastReadEnable=%u, SpiArbEnable=%i, SpiAccessMacRomEn=%i, "
Michael Karcherb05b9e12010-07-22 18:04:19 +0000366 "SpiHostAccessRomEn=%i, ArbWaitCount=%i, "
367 "SpiBridgeDisable=%i, DropOneClkOnRd=%i\n",
Stefan Tauner0466c812013-06-16 10:30:08 +0000368 tmp, (tmp >> 18) & 0x1,
Michael Karcherb05b9e12010-07-22 18:04:19 +0000369 (tmp >> 19) & 0x1, (tmp >> 22) & 0x1,
370 (tmp >> 23) & 0x1, (tmp >> 24) & 0x7,
371 (tmp >> 27) & 0x1, (tmp >> 28) & 0x1);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000372 tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3;
373 msg_pdbg("NormSpeed is %s MHz\n", speed_names[tmp]);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000374
375 /* Look for the SMBus device. */
376 smbus_dev = pci_dev_find(0x1002, 0x4385);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000377 if (!smbus_dev) {
Stefan Tauner463dd692013-08-08 12:00:19 +0000378 smbus_dev = pci_dev_find(0x1022, 0x780b); /* AMD FCH */
Wang Qing Pei6e9e2ee2011-08-26 21:11:41 +0000379 if (!smbus_dev) {
380 msg_perr("ERROR: SMBus device not found. Not enabling SPI.\n");
381 return ERROR_NONFATAL;
382 }
Michael Karcherb05b9e12010-07-22 18:04:19 +0000383 }
384
385 /* Note about the bit tests below: If a bit is zero, the GPIO is SPI. */
386 /* GPIO11/SPI_DO and GPIO12/SPI_DI status */
387 reg = pci_read_byte(smbus_dev, 0xAB);
388 reg &= 0xC0;
389 msg_pdbg("GPIO11 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_DO");
390 msg_pdbg("GPIO12 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_DI");
391 if (reg != 0x00) {
392 msg_pdbg("Not enabling SPI");
393 return 0;
394 }
395 /* GPIO31/SPI_HOLD and GPIO32/SPI_CS status */
396 reg = pci_read_byte(smbus_dev, 0x83);
397 reg &= 0xC0;
398 msg_pdbg("GPIO31 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_HOLD");
399 msg_pdbg("GPIO32 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_CS");
400 /* SPI_HOLD is not used on all boards, filter it out. */
401 if ((reg & 0x80) != 0x00) {
402 msg_pdbg("Not enabling SPI");
403 return 0;
404 }
405 /* GPIO47/SPI_CLK status */
406 reg = pci_read_byte(smbus_dev, 0xA7);
407 reg &= 0x40;
408 msg_pdbg("GPIO47 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_CLK");
409 if (reg != 0x00) {
410 msg_pdbg("Not enabling SPI");
411 return 0;
412 }
413
Rudolf Marek70e14592013-07-25 22:58:56 +0000414 if (sb600_handle_imc(dev, amd_imc_force) != 0)
415 return ERROR_FATAL;
Carl-Daniel Hailfinger39446e32010-09-15 12:02:07 +0000416
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000417 /* Bring the FIFO to a clean state. */
418 reset_internal_fifo_pointer();
419
Michael Karcherb9dbe482011-05-11 17:07:07 +0000420 register_spi_programmer(&spi_programmer_sb600);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000421 return 0;
422}
423
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000424#endif