blob: 68f8d8ac532b291c991a66ccb1fb14c3ffab0a58 [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.
Wei Hu31402ee2014-05-16 21:39:33 +00007 * Copyright (C) 2009, 2010, 2013 Carl-Daniel Hailfinger
8 * Copyright (C) 2013 Stefan Tauner
Jason Wanga3f04be2008-11-28 21:36:51 +00009 *
10 * 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; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000025#if defined(__i386__) || defined(__x86_64__)
26
Rudolf Marek70e14592013-07-25 22:58:56 +000027#include <string.h>
28#include <stdlib.h>
Jason Wanga3f04be2008-11-28 21:36:51 +000029#include "flash.h"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000030#include "programmer.h"
Patrick Georgi32508eb2012-07-20 20:35:14 +000031#include "hwaccess.h"
Jason Wanga3f04be2008-11-28 21:36:51 +000032#include "spi.h"
33
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +000034/* This struct is unused, but helps visualize the SB600 SPI BAR layout.
35 *struct sb600_spi_controller {
36 * unsigned int spi_cntrl0; / * 00h * /
37 * unsigned int restrictedcmd1; / * 04h * /
38 * unsigned int restrictedcmd2; / * 08h * /
39 * unsigned int spi_cntrl1; / * 0ch * /
40 * unsigned int spi_cmdvalue0; / * 10h * /
41 * unsigned int spi_cmdvalue1; / * 14h * /
42 * unsigned int spi_cmdvalue2; / * 18h * /
43 * unsigned int spi_fakeid; / * 1Ch * /
44 *};
45 */
Jason Wanga3f04be2008-11-28 21:36:51 +000046
Michael Karcherb05b9e12010-07-22 18:04:19 +000047static uint8_t *sb600_spibar = NULL;
Stefan Tauner463dd692013-08-08 12:00:19 +000048enum amd_chipset {
49 CHIPSET_AMD_UNKNOWN,
50 CHIPSET_SB6XX,
51 CHIPSET_SB7XX, /* SP5100 too */
52 CHIPSET_SB89XX, /* Hudson-1 too */
53 CHIPSET_HUDSON234,
Martin Roth82b6ec12014-07-15 13:50:58 +000054 CHIPSET_BOLTON,
Stefan Tauner463dd692013-08-08 12:00:19 +000055 CHIPSET_YANGTZE,
56};
57static enum amd_chipset amd_gen = CHIPSET_AMD_UNKNOWN;
58
Stefan Taunerd5b2aef2014-05-16 21:39:28 +000059#define FIFO_SIZE_OLD 8
Wei Hu31402ee2014-05-16 21:39:33 +000060#define FIFO_SIZE_YANGTZE 71
Stefan Taunerd5b2aef2014-05-16 21:39:28 +000061
62static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
63 const unsigned char *writearr, unsigned char *readarr);
Wei Hu31402ee2014-05-16 21:39:33 +000064static int spi100_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
65 const unsigned char *writearr, unsigned char *readarr);
Stefan Taunerd5b2aef2014-05-16 21:39:28 +000066
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +000067static struct spi_master spi_master_sb600 = {
Stefan Taunerd5b2aef2014-05-16 21:39:28 +000068 .type = SPI_CONTROLLER_SB600,
69 .max_data_read = FIFO_SIZE_OLD,
70 .max_data_write = FIFO_SIZE_OLD - 3,
71 .command = sb600_spi_send_command,
72 .multicommand = default_spi_send_multicommand,
73 .read = default_spi_read,
74 .write_256 = default_spi_write_256,
75 .write_aai = default_spi_write_aai,
76};
77
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +000078static struct spi_master spi_master_yangtze = {
Wei Hu31402ee2014-05-16 21:39:33 +000079 .type = SPI_CONTROLLER_YANGTZE,
80 .max_data_read = FIFO_SIZE_YANGTZE - 3, /* Apparently the big SPI 100 buffer is not a ring buffer. */
81 .max_data_write = FIFO_SIZE_YANGTZE - 3,
82 .command = spi100_spi_send_command,
83 .multicommand = default_spi_send_multicommand,
84 .read = default_spi_read,
85 .write_256 = default_spi_write_256,
86 .write_aai = default_spi_write_aai,
87};
88
Stefan Tauner463dd692013-08-08 12:00:19 +000089static void determine_generation(struct pci_dev *dev)
90{
91 amd_gen = CHIPSET_AMD_UNKNOWN;
Stefan Tauner4442b812013-09-12 15:48:35 +000092 msg_pdbg2("Trying to determine the generation of the SPI interface... ");
93 if (dev->device_id == 0x438d) {
94 amd_gen = CHIPSET_SB6XX;
95 msg_pdbg("SB6xx detected.\n");
96 } else if (dev->device_id == 0x439d) {
97 struct pci_dev *smbus_dev = pci_dev_find(0x1002, 0x4385);
98 if (smbus_dev == NULL)
99 return;
100 uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID);
101 if (rev >= 0x39 && rev <= 0x3D) {
102 amd_gen = CHIPSET_SB7XX;
103 msg_pdbg("SB7xx/SP5100 detected.\n");
104 } else if (rev >= 0x40 && rev <= 0x42) {
105 amd_gen = CHIPSET_SB89XX;
106 msg_pdbg("SB8xx/SB9xx/Hudson-1 detected.\n");
107 } else {
108 msg_pwarn("SB device found but SMBus revision 0x%02x does not match known values.\n"
109 "Assuming SB8xx/SB9xx/Hudson-1. Please send a log to flashrom@flashrom.org\n",
110 rev);
111 amd_gen = CHIPSET_SB89XX;
112 }
113 } else if (dev->device_id == 0x780e) {
Stefan Tauner463dd692013-08-08 12:00:19 +0000114 /* The PCI ID of the LPC bridge doesn't change between Hudson-2/3/4 and Yangtze (Kabini/Temash)
115 * although they use different SPI interfaces. */
116#ifdef USE_YANGTZE_HEURISTICS
117 /* This heuristic accesses the SPI interface MMIO BAR at locations beyond those supported by
118 * Hudson in the hope of getting 0xff readback on older chipsets and non-0xff readback on
119 * Yangtze (and newer, compatible chipsets). */
120 int i;
121 msg_pdbg("Checking for AMD Yangtze (Kabini/Temash) or later... ");
122 for (i = 0x20; i <= 0x4f; i++) {
123 if (mmio_readb(sb600_spibar + i) != 0xff) {
124 amd_gen = CHIPSET_YANGTZE;
125 msg_pdbg("found.\n");
126 return;
127 }
128 }
129 msg_pdbg("not found. Assuming Hudson.\n");
130 amd_gen = CHIPSET_HUDSON234;
131#else
132 struct pci_dev *smbus_dev = pci_dev_find(0x1022, 0x780B);
133 if (smbus_dev == NULL) {
134 msg_pdbg("No SMBus device with ID 1022:780B found.\n");
135 return;
136 }
137 uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID);
138 if (rev >= 0x11 && rev <= 0x15) {
139 amd_gen = CHIPSET_HUDSON234;
140 msg_pdbg("Hudson-2/3/4 detected.\n");
Martin Roth82b6ec12014-07-15 13:50:58 +0000141 } else if (rev == 0x16) {
142 amd_gen = CHIPSET_BOLTON;
143 msg_pdbg("Bolton detected.\n");
Stefan Tauner5c316f92015-02-08 21:57:52 +0000144 } else if ((rev >= 0x39 && rev <= 0x3A) || rev == 0x42) {
Stefan Tauner463dd692013-08-08 12:00:19 +0000145 amd_gen = CHIPSET_YANGTZE;
146 msg_pdbg("Yangtze detected.\n");
147 } else {
148 msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n"
149 "Please report this to flashrom@flashrom.org and include this log and\n"
150 "the output of lspci -nnvx, thanks!.\n", rev);
151 }
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100152 } else if (dev->device_id == 0x790e) {
153 struct pci_dev *smbus_dev = pci_dev_find(0x1022, 0x790B);
154 if (smbus_dev == NULL) {
155 msg_pdbg("No SMBus device with ID 1022:790B found.\n");
156 return;
157 }
158 uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID);
159 if (rev == 0x4a) {
160 amd_gen = CHIPSET_YANGTZE;
161 msg_pdbg("Yangtze detected.\n");
162 } else {
163 msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n"
164 "Please report this to flashrom@flashrom.org and include this log and\n"
165 "the output of lspci -nnvx, thanks!.\n", rev);
166 }
167
168
Stefan Tauner463dd692013-08-08 12:00:19 +0000169#endif
Stefan Tauner4442b812013-09-12 15:48:35 +0000170 } else
171 msg_pwarn("%s: Unknown LPC device %" PRIx16 ":%" PRIx16 ".\n"
172 "Please report this to flashrom@flashrom.org and include this log and\n"
173 "the output of lspci -nnvx, thanks!\n",
174 __func__, dev->vendor_id, dev->device_id);
Stefan Tauner463dd692013-08-08 12:00:19 +0000175}
Jason Wanga3f04be2008-11-28 21:36:51 +0000176
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +0000177static void reset_internal_fifo_pointer(void)
Jason Wanga3f04be2008-11-28 21:36:51 +0000178{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000179 mmio_writeb(mmio_readb(sb600_spibar + 2) | 0x10, sb600_spibar + 2);
Jason Wanga3f04be2008-11-28 21:36:51 +0000180
Rudolf Marek70e14592013-07-25 22:58:56 +0000181 /* FIXME: This loop needs a timeout and a clearer message. */
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000182 while (mmio_readb(sb600_spibar + 0xD) & 0x7)
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000183 msg_pspew("reset\n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000184}
185
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000186static int compare_internal_fifo_pointer(uint8_t want)
187{
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000188 uint8_t have = mmio_readb(sb600_spibar + 0xd) & 0x07;
189 want %= FIFO_SIZE_OLD;
190 if (have != want) {
191 msg_perr("AMD SPI FIFO pointer corruption! Pointer is %d, wanted %d\n", have, want);
192 msg_perr("Something else is accessing the flash chip and causes random corruption.\n"
193 "Please stop all applications and drivers and IPMI which access the flash chip.\n");
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000194 return 1;
195 } else {
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000196 msg_pspew("AMD SPI FIFO pointer is %d, wanted %d\n", have, want);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000197 return 0;
198 }
199}
200
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000201/* Check the number of bytes to be transmitted and extract opcode. */
202static int check_readwritecnt(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt)
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000203{
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000204 unsigned int maxwritecnt = flash->mst->spi.max_data_write + 3;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000205 if (writecnt > maxwritecnt) {
206 msg_pinfo("%s: SPI controller can not send %d bytes, it is limited to %d bytes\n",
207 __func__, writecnt, maxwritecnt);
208 return SPI_INVALID_LENGTH;
209 }
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000210
Stefan Tauner6697f712014-08-06 15:09:15 +0000211 unsigned int maxreadcnt = flash->mst->spi.max_data_read;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000212 if (readcnt > maxreadcnt) {
213 msg_pinfo("%s: SPI controller can not receive %d bytes, it is limited to %d bytes\n",
214 __func__, readcnt, maxreadcnt);
215 return SPI_INVALID_LENGTH;
216 }
217 return 0;
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000218}
219
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +0000220static void execute_command(void)
Jason Wanga3f04be2008-11-28 21:36:51 +0000221{
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000222 msg_pspew("Executing... ");
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000223 mmio_writeb(mmio_readb(sb600_spibar + 2) | 1, sb600_spibar + 2);
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000224 while (mmio_readb(sb600_spibar + 2) & 1)
Jason Wanga3f04be2008-11-28 21:36:51 +0000225 ;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000226 msg_pspew("done\n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000227}
228
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000229static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt,
230 unsigned int readcnt,
231 const unsigned char *writearr,
232 unsigned char *readarr)
Jason Wanga3f04be2008-11-28 21:36:51 +0000233{
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000234 /* First byte is cmd which can not be sent through the FIFO. */
Jason Wanga3f04be2008-11-28 21:36:51 +0000235 unsigned char cmd = *writearr++;
Jason Wanga3f04be2008-11-28 21:36:51 +0000236 writecnt--;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000237 msg_pspew("%s, cmd=0x%02x, writecnt=%d, readcnt=%d\n", __func__, cmd, writecnt, readcnt);
238 mmio_writeb(cmd, sb600_spibar + 0);
Jason Wanga3f04be2008-11-28 21:36:51 +0000239
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000240 int ret = check_readwritecnt(flash, writecnt, readcnt);
241 if (ret != 0)
242 return ret;
Jason Wanga3f04be2008-11-28 21:36:51 +0000243
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000244 /* This is a workaround for a bug in SPI controller. If we only send
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000245 * an opcode and no additional data/address, the SPI controller will
246 * read one byte too few from the chip. Basically, the last byte of
247 * the chip response is discarded and will not end up in the FIFO.
248 * It is unclear if the CS# line is set high too early as well.
249 */
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000250 unsigned int readoffby1 = (writecnt > 0) ? 0 : 1;
251 uint8_t readwrite = (readcnt + readoffby1) << 4 | (writecnt);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000252 mmio_writeb(readwrite, sb600_spibar + 1);
Jason Wanga3f04be2008-11-28 21:36:51 +0000253
Jason Wanga3f04be2008-11-28 21:36:51 +0000254 reset_internal_fifo_pointer();
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000255 msg_pspew("Filling FIFO: ");
256 int count;
257 for (count = 0; count < writecnt; count++) {
258 msg_pspew("[%02x]", writearr[count]);
259 mmio_writeb(writearr[count], sb600_spibar + 0xC);
Jason Wanga3f04be2008-11-28 21:36:51 +0000260 }
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000261 msg_pspew("\n");
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000262 if (compare_internal_fifo_pointer(writecnt))
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000263 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000264
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000265 /*
266 * We should send the data in sequence, which means we need to reset
267 * the FIFO pointer to the first byte we want to send.
268 */
269 reset_internal_fifo_pointer();
Jason Wanga3f04be2008-11-28 21:36:51 +0000270 execute_command();
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000271 if (compare_internal_fifo_pointer(writecnt + readcnt))
272 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000273
274 /*
275 * After the command executed, we should find out the index of the
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000276 * received byte. Here we just reset the FIFO pointer and skip the
277 * writecnt.
278 * It would be possible to increase the FIFO pointer by one instead
279 * of reading and discarding one byte from the FIFO.
280 * The FIFO is implemented on top of an 8 byte ring buffer and the
281 * buffer is never cleared. For every byte that is shifted out after
282 * the opcode, the FIFO already stores the response from the chip.
283 * Usually, the chip will respond with 0x00 or 0xff.
Jason Wanga3f04be2008-11-28 21:36:51 +0000284 */
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000285 reset_internal_fifo_pointer();
Jason Wanga3f04be2008-11-28 21:36:51 +0000286
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000287 /* Skip the bytes we sent. */
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000288 msg_pspew("Skipping: ");
Jason Wanga3f04be2008-11-28 21:36:51 +0000289 for (count = 0; count < writecnt; count++) {
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000290 msg_pspew("[%02x]", mmio_readb(sb600_spibar + 0xC));
Jason Wanga3f04be2008-11-28 21:36:51 +0000291 }
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000292 msg_pspew("\n");
293 if (compare_internal_fifo_pointer(writecnt))
294 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000295
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000296 msg_pspew("Reading FIFO: ");
297 for (count = 0; count < readcnt; count++) {
298 readarr[count] = mmio_readb(sb600_spibar + 0xC);
299 msg_pspew("[%02x]", readarr[count]);
Jason Wanga3f04be2008-11-28 21:36:51 +0000300 }
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000301 msg_pspew("\n");
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000302 if (compare_internal_fifo_pointer(writecnt+readcnt))
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000303 return SPI_PROGRAMMER_ERROR;
304
305 if (mmio_readb(sb600_spibar + 1) != readwrite) {
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000306 msg_perr("Unexpected change in AMD SPI read/write count!\n");
307 msg_perr("Something else is accessing the flash chip and causes random corruption.\n"
308 "Please stop all applications and drivers and IPMI which access the flash chip.\n");
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000309 return SPI_PROGRAMMER_ERROR;
310 }
Jason Wanga3f04be2008-11-28 21:36:51 +0000311
312 return 0;
313}
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000314
Wei Hu31402ee2014-05-16 21:39:33 +0000315static int spi100_spi_send_command(struct flashctx *flash, unsigned int writecnt,
316 unsigned int readcnt,
317 const unsigned char *writearr,
318 unsigned char *readarr)
319{
320 /* First byte is cmd which can not be sent through the buffer. */
321 unsigned char cmd = *writearr++;
322 writecnt--;
323 msg_pspew("%s, cmd=0x%02x, writecnt=%d, readcnt=%d\n", __func__, cmd, writecnt, readcnt);
324 mmio_writeb(cmd, sb600_spibar + 0);
325
326 int ret = check_readwritecnt(flash, writecnt, readcnt);
327 if (ret != 0)
328 return ret;
329
330 /* Use the extended TxByteCount and RxByteCount registers. */
331 mmio_writeb(writecnt, sb600_spibar + 0x48);
332 mmio_writeb(readcnt, sb600_spibar + 0x4b);
333
334 msg_pspew("Filling buffer: ");
335 int count;
336 for (count = 0; count < writecnt; count++) {
337 msg_pspew("[%02x]", writearr[count]);
338 mmio_writeb(writearr[count], sb600_spibar + 0x80 + count);
339 }
340 msg_pspew("\n");
341
342 execute_command();
343
344 msg_pspew("Reading buffer: ");
345 for (count = 0; count < readcnt; count++) {
346 readarr[count] = mmio_readb(sb600_spibar + 0x80 + (writecnt + count) % FIFO_SIZE_YANGTZE);
347 msg_pspew("[%02x]", readarr[count]);
348 }
349 msg_pspew("\n");
350
351 return 0;
352}
353
Stefan Taunera6a0d202013-09-15 14:17:39 +0000354struct spispeed {
355 const char *const name;
356 const uint8_t speed;
357};
358
359static const struct spispeed spispeeds[] = {
360 { "66 MHz", 0x00 },
361 { "33 MHz", 0x01 },
362 { "22 MHz", 0x02 },
363 { "16.5 MHz", 0x03 },
Wei Hu31402ee2014-05-16 21:39:33 +0000364 { "100 MHz", 0x04 },
365 { "Reserved", 0x05 },
366 { "Reserved", 0x06 },
367 { "800 kHz", 0x07 },
Stefan Taunera6a0d202013-09-15 14:17:39 +0000368};
369
370static int set_speed(struct pci_dev *dev, const struct spispeed *spispeed)
371{
372 bool success = false;
373 uint8_t speed = spispeed->speed;
374
375 msg_pdbg("Setting SPI clock to %s (0x%x).\n", spispeed->name, speed);
Wei Hu31402ee2014-05-16 21:39:33 +0000376 if (amd_gen >= CHIPSET_YANGTZE) {
377 rmmio_writew((speed << 12) | (speed << 8) | (speed << 4) | speed, sb600_spibar + 0x22);
378 uint16_t tmp = mmio_readw(sb600_spibar + 0x22);
379 success = (((tmp >> 12) & 0xf) == speed && ((tmp >> 8) & 0xf) == speed &&
380 ((tmp >> 4) & 0xf) == speed && ((tmp >> 0) & 0xf) == speed);
381 } else {
Stefan Taunera6a0d202013-09-15 14:17:39 +0000382 rmmio_writeb((mmio_readb(sb600_spibar + 0xd) & ~(0x3 << 4)) | (speed << 4), sb600_spibar + 0xd);
383 success = (speed == ((mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3));
384 }
385
386 if (!success) {
387 msg_perr("Setting SPI clock failed.\n");
388 return 1;
389 }
390 return 0;
391}
392
Wei Hu31402ee2014-05-16 21:39:33 +0000393static int set_mode(struct pci_dev *dev, uint8_t read_mode)
394{
395 uint32_t tmp = mmio_readl(sb600_spibar + 0x00);
396 tmp &= ~(0x6 << 28 | 0x1 << 18); /* Clear mode bits */
397 tmp |= ((read_mode & 0x6) << 28) | ((read_mode & 0x1) << 18);
398 rmmio_writel(tmp, sb600_spibar + 0x00);
399 if (tmp != mmio_readl(sb600_spibar + 0x00))
400 return 1;
401 return 0;
402}
403
Stefan Taunera6a0d202013-09-15 14:17:39 +0000404static int handle_speed(struct pci_dev *dev)
405{
406 uint32_t tmp;
Carl-Daniel Hailfinger57cdd6b2016-03-12 19:49:14 +0000407 uint8_t spispeed_idx = 3; /* Default to 16.5 MHz */
Stefan Taunera6a0d202013-09-15 14:17:39 +0000408
Stefan Tauner21071b02014-05-16 21:39:48 +0000409 char *spispeed = extract_programmer_param("spispeed");
410 if (spispeed != NULL) {
Carl-Daniel Hailfinger57cdd6b2016-03-12 19:49:14 +0000411 unsigned int i;
412 for (i = 0; i < ARRAY_SIZE(spispeeds); i++) {
413 if (strcasecmp(spispeeds[i].name, spispeed) == 0) {
414 spispeed_idx = i;
415 break;
Stefan Tauner21071b02014-05-16 21:39:48 +0000416 }
Stefan Tauner21071b02014-05-16 21:39:48 +0000417 }
Carl-Daniel Hailfinger57cdd6b2016-03-12 19:49:14 +0000418 /* "reserved" is not a valid speed.
419 * Error out on speeds not present in the spispeeds array.
420 * Only Yangtze supports the second half of indices.
421 * No 66 MHz before SB8xx. */
422 if ((strcasecmp(spispeed, "reserved") == 0) ||
423 (i == ARRAY_SIZE(spispeeds)) ||
424 (amd_gen < CHIPSET_YANGTZE && spispeed_idx > 3) ||
425 (amd_gen < CHIPSET_SB89XX && spispeed_idx == 0)) {
Stefan Tauner21071b02014-05-16 21:39:48 +0000426 msg_perr("Error: Invalid spispeed value: '%s'.\n", spispeed);
427 free(spispeed);
428 return 1;
429 }
430 free(spispeed);
431 }
432
Stefan Taunera6a0d202013-09-15 14:17:39 +0000433 /* See the chipset support matrix for SPI Base_Addr below for an explanation of the symbols used.
Martin Roth82b6ec12014-07-15 13:50:58 +0000434 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson234 bolton/yangtze
Stefan Taunera6a0d202013-09-15 14:17:39 +0000435 * 18 rsvd <- fastReadEnable ? <- ? SpiReadMode[0]
436 * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]
437 */
Martin Roth82b6ec12014-07-15 13:50:58 +0000438 if (amd_gen >= CHIPSET_BOLTON) {
Wei Hu31402ee2014-05-16 21:39:33 +0000439 static const char *spireadmodes[] = {
440 "Normal (up to 33 MHz)", /* 0 */
441 "Reserved", /* 1 */
442 "Dual IO (1-1-2)", /* 2 */
443 "Quad IO (1-1-4)", /* 3 */
444 "Dual IO (1-2-2)", /* 4 */
445 "Quad IO (1-4-4)", /* 5 */
446 "Normal (up to 66 MHz)", /* 6 */
Martin Roth82b6ec12014-07-15 13:50:58 +0000447 "Fast Read", /* 7 (Not defined in the Bolton datasheet.) */
Wei Hu31402ee2014-05-16 21:39:33 +0000448 };
449 tmp = mmio_readl(sb600_spibar + 0x00);
450 uint8_t read_mode = ((tmp >> 28) & 0x6) | ((tmp >> 18) & 0x1);
451 msg_pdbg("SpiReadMode=%s (%i)\n", spireadmodes[read_mode], read_mode);
452 if (read_mode != 6) {
453 read_mode = 6; /* Default to "Normal (up to 66 MHz)" */
454 if (set_mode(dev, read_mode) != 0) {
455 msg_perr("Setting read mode to \"%s\" failed.\n", spireadmodes[read_mode]);
456 return 1;
457 }
458 msg_pdbg("Setting read mode to \"%s\" succeeded.\n", spireadmodes[read_mode]);
459 }
460
Martin Roth82b6ec12014-07-15 13:50:58 +0000461 if (amd_gen >= CHIPSET_YANGTZE) {
462 tmp = mmio_readb(sb600_spibar + 0x20);
463 msg_pdbg("UseSpi100 is %sabled\n", (tmp & 0x1) ? "en" : "dis");
464 if ((tmp & 0x1) == 0) {
465 rmmio_writeb(tmp | 0x1, sb600_spibar + 0x20);
466 tmp = mmio_readb(sb600_spibar + 0x20) & 0x1;
467 if (tmp == 0) {
468 msg_perr("Enabling Spi100 failed.\n");
469 return 1;
470 }
471 msg_pdbg("Enabling Spi100 succeeded.\n");
472 }
473
474 tmp = mmio_readw(sb600_spibar + 0x22); /* SPI 100 Speed Config */
475 msg_pdbg("NormSpeedNew is %s\n", spispeeds[(tmp >> 12) & 0xf].name);
476 msg_pdbg("FastSpeedNew is %s\n", spispeeds[(tmp >> 8) & 0xf].name);
477 msg_pdbg("AltSpeedNew is %s\n", spispeeds[(tmp >> 4) & 0xf].name);
478 msg_pdbg("TpmSpeedNew is %s\n", spispeeds[(tmp >> 0) & 0xf].name);
479 }
Wei Hu31402ee2014-05-16 21:39:33 +0000480 } else {
Stefan Taunera6a0d202013-09-15 14:17:39 +0000481 if (amd_gen >= CHIPSET_SB89XX && amd_gen <= CHIPSET_HUDSON234) {
482 bool fast_read = (mmio_readl(sb600_spibar + 0x00) >> 18) & 0x1;
483 msg_pdbg("Fast Reads are %sabled\n", fast_read ? "en" : "dis");
484 if (fast_read) {
485 msg_pdbg("Disabling them temporarily.\n");
486 rmmio_writel(mmio_readl(sb600_spibar + 0x00) & ~(0x1 << 18),
487 sb600_spibar + 0x00);
488 }
489 }
490 tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3;
491 msg_pdbg("NormSpeed is %s\n", spispeeds[tmp].name);
492 }
493 return set_speed(dev, &spispeeds[spispeed_idx]);
494}
495
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000496static int handle_imc(struct pci_dev *dev)
Rudolf Marek70e14592013-07-25 22:58:56 +0000497{
498 /* Handle IMC everywhere but sb600 which does not have one. */
Stefan Tauner4442b812013-09-12 15:48:35 +0000499 if (amd_gen == CHIPSET_SB6XX)
Rudolf Marek70e14592013-07-25 22:58:56 +0000500 return 0;
501
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000502 bool amd_imc_force = false;
503 char *arg = extract_programmer_param("amd_imc_force");
504 if (arg && !strcmp(arg, "yes")) {
505 amd_imc_force = true;
506 msg_pspew("amd_imc_force enabled.\n");
507 } else if (arg && !strlen(arg)) {
508 msg_perr("Missing argument for amd_imc_force.\n");
509 free(arg);
510 return 1;
511 } else if (arg) {
512 msg_perr("Unknown argument for amd_imc_force: \"%s\" (not \"yes\").\n", arg);
513 free(arg);
514 return 1;
515 }
516 free(arg);
517
Rudolf Marek70e14592013-07-25 22:58:56 +0000518 /* TODO: we should not only look at IntegratedImcPresent (LPC Dev 20, Func 3, 40h) but also at
Stefan Tauner5c316f92015-02-08 21:57:52 +0000519 * IMCEnable(Strap) and Override EcEnable(Strap) (sb8xx, sb9xx?, a50, Bolton: Misc_Reg: 80h-87h;
Rudolf Marek70e14592013-07-25 22:58:56 +0000520 * sb7xx, sp5100: PM_Reg: B0h-B1h) etc. */
521 uint8_t reg = pci_read_byte(dev, 0x40);
522 if ((reg & (1 << 7)) == 0) {
523 msg_pdbg("IMC is not active.\n");
524 return 0;
525 }
526
527 if (!amd_imc_force)
528 programmer_may_write = 0;
Stefan Tauner463dd692013-08-08 12:00:19 +0000529 msg_pinfo("Writes have been disabled for safety reasons because the presence of the IMC\n"
530 "was detected and it could interfere with accessing flash memory. Flashrom will\n"
531 "try to disable it temporarily but even then this might not be safe:\n"
Stefan Tauner0be072c2016-03-13 15:16:30 +0000532 "when it is re-enabled and after a reboot it expects to find working code\n"
Rudolf Marek70e14592013-07-25 22:58:56 +0000533 "in the flash and it is unpredictable what happens if there is none.\n"
534 "\n"
535 "To be safe make sure that there is a working IMC firmware at the right\n"
536 "location in the image you intend to write and do not attempt to erase.\n"
537 "\n"
538 "You can enforce write support with the amd_imc_force programmer option.\n");
539 if (amd_imc_force)
540 msg_pinfo("Continuing with write support because the user forced us to!\n");
541
542 return amd_imc_shutdown(dev);
543}
544
Michael Karcherb05b9e12010-07-22 18:04:19 +0000545int sb600_probe_spi(struct pci_dev *dev)
546{
547 struct pci_dev *smbus_dev;
548 uint32_t tmp;
549 uint8_t reg;
Rudolf Marek70e14592013-07-25 22:58:56 +0000550
Michael Karcherb05b9e12010-07-22 18:04:19 +0000551 /* Read SPI_BaseAddr */
552 tmp = pci_read_long(dev, 0xa0);
553 tmp &= 0xffffffe0; /* remove bits 4-0 (reserved) */
554 msg_pdbg("SPI base address is at 0x%x\n", tmp);
555
556 /* If the BAR has address 0, it is unlikely SPI is used. */
557 if (!tmp)
558 return 0;
559
560 /* Physical memory has to be mapped at page (4k) boundaries. */
Stefan Tauner7fb5aa02013-08-14 15:48:44 +0000561 sb600_spibar = rphysmap("SB600 SPI registers", tmp & 0xfffff000, 0x1000);
562 if (sb600_spibar == ERROR_PTR)
Niklas Söderlund5d307202013-09-14 09:02:27 +0000563 return ERROR_FATAL;
Stefan Tauner7fb5aa02013-08-14 15:48:44 +0000564
Michael Karcherb05b9e12010-07-22 18:04:19 +0000565 /* The low bits of the SPI base address are used as offset into
566 * the mapped page.
567 */
568 sb600_spibar += tmp & 0xfff;
569
Stefan Tauner463dd692013-08-08 12:00:19 +0000570 determine_generation(dev);
Stefan Tauner4442b812013-09-12 15:48:35 +0000571 if (amd_gen == CHIPSET_AMD_UNKNOWN) {
572 msg_perr("Could not determine chipset generation.");
573 return ERROR_NONFATAL;
574 }
Stefan Tauner463dd692013-08-08 12:00:19 +0000575
Stefan Tauner4442b812013-09-12 15:48:35 +0000576 /* How to read the following table and similar ones in this file:
577 * "?" means we have no datasheet for this chipset generation or it doesn't have any relevant info.
578 * "<-" means the bit/register meaning is identical to the next non-"?" chipset to the left. "<-" thus
579 * never refers to another "?".
580 * If a "?" chipset is between two chipsets with identical meaning, we assume the meaning didn't change
581 * twice in between, i.e. the meaning is unchanged for the "?" chipset. Usually we assume that
582 * succeeding hardware supports the same functionality as its predecessor unless proven different by
583 * tests or documentation, hence "?" will often be implemented equally to "<-".
584 *
585 * Chipset support matrix for SPI Base_Addr (LPC PCI reg 0xa0)
586 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson2+ yangtze
587 * 3 rsvd <- <- ? <- ? RouteTpm2Spi
588 * 2 rsvd AbortEnable rsvd ? <- ? <-
589 * 1 rsvd SpiRomEnable <- ? <- ? <-
590 * 0 rsvd AltSpiCSEnable rsvd ? <- ? <-
591 */
592 if (amd_gen >= CHIPSET_SB7XX) {
593 tmp = pci_read_long(dev, 0xa0);
594 msg_pdbg("SpiRomEnable=%i", (tmp >> 1) & 0x1);
595 if (amd_gen == CHIPSET_SB7XX)
596 msg_pdbg(", AltSpiCSEnable=%i, AbortEnable=%i", tmp & 0x1, (tmp >> 2) & 0x1);
Wei Hu31402ee2014-05-16 21:39:33 +0000597 else if (amd_gen == CHIPSET_YANGTZE)
598 msg_pdbg(", RouteTpm2Sp=%i", (tmp >> 3) & 0x1);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000599
Stefan Tauner4442b812013-09-12 15:48:35 +0000600 tmp = pci_read_byte(dev, 0xba);
601 msg_pdbg(", PrefetchEnSPIFromIMC=%i", (tmp & 0x4) >> 2);
602
603 tmp = pci_read_byte(dev, 0xbb);
604 /* FIXME: Set bit 3,6,7 if not already set.
605 * Set bit 5, otherwise SPI accesses are pointless in LPC mode.
606 * See doc 42413 AMD SB700/710/750 RPR.
607 */
608 if (amd_gen == CHIPSET_SB7XX)
609 msg_pdbg(", SpiOpEnInLpcMode=%i", (tmp >> 5) & 0x1);
610 msg_pdbg(", PrefetchEnSPIFromHost=%i\n", tmp & 0x1);
611 }
612
613 /* Chipset support matrix for SPI_Cntrl0 (spibar + 0x0)
614 * See the chipset support matrix for SPI Base_Addr above for an explanation of the symbols used.
615 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson2+ yangtze
616 * 17 rsvd <- <- ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000617 * 18 rsvd <- fastReadEnable<1> ? <- ? SpiReadMode[0]<1>
Stefan Tauner4442b812013-09-12 15:48:35 +0000618 * 19 SpiArbEnable <- <- ? <- ? <-
619 * 20 (FifoPtrClr) <- <- ? <- ? <-
620 * 21 (FifoPtrInc) <- <- ? <- ? IllegalAccess
621 * 22 SpiAccessMacRomEn <- <- ? <- ? <-
622 * 23 SpiHostAccessRomEn <- <- ? <- ? <-
623 * 24:26 ArbWaitCount <- <- ? <- ? <-
624 * 27 SpiBridgeDisable <- <- ? <- ? rsvd
625 * 28 rsvd DropOneClkOnRd = SPIClkGate ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000626 * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]<1>
Stefan Tauner4442b812013-09-12 15:48:35 +0000627 * 31 rsvd <- SpiBusy ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000628 *
629 * <1> see handle_speed
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000630 */
Stefan Tauner4442b812013-09-12 15:48:35 +0000631 tmp = mmio_readl(sb600_spibar + 0x00);
632 msg_pdbg("(0x%08" PRIx32 ") SpiArbEnable=%i", tmp, (tmp >> 19) & 0x1);
Wei Hu31402ee2014-05-16 21:39:33 +0000633 if (amd_gen == CHIPSET_YANGTZE)
634 msg_pdbg(", IllegalAccess=%i", (tmp >> 21) & 0x1);
Stefan Tauner4442b812013-09-12 15:48:35 +0000635
636 msg_pdbg(", SpiAccessMacRomEn=%i, SpiHostAccessRomEn=%i, ArbWaitCount=%i",
637 (tmp >> 22) & 0x1, (tmp >> 23) & 0x1, (tmp >> 24) & 0x7);
638
639 if (amd_gen != CHIPSET_YANGTZE)
640 msg_pdbg(", SpiBridgeDisable=%i", (tmp >> 27) & 0x1);
641
642 switch (amd_gen) {
643 case CHIPSET_SB7XX:
644 msg_pdbg(", DropOneClkOnRd/SpiClkGate=%i", (tmp >> 28) & 0x1);
645 case CHIPSET_SB89XX:
646 case CHIPSET_HUDSON234:
Wei Hu31402ee2014-05-16 21:39:33 +0000647 case CHIPSET_YANGTZE:
Stefan Tauner4442b812013-09-12 15:48:35 +0000648 msg_pdbg(", SpiBusy=%i", (tmp >> 31) & 0x1);
649 default: break;
650 }
651 msg_pdbg("\n");
652
653 if (((tmp >> 22) & 0x1) == 0 || ((tmp >> 23) & 0x1) == 0) {
654 msg_perr("ERROR: State of SpiAccessMacRomEn or SpiHostAccessRomEn prohibits full access.\n");
655 return ERROR_NONFATAL;
656 }
657
Stefan Tauner4442b812013-09-12 15:48:35 +0000658 if (amd_gen >= CHIPSET_SB89XX) {
659 tmp = mmio_readb(sb600_spibar + 0x1D);
660 msg_pdbg("Using SPI_CS%d\n", tmp & 0x3);
Wei Hu31402ee2014-05-16 21:39:33 +0000661 /* FIXME: Handle SpiProtect* configuration on Yangtze. */
Stefan Tauner4442b812013-09-12 15:48:35 +0000662 }
663
Michael Karcherb05b9e12010-07-22 18:04:19 +0000664 /* Look for the SMBus device. */
665 smbus_dev = pci_dev_find(0x1002, 0x4385);
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100666 if (!smbus_dev)
Stefan Tauner463dd692013-08-08 12:00:19 +0000667 smbus_dev = pci_dev_find(0x1022, 0x780b); /* AMD FCH */
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100668 if (!smbus_dev)
669 smbus_dev = pci_dev_find(0x1022, 0x790b); /* AMD FP4 */
670 if (!smbus_dev) {
671 msg_perr("ERROR: SMBus device not found. Not enabling SPI.\n");
672 return ERROR_NONFATAL;
Michael Karcherb05b9e12010-07-22 18:04:19 +0000673 }
674
675 /* Note about the bit tests below: If a bit is zero, the GPIO is SPI. */
676 /* GPIO11/SPI_DO and GPIO12/SPI_DI status */
677 reg = pci_read_byte(smbus_dev, 0xAB);
678 reg &= 0xC0;
679 msg_pdbg("GPIO11 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_DO");
680 msg_pdbg("GPIO12 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_DI");
681 if (reg != 0x00) {
682 msg_pdbg("Not enabling SPI");
683 return 0;
684 }
685 /* GPIO31/SPI_HOLD and GPIO32/SPI_CS status */
686 reg = pci_read_byte(smbus_dev, 0x83);
687 reg &= 0xC0;
688 msg_pdbg("GPIO31 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_HOLD");
689 msg_pdbg("GPIO32 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_CS");
690 /* SPI_HOLD is not used on all boards, filter it out. */
691 if ((reg & 0x80) != 0x00) {
692 msg_pdbg("Not enabling SPI");
693 return 0;
694 }
695 /* GPIO47/SPI_CLK status */
696 reg = pci_read_byte(smbus_dev, 0xA7);
697 reg &= 0x40;
698 msg_pdbg("GPIO47 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_CLK");
699 if (reg != 0x00) {
700 msg_pdbg("Not enabling SPI");
701 return 0;
702 }
703
Stefan Taunera6a0d202013-09-15 14:17:39 +0000704 if (handle_speed(dev) != 0)
705 return ERROR_FATAL;
706
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000707 if (handle_imc(dev) != 0)
Rudolf Marek70e14592013-07-25 22:58:56 +0000708 return ERROR_FATAL;
Carl-Daniel Hailfinger39446e32010-09-15 12:02:07 +0000709
Wei Hu31402ee2014-05-16 21:39:33 +0000710 /* Starting with Yangtze the SPI controller got a different interface with a much bigger buffer. */
711 if (amd_gen != CHIPSET_YANGTZE)
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000712 register_spi_master(&spi_master_sb600);
Wei Hu31402ee2014-05-16 21:39:33 +0000713 else
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000714 register_spi_master(&spi_master_yangtze);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000715 return 0;
716}
717
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000718#endif