blob: 9523591aa26bdf8facd346fa65b4e14684952dfa [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;
Stefan Tauner4442b812013-09-12 15:48:35 +000060 msg_pdbg2("Trying to determine the generation of the SPI interface... ");
61 if (dev->device_id == 0x438d) {
62 amd_gen = CHIPSET_SB6XX;
63 msg_pdbg("SB6xx detected.\n");
64 } else if (dev->device_id == 0x439d) {
65 struct pci_dev *smbus_dev = pci_dev_find(0x1002, 0x4385);
66 if (smbus_dev == NULL)
67 return;
68 uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID);
69 if (rev >= 0x39 && rev <= 0x3D) {
70 amd_gen = CHIPSET_SB7XX;
71 msg_pdbg("SB7xx/SP5100 detected.\n");
72 } else if (rev >= 0x40 && rev <= 0x42) {
73 amd_gen = CHIPSET_SB89XX;
74 msg_pdbg("SB8xx/SB9xx/Hudson-1 detected.\n");
75 } else {
76 msg_pwarn("SB device found but SMBus revision 0x%02x does not match known values.\n"
77 "Assuming SB8xx/SB9xx/Hudson-1. Please send a log to flashrom@flashrom.org\n",
78 rev);
79 amd_gen = CHIPSET_SB89XX;
80 }
81 } else if (dev->device_id == 0x780e) {
Stefan Tauner463dd692013-08-08 12:00:19 +000082 /* The PCI ID of the LPC bridge doesn't change between Hudson-2/3/4 and Yangtze (Kabini/Temash)
83 * although they use different SPI interfaces. */
84#ifdef USE_YANGTZE_HEURISTICS
85 /* This heuristic accesses the SPI interface MMIO BAR at locations beyond those supported by
86 * Hudson in the hope of getting 0xff readback on older chipsets and non-0xff readback on
87 * Yangtze (and newer, compatible chipsets). */
88 int i;
89 msg_pdbg("Checking for AMD Yangtze (Kabini/Temash) or later... ");
90 for (i = 0x20; i <= 0x4f; i++) {
91 if (mmio_readb(sb600_spibar + i) != 0xff) {
92 amd_gen = CHIPSET_YANGTZE;
93 msg_pdbg("found.\n");
94 return;
95 }
96 }
97 msg_pdbg("not found. Assuming Hudson.\n");
98 amd_gen = CHIPSET_HUDSON234;
99#else
100 struct pci_dev *smbus_dev = pci_dev_find(0x1022, 0x780B);
101 if (smbus_dev == NULL) {
102 msg_pdbg("No SMBus device with ID 1022:780B found.\n");
103 return;
104 }
105 uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID);
106 if (rev >= 0x11 && rev <= 0x15) {
107 amd_gen = CHIPSET_HUDSON234;
108 msg_pdbg("Hudson-2/3/4 detected.\n");
109 } else if (rev >= 0x39 && rev <= 0x3A) {
110 amd_gen = CHIPSET_YANGTZE;
111 msg_pdbg("Yangtze detected.\n");
112 } else {
113 msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n"
114 "Please report this to flashrom@flashrom.org and include this log and\n"
115 "the output of lspci -nnvx, thanks!.\n", rev);
116 }
117#endif
Stefan Tauner4442b812013-09-12 15:48:35 +0000118 } else
119 msg_pwarn("%s: Unknown LPC device %" PRIx16 ":%" PRIx16 ".\n"
120 "Please report this to flashrom@flashrom.org and include this log and\n"
121 "the output of lspci -nnvx, thanks!\n",
122 __func__, dev->vendor_id, dev->device_id);
Stefan Tauner463dd692013-08-08 12:00:19 +0000123}
Jason Wanga3f04be2008-11-28 21:36:51 +0000124
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +0000125static void reset_internal_fifo_pointer(void)
Jason Wanga3f04be2008-11-28 21:36:51 +0000126{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000127 mmio_writeb(mmio_readb(sb600_spibar + 2) | 0x10, sb600_spibar + 2);
Jason Wanga3f04be2008-11-28 21:36:51 +0000128
Rudolf Marek70e14592013-07-25 22:58:56 +0000129 /* FIXME: This loop needs a timeout and a clearer message. */
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000130 while (mmio_readb(sb600_spibar + 0xD) & 0x7)
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000131 msg_pspew("reset\n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000132}
133
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000134static int compare_internal_fifo_pointer(uint8_t want)
135{
136 uint8_t tmp;
137
138 tmp = mmio_readb(sb600_spibar + 0xd) & 0x07;
139 want &= 0x7;
140 if (want != tmp) {
Rudolf Marek70e14592013-07-25 22:58:56 +0000141 msg_perr("FIFO pointer corruption! Pointer is %d, wanted %d\n", tmp, want);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000142 msg_perr("Something else is accessing the flash chip and "
143 "causes random corruption.\nPlease stop all "
144 "applications and drivers and IPMI which access the "
145 "flash chip.\n");
146 return 1;
147 } else {
148 msg_pspew("SB600 FIFO pointer is %d, wanted %d\n", tmp, want);
149 return 0;
150 }
151}
152
153static int reset_compare_internal_fifo_pointer(uint8_t want)
154{
155 int ret;
156
157 ret = compare_internal_fifo_pointer(want);
158 reset_internal_fifo_pointer();
159 return ret;
160}
161
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +0000162static void execute_command(void)
Jason Wanga3f04be2008-11-28 21:36:51 +0000163{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000164 mmio_writeb(mmio_readb(sb600_spibar + 2) | 1, sb600_spibar + 2);
Jason Wanga3f04be2008-11-28 21:36:51 +0000165
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000166 while (mmio_readb(sb600_spibar + 2) & 1)
Jason Wanga3f04be2008-11-28 21:36:51 +0000167 ;
168}
169
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000170static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt,
171 unsigned int readcnt,
172 const unsigned char *writearr,
173 unsigned char *readarr)
Jason Wanga3f04be2008-11-28 21:36:51 +0000174{
175 int count;
176 /* First byte is cmd which can not being sent through FIFO. */
177 unsigned char cmd = *writearr++;
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000178 unsigned int readoffby1;
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000179 unsigned char readwrite;
Jason Wanga3f04be2008-11-28 21:36:51 +0000180
181 writecnt--;
182
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000183 msg_pspew("%s, cmd=%x, writecnt=%x, readcnt=%x\n",
184 __func__, cmd, writecnt, readcnt);
Jason Wanga3f04be2008-11-28 21:36:51 +0000185
186 if (readcnt > 8) {
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000187 msg_pinfo("%s, SB600 SPI controller can not receive %d bytes, "
Carl-Daniel Hailfinger142e30f2009-07-14 10:26:56 +0000188 "it is limited to 8 bytes\n", __func__, readcnt);
189 return SPI_INVALID_LENGTH;
Jason Wanga3f04be2008-11-28 21:36:51 +0000190 }
191
192 if (writecnt > 8) {
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000193 msg_pinfo("%s, SB600 SPI controller can not send %d bytes, "
Carl-Daniel Hailfinger142e30f2009-07-14 10:26:56 +0000194 "it is limited to 8 bytes\n", __func__, writecnt);
195 return SPI_INVALID_LENGTH;
Jason Wanga3f04be2008-11-28 21:36:51 +0000196 }
197
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000198 /* This is a workaround for a bug in SB600 and SB700. If we only send
199 * an opcode and no additional data/address, the SPI controller will
200 * read one byte too few from the chip. Basically, the last byte of
201 * the chip response is discarded and will not end up in the FIFO.
202 * It is unclear if the CS# line is set high too early as well.
203 */
204 readoffby1 = (writecnt) ? 0 : 1;
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000205 readwrite = (readcnt + readoffby1) << 4 | (writecnt);
206 mmio_writeb(readwrite, sb600_spibar + 1);
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000207 mmio_writeb(cmd, sb600_spibar + 0);
Jason Wanga3f04be2008-11-28 21:36:51 +0000208
209 /* Before we use the FIFO, reset it first. */
210 reset_internal_fifo_pointer();
211
212 /* Send the write byte to FIFO. */
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000213 msg_pspew("Writing: ");
Jason Wanga3f04be2008-11-28 21:36:51 +0000214 for (count = 0; count < writecnt; count++, writearr++) {
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000215 msg_pspew("[%02x]", *writearr);
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000216 mmio_writeb(*writearr, sb600_spibar + 0xC);
Jason Wanga3f04be2008-11-28 21:36:51 +0000217 }
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000218 msg_pspew("\n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000219
220 /*
221 * We should send the data by sequence, which means we need to reset
222 * the FIFO pointer to the first byte we want to send.
223 */
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000224 if (reset_compare_internal_fifo_pointer(writecnt))
225 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000226
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000227 msg_pspew("Executing: \n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000228 execute_command();
229
230 /*
231 * After the command executed, we should find out the index of the
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000232 * received byte. Here we just reset the FIFO pointer and skip the
233 * writecnt.
234 * It would be possible to increase the FIFO pointer by one instead
235 * of reading and discarding one byte from the FIFO.
236 * The FIFO is implemented on top of an 8 byte ring buffer and the
237 * buffer is never cleared. For every byte that is shifted out after
238 * the opcode, the FIFO already stores the response from the chip.
239 * Usually, the chip will respond with 0x00 or 0xff.
Jason Wanga3f04be2008-11-28 21:36:51 +0000240 */
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000241 if (reset_compare_internal_fifo_pointer(writecnt + readcnt))
242 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000243
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000244 /* Skip the bytes we sent. */
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000245 msg_pspew("Skipping: ");
Jason Wanga3f04be2008-11-28 21:36:51 +0000246 for (count = 0; count < writecnt; count++) {
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000247 cmd = mmio_readb(sb600_spibar + 0xC);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000248 msg_pspew("[%02x]", cmd);
Jason Wanga3f04be2008-11-28 21:36:51 +0000249 }
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000250 msg_pspew("\n");
251 if (compare_internal_fifo_pointer(writecnt))
252 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000253
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000254 msg_pspew("Reading: ");
Jason Wanga3f04be2008-11-28 21:36:51 +0000255 for (count = 0; count < readcnt; count++, readarr++) {
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000256 *readarr = mmio_readb(sb600_spibar + 0xC);
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000257 msg_pspew("[%02x]", *readarr);
Jason Wanga3f04be2008-11-28 21:36:51 +0000258 }
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000259 msg_pspew("\n");
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000260 if (reset_compare_internal_fifo_pointer(readcnt + writecnt))
261 return SPI_PROGRAMMER_ERROR;
262
263 if (mmio_readb(sb600_spibar + 1) != readwrite) {
264 msg_perr("Unexpected change in SB600 read/write count!\n");
265 msg_perr("Something else is accessing the flash chip and "
266 "causes random corruption.\nPlease stop all "
267 "applications and drivers and IPMI which access the "
268 "flash chip.\n");
269 return SPI_PROGRAMMER_ERROR;
270 }
Jason Wanga3f04be2008-11-28 21:36:51 +0000271
272 return 0;
273}
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000274
Stefan Taunera6a0d202013-09-15 14:17:39 +0000275struct spispeed {
276 const char *const name;
277 const uint8_t speed;
278};
279
280static const struct spispeed spispeeds[] = {
281 { "66 MHz", 0x00 },
282 { "33 MHz", 0x01 },
283 { "22 MHz", 0x02 },
284 { "16.5 MHz", 0x03 },
285};
286
287static int set_speed(struct pci_dev *dev, const struct spispeed *spispeed)
288{
289 bool success = false;
290 uint8_t speed = spispeed->speed;
291
292 msg_pdbg("Setting SPI clock to %s (0x%x).\n", spispeed->name, speed);
293 if (amd_gen != CHIPSET_YANGTZE) {
294 rmmio_writeb((mmio_readb(sb600_spibar + 0xd) & ~(0x3 << 4)) | (speed << 4), sb600_spibar + 0xd);
295 success = (speed == ((mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3));
296 }
297
298 if (!success) {
299 msg_perr("Setting SPI clock failed.\n");
300 return 1;
301 }
302 return 0;
303}
304
305static int handle_speed(struct pci_dev *dev)
306{
307 uint32_t tmp;
308 int8_t spispeed_idx = 3; /* Default to 16.5 MHz */
309
310 /* See the chipset support matrix for SPI Base_Addr below for an explanation of the symbols used.
311 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson234 yangtze
312 * 18 rsvd <- fastReadEnable ? <- ? SpiReadMode[0]
313 * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]
314 */
315 if (amd_gen != CHIPSET_YANGTZE) {
316 if (amd_gen >= CHIPSET_SB89XX && amd_gen <= CHIPSET_HUDSON234) {
317 bool fast_read = (mmio_readl(sb600_spibar + 0x00) >> 18) & 0x1;
318 msg_pdbg("Fast Reads are %sabled\n", fast_read ? "en" : "dis");
319 if (fast_read) {
320 msg_pdbg("Disabling them temporarily.\n");
321 rmmio_writel(mmio_readl(sb600_spibar + 0x00) & ~(0x1 << 18),
322 sb600_spibar + 0x00);
323 }
324 }
325 tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3;
326 msg_pdbg("NormSpeed is %s\n", spispeeds[tmp].name);
327 }
328 return set_speed(dev, &spispeeds[spispeed_idx]);
329}
330
Rudolf Marek70e14592013-07-25 22:58:56 +0000331static int sb600_handle_imc(struct pci_dev *dev, bool amd_imc_force)
332{
333 /* Handle IMC everywhere but sb600 which does not have one. */
Stefan Tauner4442b812013-09-12 15:48:35 +0000334 if (amd_gen == CHIPSET_SB6XX)
Rudolf Marek70e14592013-07-25 22:58:56 +0000335 return 0;
336
337 /* TODO: we should not only look at IntegratedImcPresent (LPC Dev 20, Func 3, 40h) but also at
338 * IMCEnable(Strap) and Override EcEnable(Strap) (sb8xx, sb9xx?, a50: Misc_Reg: 80h-87h;
339 * sb7xx, sp5100: PM_Reg: B0h-B1h) etc. */
340 uint8_t reg = pci_read_byte(dev, 0x40);
341 if ((reg & (1 << 7)) == 0) {
342 msg_pdbg("IMC is not active.\n");
343 return 0;
344 }
345
346 if (!amd_imc_force)
347 programmer_may_write = 0;
Stefan Tauner463dd692013-08-08 12:00:19 +0000348 msg_pinfo("Writes have been disabled for safety reasons because the presence of the IMC\n"
349 "was detected and it could interfere with accessing flash memory. Flashrom will\n"
350 "try to disable it temporarily but even then this might not be safe:\n"
Rudolf Marek70e14592013-07-25 22:58:56 +0000351 "when it is reenabled and after a reboot it expects to find working code\n"
352 "in the flash and it is unpredictable what happens if there is none.\n"
353 "\n"
354 "To be safe make sure that there is a working IMC firmware at the right\n"
355 "location in the image you intend to write and do not attempt to erase.\n"
356 "\n"
357 "You can enforce write support with the amd_imc_force programmer option.\n");
358 if (amd_imc_force)
359 msg_pinfo("Continuing with write support because the user forced us to!\n");
360
361 return amd_imc_shutdown(dev);
362}
363
Michael Karcherb9dbe482011-05-11 17:07:07 +0000364static const struct spi_programmer spi_programmer_sb600 = {
365 .type = SPI_CONTROLLER_SB600,
366 .max_data_read = 8,
367 .max_data_write = 5,
368 .command = sb600_spi_send_command,
369 .multicommand = default_spi_send_multicommand,
370 .read = default_spi_read,
371 .write_256 = default_spi_write_256,
Nico Huber7bca1262012-06-15 22:28:12 +0000372 .write_aai = default_spi_write_aai,
Michael Karcherb9dbe482011-05-11 17:07:07 +0000373};
374
Michael Karcherb05b9e12010-07-22 18:04:19 +0000375int sb600_probe_spi(struct pci_dev *dev)
376{
377 struct pci_dev *smbus_dev;
378 uint32_t tmp;
379 uint8_t reg;
Rudolf Marek70e14592013-07-25 22:58:56 +0000380 bool amd_imc_force = false;
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000381
Rudolf Marek70e14592013-07-25 22:58:56 +0000382 char *arg = extract_programmer_param("amd_imc_force");
383 if (arg && !strcmp(arg, "yes")) {
384 amd_imc_force = true;
385 msg_pspew("amd_imc_force enabled.\n");
386 } else if (arg && !strlen(arg)) {
387 msg_perr("Missing argument for amd_imc_force.\n");
388 free(arg);
389 return ERROR_FATAL;
390 } else if (arg) {
391 msg_perr("Unknown argument for amd_imc_force: \"%s\" (not \"yes\").\n", arg);
392 free(arg);
393 return ERROR_FATAL;
394 }
395 free(arg);
396
Michael Karcherb05b9e12010-07-22 18:04:19 +0000397 /* Read SPI_BaseAddr */
398 tmp = pci_read_long(dev, 0xa0);
399 tmp &= 0xffffffe0; /* remove bits 4-0 (reserved) */
400 msg_pdbg("SPI base address is at 0x%x\n", tmp);
401
402 /* If the BAR has address 0, it is unlikely SPI is used. */
403 if (!tmp)
404 return 0;
405
406 /* Physical memory has to be mapped at page (4k) boundaries. */
Stefan Tauner7fb5aa02013-08-14 15:48:44 +0000407 sb600_spibar = rphysmap("SB600 SPI registers", tmp & 0xfffff000, 0x1000);
408 if (sb600_spibar == ERROR_PTR)
Niklas Söderlund5d307202013-09-14 09:02:27 +0000409 return ERROR_FATAL;
Stefan Tauner7fb5aa02013-08-14 15:48:44 +0000410
Michael Karcherb05b9e12010-07-22 18:04:19 +0000411 /* The low bits of the SPI base address are used as offset into
412 * the mapped page.
413 */
414 sb600_spibar += tmp & 0xfff;
415
Stefan Tauner463dd692013-08-08 12:00:19 +0000416 determine_generation(dev);
Stefan Tauner4442b812013-09-12 15:48:35 +0000417 if (amd_gen == CHIPSET_AMD_UNKNOWN) {
418 msg_perr("Could not determine chipset generation.");
419 return ERROR_NONFATAL;
420 }
Stefan Tauner463dd692013-08-08 12:00:19 +0000421
422 if (amd_gen == CHIPSET_YANGTZE) {
423 msg_perr("SPI on Kabini/Temash and newer chipsets are not yet supported.\n"
424 "Please try a newer version of flashrom.\n");
425 return ERROR_NONFATAL;
426 }
427
Stefan Tauner4442b812013-09-12 15:48:35 +0000428 /* How to read the following table and similar ones in this file:
429 * "?" means we have no datasheet for this chipset generation or it doesn't have any relevant info.
430 * "<-" means the bit/register meaning is identical to the next non-"?" chipset to the left. "<-" thus
431 * never refers to another "?".
432 * If a "?" chipset is between two chipsets with identical meaning, we assume the meaning didn't change
433 * twice in between, i.e. the meaning is unchanged for the "?" chipset. Usually we assume that
434 * succeeding hardware supports the same functionality as its predecessor unless proven different by
435 * tests or documentation, hence "?" will often be implemented equally to "<-".
436 *
437 * Chipset support matrix for SPI Base_Addr (LPC PCI reg 0xa0)
438 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson2+ yangtze
439 * 3 rsvd <- <- ? <- ? RouteTpm2Spi
440 * 2 rsvd AbortEnable rsvd ? <- ? <-
441 * 1 rsvd SpiRomEnable <- ? <- ? <-
442 * 0 rsvd AltSpiCSEnable rsvd ? <- ? <-
443 */
444 if (amd_gen >= CHIPSET_SB7XX) {
445 tmp = pci_read_long(dev, 0xa0);
446 msg_pdbg("SpiRomEnable=%i", (tmp >> 1) & 0x1);
447 if (amd_gen == CHIPSET_SB7XX)
448 msg_pdbg(", AltSpiCSEnable=%i, AbortEnable=%i", tmp & 0x1, (tmp >> 2) & 0x1);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000449
Stefan Tauner4442b812013-09-12 15:48:35 +0000450 tmp = pci_read_byte(dev, 0xba);
451 msg_pdbg(", PrefetchEnSPIFromIMC=%i", (tmp & 0x4) >> 2);
452
453 tmp = pci_read_byte(dev, 0xbb);
454 /* FIXME: Set bit 3,6,7 if not already set.
455 * Set bit 5, otherwise SPI accesses are pointless in LPC mode.
456 * See doc 42413 AMD SB700/710/750 RPR.
457 */
458 if (amd_gen == CHIPSET_SB7XX)
459 msg_pdbg(", SpiOpEnInLpcMode=%i", (tmp >> 5) & 0x1);
460 msg_pdbg(", PrefetchEnSPIFromHost=%i\n", tmp & 0x1);
461 }
462
463 /* Chipset support matrix for SPI_Cntrl0 (spibar + 0x0)
464 * See the chipset support matrix for SPI Base_Addr above for an explanation of the symbols used.
465 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson2+ yangtze
466 * 17 rsvd <- <- ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000467 * 18 rsvd <- fastReadEnable<1> ? <- ? SpiReadMode[0]<1>
Stefan Tauner4442b812013-09-12 15:48:35 +0000468 * 19 SpiArbEnable <- <- ? <- ? <-
469 * 20 (FifoPtrClr) <- <- ? <- ? <-
470 * 21 (FifoPtrInc) <- <- ? <- ? IllegalAccess
471 * 22 SpiAccessMacRomEn <- <- ? <- ? <-
472 * 23 SpiHostAccessRomEn <- <- ? <- ? <-
473 * 24:26 ArbWaitCount <- <- ? <- ? <-
474 * 27 SpiBridgeDisable <- <- ? <- ? rsvd
475 * 28 rsvd DropOneClkOnRd = SPIClkGate ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000476 * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]<1>
Stefan Tauner4442b812013-09-12 15:48:35 +0000477 * 31 rsvd <- SpiBusy ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000478 *
479 * <1> see handle_speed
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000480 */
Stefan Tauner4442b812013-09-12 15:48:35 +0000481 tmp = mmio_readl(sb600_spibar + 0x00);
482 msg_pdbg("(0x%08" PRIx32 ") SpiArbEnable=%i", tmp, (tmp >> 19) & 0x1);
483
484 msg_pdbg(", SpiAccessMacRomEn=%i, SpiHostAccessRomEn=%i, ArbWaitCount=%i",
485 (tmp >> 22) & 0x1, (tmp >> 23) & 0x1, (tmp >> 24) & 0x7);
486
487 if (amd_gen != CHIPSET_YANGTZE)
488 msg_pdbg(", SpiBridgeDisable=%i", (tmp >> 27) & 0x1);
489
490 switch (amd_gen) {
491 case CHIPSET_SB7XX:
492 msg_pdbg(", DropOneClkOnRd/SpiClkGate=%i", (tmp >> 28) & 0x1);
493 case CHIPSET_SB89XX:
494 case CHIPSET_HUDSON234:
495 msg_pdbg(", SpiBusy=%i", (tmp >> 31) & 0x1);
496 default: break;
497 }
498 msg_pdbg("\n");
499
500 if (((tmp >> 22) & 0x1) == 0 || ((tmp >> 23) & 0x1) == 0) {
501 msg_perr("ERROR: State of SpiAccessMacRomEn or SpiHostAccessRomEn prohibits full access.\n");
502 return ERROR_NONFATAL;
503 }
504
Stefan Tauner4442b812013-09-12 15:48:35 +0000505 if (amd_gen >= CHIPSET_SB89XX) {
506 tmp = mmio_readb(sb600_spibar + 0x1D);
507 msg_pdbg("Using SPI_CS%d\n", tmp & 0x3);
508 }
509
Michael Karcherb05b9e12010-07-22 18:04:19 +0000510 /* Look for the SMBus device. */
511 smbus_dev = pci_dev_find(0x1002, 0x4385);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000512 if (!smbus_dev) {
Stefan Tauner463dd692013-08-08 12:00:19 +0000513 smbus_dev = pci_dev_find(0x1022, 0x780b); /* AMD FCH */
Wang Qing Pei6e9e2ee2011-08-26 21:11:41 +0000514 if (!smbus_dev) {
515 msg_perr("ERROR: SMBus device not found. Not enabling SPI.\n");
516 return ERROR_NONFATAL;
517 }
Michael Karcherb05b9e12010-07-22 18:04:19 +0000518 }
519
520 /* Note about the bit tests below: If a bit is zero, the GPIO is SPI. */
521 /* GPIO11/SPI_DO and GPIO12/SPI_DI status */
522 reg = pci_read_byte(smbus_dev, 0xAB);
523 reg &= 0xC0;
524 msg_pdbg("GPIO11 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_DO");
525 msg_pdbg("GPIO12 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_DI");
526 if (reg != 0x00) {
527 msg_pdbg("Not enabling SPI");
528 return 0;
529 }
530 /* GPIO31/SPI_HOLD and GPIO32/SPI_CS status */
531 reg = pci_read_byte(smbus_dev, 0x83);
532 reg &= 0xC0;
533 msg_pdbg("GPIO31 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_HOLD");
534 msg_pdbg("GPIO32 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_CS");
535 /* SPI_HOLD is not used on all boards, filter it out. */
536 if ((reg & 0x80) != 0x00) {
537 msg_pdbg("Not enabling SPI");
538 return 0;
539 }
540 /* GPIO47/SPI_CLK status */
541 reg = pci_read_byte(smbus_dev, 0xA7);
542 reg &= 0x40;
543 msg_pdbg("GPIO47 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_CLK");
544 if (reg != 0x00) {
545 msg_pdbg("Not enabling SPI");
546 return 0;
547 }
548
Stefan Taunera6a0d202013-09-15 14:17:39 +0000549 if (handle_speed(dev) != 0)
550 return ERROR_FATAL;
551
Rudolf Marek70e14592013-07-25 22:58:56 +0000552 if (sb600_handle_imc(dev, amd_imc_force) != 0)
553 return ERROR_FATAL;
Carl-Daniel Hailfinger39446e32010-09-15 12:02:07 +0000554
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000555 /* Bring the FIFO to a clean state. */
556 reset_internal_fifo_pointer();
557
Michael Karcherb9dbe482011-05-11 17:07:07 +0000558 register_spi_programmer(&spi_programmer_sb600);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000559 return 0;
560}
561
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000562#endif