blob: 6466795bfea5f10ab31c3e6607a716dd9d462916 [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.
Jason Wanga3f04be2008-11-28 21:36:51 +000019 */
20
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +000021#if defined(__i386__) || defined(__x86_64__)
22
Rudolf Marek70e14592013-07-25 22:58:56 +000023#include <string.h>
24#include <stdlib.h>
Jason Wanga3f04be2008-11-28 21:36:51 +000025#include "flash.h"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000026#include "programmer.h"
Patrick Georgi32508eb2012-07-20 20:35:14 +000027#include "hwaccess.h"
Jason Wanga3f04be2008-11-28 21:36:51 +000028#include "spi.h"
29
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +000030/* This struct is unused, but helps visualize the SB600 SPI BAR layout.
31 *struct sb600_spi_controller {
32 * unsigned int spi_cntrl0; / * 00h * /
33 * unsigned int restrictedcmd1; / * 04h * /
34 * unsigned int restrictedcmd2; / * 08h * /
35 * unsigned int spi_cntrl1; / * 0ch * /
36 * unsigned int spi_cmdvalue0; / * 10h * /
37 * unsigned int spi_cmdvalue1; / * 14h * /
38 * unsigned int spi_cmdvalue2; / * 18h * /
39 * unsigned int spi_fakeid; / * 1Ch * /
40 *};
41 */
Jason Wanga3f04be2008-11-28 21:36:51 +000042
Michael Karcherb05b9e12010-07-22 18:04:19 +000043static uint8_t *sb600_spibar = NULL;
Stefan Tauner463dd692013-08-08 12:00:19 +000044enum amd_chipset {
45 CHIPSET_AMD_UNKNOWN,
46 CHIPSET_SB6XX,
47 CHIPSET_SB7XX, /* SP5100 too */
48 CHIPSET_SB89XX, /* Hudson-1 too */
49 CHIPSET_HUDSON234,
Martin Roth82b6ec12014-07-15 13:50:58 +000050 CHIPSET_BOLTON,
Stefan Tauner463dd692013-08-08 12:00:19 +000051 CHIPSET_YANGTZE,
52};
53static enum amd_chipset amd_gen = CHIPSET_AMD_UNKNOWN;
54
Stefan Taunerd5b2aef2014-05-16 21:39:28 +000055#define FIFO_SIZE_OLD 8
Wei Hu31402ee2014-05-16 21:39:33 +000056#define FIFO_SIZE_YANGTZE 71
Stefan Taunerd5b2aef2014-05-16 21:39:28 +000057
58static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
59 const unsigned char *writearr, unsigned char *readarr);
Wei Hu31402ee2014-05-16 21:39:33 +000060static int spi100_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
61 const unsigned char *writearr, unsigned char *readarr);
Stefan Taunerd5b2aef2014-05-16 21:39:28 +000062
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +000063static struct spi_master spi_master_sb600 = {
Stefan Taunerd5b2aef2014-05-16 21:39:28 +000064 .max_data_read = FIFO_SIZE_OLD,
65 .max_data_write = FIFO_SIZE_OLD - 3,
66 .command = sb600_spi_send_command,
67 .multicommand = default_spi_send_multicommand,
68 .read = default_spi_read,
69 .write_256 = default_spi_write_256,
70 .write_aai = default_spi_write_aai,
71};
72
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +000073static struct spi_master spi_master_yangtze = {
Wei Hu31402ee2014-05-16 21:39:33 +000074 .max_data_read = FIFO_SIZE_YANGTZE - 3, /* Apparently the big SPI 100 buffer is not a ring buffer. */
75 .max_data_write = FIFO_SIZE_YANGTZE - 3,
76 .command = spi100_spi_send_command,
77 .multicommand = default_spi_send_multicommand,
78 .read = default_spi_read,
79 .write_256 = default_spi_write_256,
80 .write_aai = default_spi_write_aai,
81};
82
Edward O'Callaghanc0a27e12019-10-29 17:05:39 +110083static int find_smbus_dev_rev(uint16_t vendor, uint16_t device)
84{
85 struct pci_dev *smbus_dev = pci_dev_find(vendor, device);
86 if (!smbus_dev) {
87 msg_pdbg("No SMBus device with ID %04X:%04X found.\n", vendor, device);
88 msg_perr("ERROR: SMBus device not found. Not enabling SPI.\n");
89 return -1;
90 }
91 return pci_read_byte(smbus_dev, PCI_REVISION_ID);
92}
93
Stefan Tauner463dd692013-08-08 12:00:19 +000094static void determine_generation(struct pci_dev *dev)
95{
96 amd_gen = CHIPSET_AMD_UNKNOWN;
Stefan Tauner4442b812013-09-12 15:48:35 +000097 msg_pdbg2("Trying to determine the generation of the SPI interface... ");
98 if (dev->device_id == 0x438d) {
99 amd_gen = CHIPSET_SB6XX;
100 msg_pdbg("SB6xx detected.\n");
101 } else if (dev->device_id == 0x439d) {
Edward O'Callaghanc0a27e12019-10-29 17:05:39 +1100102 int rev = find_smbus_dev_rev(0x1002, 0x4385);
103 if (rev < 0)
Stefan Tauner4442b812013-09-12 15:48:35 +0000104 return;
Stefan Tauner4442b812013-09-12 15:48:35 +0000105 if (rev >= 0x39 && rev <= 0x3D) {
106 amd_gen = CHIPSET_SB7XX;
107 msg_pdbg("SB7xx/SP5100 detected.\n");
108 } else if (rev >= 0x40 && rev <= 0x42) {
109 amd_gen = CHIPSET_SB89XX;
110 msg_pdbg("SB8xx/SB9xx/Hudson-1 detected.\n");
111 } else {
112 msg_pwarn("SB device found but SMBus revision 0x%02x does not match known values.\n"
113 "Assuming SB8xx/SB9xx/Hudson-1. Please send a log to flashrom@flashrom.org\n",
114 rev);
115 amd_gen = CHIPSET_SB89XX;
116 }
117 } else if (dev->device_id == 0x780e) {
Stefan Tauner463dd692013-08-08 12:00:19 +0000118 /* The PCI ID of the LPC bridge doesn't change between Hudson-2/3/4 and Yangtze (Kabini/Temash)
119 * although they use different SPI interfaces. */
120#ifdef USE_YANGTZE_HEURISTICS
121 /* This heuristic accesses the SPI interface MMIO BAR at locations beyond those supported by
122 * Hudson in the hope of getting 0xff readback on older chipsets and non-0xff readback on
123 * Yangtze (and newer, compatible chipsets). */
124 int i;
125 msg_pdbg("Checking for AMD Yangtze (Kabini/Temash) or later... ");
126 for (i = 0x20; i <= 0x4f; i++) {
127 if (mmio_readb(sb600_spibar + i) != 0xff) {
128 amd_gen = CHIPSET_YANGTZE;
129 msg_pdbg("found.\n");
130 return;
131 }
132 }
133 msg_pdbg("not found. Assuming Hudson.\n");
134 amd_gen = CHIPSET_HUDSON234;
135#else
Edward O'Callaghanc0a27e12019-10-29 17:05:39 +1100136 int rev = find_smbus_dev_rev(0x1022, 0x780B);
137 if (rev < 0)
Stefan Tauner463dd692013-08-08 12:00:19 +0000138 return;
Stefan Tauner463dd692013-08-08 12:00:19 +0000139 if (rev >= 0x11 && rev <= 0x15) {
140 amd_gen = CHIPSET_HUDSON234;
141 msg_pdbg("Hudson-2/3/4 detected.\n");
Martin Roth82b6ec12014-07-15 13:50:58 +0000142 } else if (rev == 0x16) {
143 amd_gen = CHIPSET_BOLTON;
144 msg_pdbg("Bolton detected.\n");
Stefan Tauner5c316f92015-02-08 21:57:52 +0000145 } else if ((rev >= 0x39 && rev <= 0x3A) || rev == 0x42) {
Stefan Tauner463dd692013-08-08 12:00:19 +0000146 amd_gen = CHIPSET_YANGTZE;
147 msg_pdbg("Yangtze detected.\n");
148 } else {
149 msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n"
150 "Please report this to flashrom@flashrom.org and include this log and\n"
151 "the output of lspci -nnvx, thanks!.\n", rev);
152 }
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100153 } else if (dev->device_id == 0x790e) {
Edward O'Callaghanc0a27e12019-10-29 17:05:39 +1100154 int rev = find_smbus_dev_rev(0x1022, 0x790B);
155 if (rev < 0)
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100156 return;
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100157 if (rev == 0x4a) {
158 amd_gen = CHIPSET_YANGTZE;
159 msg_pdbg("Yangtze detected.\n");
160 } else {
161 msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n"
162 "Please report this to flashrom@flashrom.org and include this log and\n"
163 "the output of lspci -nnvx, thanks!.\n", rev);
164 }
165
166
Stefan Tauner463dd692013-08-08 12:00:19 +0000167#endif
Stefan Tauner4442b812013-09-12 15:48:35 +0000168 } else
169 msg_pwarn("%s: Unknown LPC device %" PRIx16 ":%" PRIx16 ".\n"
170 "Please report this to flashrom@flashrom.org and include this log and\n"
171 "the output of lspci -nnvx, thanks!\n",
172 __func__, dev->vendor_id, dev->device_id);
Stefan Tauner463dd692013-08-08 12:00:19 +0000173}
Jason Wanga3f04be2008-11-28 21:36:51 +0000174
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +0000175static void reset_internal_fifo_pointer(void)
Jason Wanga3f04be2008-11-28 21:36:51 +0000176{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000177 mmio_writeb(mmio_readb(sb600_spibar + 2) | 0x10, sb600_spibar + 2);
Jason Wanga3f04be2008-11-28 21:36:51 +0000178
Rudolf Marek70e14592013-07-25 22:58:56 +0000179 /* FIXME: This loop needs a timeout and a clearer message. */
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000180 while (mmio_readb(sb600_spibar + 0xD) & 0x7)
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000181 msg_pspew("reset\n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000182}
183
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000184static int compare_internal_fifo_pointer(uint8_t want)
185{
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000186 uint8_t have = mmio_readb(sb600_spibar + 0xd) & 0x07;
187 want %= FIFO_SIZE_OLD;
188 if (have != want) {
189 msg_perr("AMD SPI FIFO pointer corruption! Pointer is %d, wanted %d\n", have, want);
190 msg_perr("Something else is accessing the flash chip and causes random corruption.\n"
191 "Please stop all applications and drivers and IPMI which access the flash chip.\n");
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000192 return 1;
193 } else {
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000194 msg_pspew("AMD SPI FIFO pointer is %d, wanted %d\n", have, want);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000195 return 0;
196 }
197}
198
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000199/* Check the number of bytes to be transmitted and extract opcode. */
200static int check_readwritecnt(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt)
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000201{
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000202 unsigned int maxwritecnt = flash->mst->spi.max_data_write + 3;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000203 if (writecnt > maxwritecnt) {
204 msg_pinfo("%s: SPI controller can not send %d bytes, it is limited to %d bytes\n",
205 __func__, writecnt, maxwritecnt);
206 return SPI_INVALID_LENGTH;
207 }
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000208
Stefan Tauner6697f712014-08-06 15:09:15 +0000209 unsigned int maxreadcnt = flash->mst->spi.max_data_read;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000210 if (readcnt > maxreadcnt) {
211 msg_pinfo("%s: SPI controller can not receive %d bytes, it is limited to %d bytes\n",
212 __func__, readcnt, maxreadcnt);
213 return SPI_INVALID_LENGTH;
214 }
215 return 0;
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000216}
217
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +0000218static void execute_command(void)
Jason Wanga3f04be2008-11-28 21:36:51 +0000219{
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000220 msg_pspew("Executing... ");
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000221 mmio_writeb(mmio_readb(sb600_spibar + 2) | 1, sb600_spibar + 2);
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000222 while (mmio_readb(sb600_spibar + 2) & 1)
Jason Wanga3f04be2008-11-28 21:36:51 +0000223 ;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000224 msg_pspew("done\n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000225}
226
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000227static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt,
228 unsigned int readcnt,
229 const unsigned char *writearr,
230 unsigned char *readarr)
Jason Wanga3f04be2008-11-28 21:36:51 +0000231{
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000232 /* First byte is cmd which can not be sent through the FIFO. */
Jason Wanga3f04be2008-11-28 21:36:51 +0000233 unsigned char cmd = *writearr++;
Jason Wanga3f04be2008-11-28 21:36:51 +0000234 writecnt--;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000235 msg_pspew("%s, cmd=0x%02x, writecnt=%d, readcnt=%d\n", __func__, cmd, writecnt, readcnt);
236 mmio_writeb(cmd, sb600_spibar + 0);
Jason Wanga3f04be2008-11-28 21:36:51 +0000237
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000238 int ret = check_readwritecnt(flash, writecnt, readcnt);
239 if (ret != 0)
240 return ret;
Jason Wanga3f04be2008-11-28 21:36:51 +0000241
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000242 /* This is a workaround for a bug in SPI controller. If we only send
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000243 * an opcode and no additional data/address, the SPI controller will
244 * read one byte too few from the chip. Basically, the last byte of
245 * the chip response is discarded and will not end up in the FIFO.
246 * It is unclear if the CS# line is set high too early as well.
247 */
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000248 unsigned int readoffby1 = (writecnt > 0) ? 0 : 1;
249 uint8_t readwrite = (readcnt + readoffby1) << 4 | (writecnt);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000250 mmio_writeb(readwrite, sb600_spibar + 1);
Jason Wanga3f04be2008-11-28 21:36:51 +0000251
Jason Wanga3f04be2008-11-28 21:36:51 +0000252 reset_internal_fifo_pointer();
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000253 msg_pspew("Filling FIFO: ");
Nico Huber519be662018-12-23 20:03:35 +0100254 unsigned int count;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000255 for (count = 0; count < writecnt; count++) {
256 msg_pspew("[%02x]", writearr[count]);
257 mmio_writeb(writearr[count], sb600_spibar + 0xC);
Jason Wanga3f04be2008-11-28 21:36:51 +0000258 }
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000259 msg_pspew("\n");
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000260 if (compare_internal_fifo_pointer(writecnt))
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000261 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000262
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000263 /*
264 * We should send the data in sequence, which means we need to reset
265 * the FIFO pointer to the first byte we want to send.
266 */
267 reset_internal_fifo_pointer();
Jason Wanga3f04be2008-11-28 21:36:51 +0000268 execute_command();
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000269 if (compare_internal_fifo_pointer(writecnt + readcnt))
270 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000271
272 /*
273 * After the command executed, we should find out the index of the
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000274 * received byte. Here we just reset the FIFO pointer and skip the
275 * writecnt.
276 * It would be possible to increase the FIFO pointer by one instead
277 * of reading and discarding one byte from the FIFO.
278 * The FIFO is implemented on top of an 8 byte ring buffer and the
279 * buffer is never cleared. For every byte that is shifted out after
280 * the opcode, the FIFO already stores the response from the chip.
281 * Usually, the chip will respond with 0x00 or 0xff.
Jason Wanga3f04be2008-11-28 21:36:51 +0000282 */
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000283 reset_internal_fifo_pointer();
Jason Wanga3f04be2008-11-28 21:36:51 +0000284
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000285 /* Skip the bytes we sent. */
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000286 msg_pspew("Skipping: ");
Jason Wanga3f04be2008-11-28 21:36:51 +0000287 for (count = 0; count < writecnt; count++) {
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000288 msg_pspew("[%02x]", mmio_readb(sb600_spibar + 0xC));
Jason Wanga3f04be2008-11-28 21:36:51 +0000289 }
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000290 msg_pspew("\n");
291 if (compare_internal_fifo_pointer(writecnt))
292 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000293
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000294 msg_pspew("Reading FIFO: ");
295 for (count = 0; count < readcnt; count++) {
296 readarr[count] = mmio_readb(sb600_spibar + 0xC);
297 msg_pspew("[%02x]", readarr[count]);
Jason Wanga3f04be2008-11-28 21:36:51 +0000298 }
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000299 msg_pspew("\n");
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000300 if (compare_internal_fifo_pointer(writecnt+readcnt))
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000301 return SPI_PROGRAMMER_ERROR;
302
303 if (mmio_readb(sb600_spibar + 1) != readwrite) {
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000304 msg_perr("Unexpected change in AMD SPI read/write count!\n");
305 msg_perr("Something else is accessing the flash chip and causes random corruption.\n"
306 "Please stop all applications and drivers and IPMI which access the flash chip.\n");
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000307 return SPI_PROGRAMMER_ERROR;
308 }
Jason Wanga3f04be2008-11-28 21:36:51 +0000309
310 return 0;
311}
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000312
Wei Hu31402ee2014-05-16 21:39:33 +0000313static int spi100_spi_send_command(struct flashctx *flash, unsigned int writecnt,
314 unsigned int readcnt,
315 const unsigned char *writearr,
316 unsigned char *readarr)
317{
318 /* First byte is cmd which can not be sent through the buffer. */
319 unsigned char cmd = *writearr++;
320 writecnt--;
321 msg_pspew("%s, cmd=0x%02x, writecnt=%d, readcnt=%d\n", __func__, cmd, writecnt, readcnt);
322 mmio_writeb(cmd, sb600_spibar + 0);
323
324 int ret = check_readwritecnt(flash, writecnt, readcnt);
325 if (ret != 0)
326 return ret;
327
328 /* Use the extended TxByteCount and RxByteCount registers. */
329 mmio_writeb(writecnt, sb600_spibar + 0x48);
330 mmio_writeb(readcnt, sb600_spibar + 0x4b);
331
332 msg_pspew("Filling buffer: ");
Nico Huber519be662018-12-23 20:03:35 +0100333 unsigned int count;
Wei Hu31402ee2014-05-16 21:39:33 +0000334 for (count = 0; count < writecnt; count++) {
335 msg_pspew("[%02x]", writearr[count]);
336 mmio_writeb(writearr[count], sb600_spibar + 0x80 + count);
337 }
338 msg_pspew("\n");
339
340 execute_command();
341
342 msg_pspew("Reading buffer: ");
343 for (count = 0; count < readcnt; count++) {
344 readarr[count] = mmio_readb(sb600_spibar + 0x80 + (writecnt + count) % FIFO_SIZE_YANGTZE);
345 msg_pspew("[%02x]", readarr[count]);
346 }
347 msg_pspew("\n");
348
349 return 0;
350}
351
Stefan Taunera6a0d202013-09-15 14:17:39 +0000352struct spispeed {
353 const char *const name;
354 const uint8_t speed;
355};
356
357static const struct spispeed spispeeds[] = {
358 { "66 MHz", 0x00 },
359 { "33 MHz", 0x01 },
360 { "22 MHz", 0x02 },
361 { "16.5 MHz", 0x03 },
Wei Hu31402ee2014-05-16 21:39:33 +0000362 { "100 MHz", 0x04 },
363 { "Reserved", 0x05 },
364 { "Reserved", 0x06 },
365 { "800 kHz", 0x07 },
Stefan Taunera6a0d202013-09-15 14:17:39 +0000366};
367
368static int set_speed(struct pci_dev *dev, const struct spispeed *spispeed)
369{
370 bool success = false;
371 uint8_t speed = spispeed->speed;
372
373 msg_pdbg("Setting SPI clock to %s (0x%x).\n", spispeed->name, speed);
Wei Hu31402ee2014-05-16 21:39:33 +0000374 if (amd_gen >= CHIPSET_YANGTZE) {
375 rmmio_writew((speed << 12) | (speed << 8) | (speed << 4) | speed, sb600_spibar + 0x22);
376 uint16_t tmp = mmio_readw(sb600_spibar + 0x22);
377 success = (((tmp >> 12) & 0xf) == speed && ((tmp >> 8) & 0xf) == speed &&
378 ((tmp >> 4) & 0xf) == speed && ((tmp >> 0) & 0xf) == speed);
379 } else {
Stefan Taunera6a0d202013-09-15 14:17:39 +0000380 rmmio_writeb((mmio_readb(sb600_spibar + 0xd) & ~(0x3 << 4)) | (speed << 4), sb600_spibar + 0xd);
381 success = (speed == ((mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3));
382 }
383
384 if (!success) {
385 msg_perr("Setting SPI clock failed.\n");
386 return 1;
387 }
388 return 0;
389}
390
Wei Hu31402ee2014-05-16 21:39:33 +0000391static int set_mode(struct pci_dev *dev, uint8_t read_mode)
392{
393 uint32_t tmp = mmio_readl(sb600_spibar + 0x00);
394 tmp &= ~(0x6 << 28 | 0x1 << 18); /* Clear mode bits */
395 tmp |= ((read_mode & 0x6) << 28) | ((read_mode & 0x1) << 18);
396 rmmio_writel(tmp, sb600_spibar + 0x00);
397 if (tmp != mmio_readl(sb600_spibar + 0x00))
398 return 1;
399 return 0;
400}
401
Stefan Taunera6a0d202013-09-15 14:17:39 +0000402static int handle_speed(struct pci_dev *dev)
403{
404 uint32_t tmp;
Carl-Daniel Hailfinger57cdd6b2016-03-12 19:49:14 +0000405 uint8_t spispeed_idx = 3; /* Default to 16.5 MHz */
Stefan Taunera6a0d202013-09-15 14:17:39 +0000406
Stefan Tauner21071b02014-05-16 21:39:48 +0000407 char *spispeed = extract_programmer_param("spispeed");
408 if (spispeed != NULL) {
Carl-Daniel Hailfinger57cdd6b2016-03-12 19:49:14 +0000409 unsigned int i;
410 for (i = 0; i < ARRAY_SIZE(spispeeds); i++) {
411 if (strcasecmp(spispeeds[i].name, spispeed) == 0) {
412 spispeed_idx = i;
413 break;
Stefan Tauner21071b02014-05-16 21:39:48 +0000414 }
Stefan Tauner21071b02014-05-16 21:39:48 +0000415 }
Carl-Daniel Hailfinger57cdd6b2016-03-12 19:49:14 +0000416 /* "reserved" is not a valid speed.
417 * Error out on speeds not present in the spispeeds array.
418 * Only Yangtze supports the second half of indices.
419 * No 66 MHz before SB8xx. */
420 if ((strcasecmp(spispeed, "reserved") == 0) ||
421 (i == ARRAY_SIZE(spispeeds)) ||
422 (amd_gen < CHIPSET_YANGTZE && spispeed_idx > 3) ||
423 (amd_gen < CHIPSET_SB89XX && spispeed_idx == 0)) {
Stefan Tauner21071b02014-05-16 21:39:48 +0000424 msg_perr("Error: Invalid spispeed value: '%s'.\n", spispeed);
425 free(spispeed);
426 return 1;
427 }
428 free(spispeed);
429 }
430
Stefan Taunera6a0d202013-09-15 14:17:39 +0000431 /* See the chipset support matrix for SPI Base_Addr below for an explanation of the symbols used.
Martin Roth82b6ec12014-07-15 13:50:58 +0000432 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson234 bolton/yangtze
Stefan Taunera6a0d202013-09-15 14:17:39 +0000433 * 18 rsvd <- fastReadEnable ? <- ? SpiReadMode[0]
434 * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]
435 */
Martin Roth82b6ec12014-07-15 13:50:58 +0000436 if (amd_gen >= CHIPSET_BOLTON) {
Wei Hu31402ee2014-05-16 21:39:33 +0000437 static const char *spireadmodes[] = {
438 "Normal (up to 33 MHz)", /* 0 */
439 "Reserved", /* 1 */
440 "Dual IO (1-1-2)", /* 2 */
441 "Quad IO (1-1-4)", /* 3 */
442 "Dual IO (1-2-2)", /* 4 */
443 "Quad IO (1-4-4)", /* 5 */
444 "Normal (up to 66 MHz)", /* 6 */
Martin Roth82b6ec12014-07-15 13:50:58 +0000445 "Fast Read", /* 7 (Not defined in the Bolton datasheet.) */
Wei Hu31402ee2014-05-16 21:39:33 +0000446 };
447 tmp = mmio_readl(sb600_spibar + 0x00);
448 uint8_t read_mode = ((tmp >> 28) & 0x6) | ((tmp >> 18) & 0x1);
449 msg_pdbg("SpiReadMode=%s (%i)\n", spireadmodes[read_mode], read_mode);
450 if (read_mode != 6) {
451 read_mode = 6; /* Default to "Normal (up to 66 MHz)" */
452 if (set_mode(dev, read_mode) != 0) {
453 msg_perr("Setting read mode to \"%s\" failed.\n", spireadmodes[read_mode]);
454 return 1;
455 }
456 msg_pdbg("Setting read mode to \"%s\" succeeded.\n", spireadmodes[read_mode]);
457 }
458
Martin Roth82b6ec12014-07-15 13:50:58 +0000459 if (amd_gen >= CHIPSET_YANGTZE) {
460 tmp = mmio_readb(sb600_spibar + 0x20);
461 msg_pdbg("UseSpi100 is %sabled\n", (tmp & 0x1) ? "en" : "dis");
462 if ((tmp & 0x1) == 0) {
463 rmmio_writeb(tmp | 0x1, sb600_spibar + 0x20);
464 tmp = mmio_readb(sb600_spibar + 0x20) & 0x1;
465 if (tmp == 0) {
466 msg_perr("Enabling Spi100 failed.\n");
467 return 1;
468 }
469 msg_pdbg("Enabling Spi100 succeeded.\n");
470 }
471
472 tmp = mmio_readw(sb600_spibar + 0x22); /* SPI 100 Speed Config */
473 msg_pdbg("NormSpeedNew is %s\n", spispeeds[(tmp >> 12) & 0xf].name);
474 msg_pdbg("FastSpeedNew is %s\n", spispeeds[(tmp >> 8) & 0xf].name);
475 msg_pdbg("AltSpeedNew is %s\n", spispeeds[(tmp >> 4) & 0xf].name);
476 msg_pdbg("TpmSpeedNew is %s\n", spispeeds[(tmp >> 0) & 0xf].name);
477 }
Wei Hu31402ee2014-05-16 21:39:33 +0000478 } else {
Stefan Taunera6a0d202013-09-15 14:17:39 +0000479 if (amd_gen >= CHIPSET_SB89XX && amd_gen <= CHIPSET_HUDSON234) {
480 bool fast_read = (mmio_readl(sb600_spibar + 0x00) >> 18) & 0x1;
481 msg_pdbg("Fast Reads are %sabled\n", fast_read ? "en" : "dis");
482 if (fast_read) {
483 msg_pdbg("Disabling them temporarily.\n");
484 rmmio_writel(mmio_readl(sb600_spibar + 0x00) & ~(0x1 << 18),
485 sb600_spibar + 0x00);
486 }
487 }
488 tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3;
489 msg_pdbg("NormSpeed is %s\n", spispeeds[tmp].name);
490 }
491 return set_speed(dev, &spispeeds[spispeed_idx]);
492}
493
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000494static int handle_imc(struct pci_dev *dev)
Rudolf Marek70e14592013-07-25 22:58:56 +0000495{
496 /* Handle IMC everywhere but sb600 which does not have one. */
Stefan Tauner4442b812013-09-12 15:48:35 +0000497 if (amd_gen == CHIPSET_SB6XX)
Rudolf Marek70e14592013-07-25 22:58:56 +0000498 return 0;
499
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000500 bool amd_imc_force = false;
501 char *arg = extract_programmer_param("amd_imc_force");
502 if (arg && !strcmp(arg, "yes")) {
503 amd_imc_force = true;
504 msg_pspew("amd_imc_force enabled.\n");
505 } else if (arg && !strlen(arg)) {
506 msg_perr("Missing argument for amd_imc_force.\n");
507 free(arg);
508 return 1;
509 } else if (arg) {
510 msg_perr("Unknown argument for amd_imc_force: \"%s\" (not \"yes\").\n", arg);
511 free(arg);
512 return 1;
513 }
514 free(arg);
515
Rudolf Marek70e14592013-07-25 22:58:56 +0000516 /* TODO: we should not only look at IntegratedImcPresent (LPC Dev 20, Func 3, 40h) but also at
Stefan Tauner5c316f92015-02-08 21:57:52 +0000517 * IMCEnable(Strap) and Override EcEnable(Strap) (sb8xx, sb9xx?, a50, Bolton: Misc_Reg: 80h-87h;
Rudolf Marek70e14592013-07-25 22:58:56 +0000518 * sb7xx, sp5100: PM_Reg: B0h-B1h) etc. */
519 uint8_t reg = pci_read_byte(dev, 0x40);
520 if ((reg & (1 << 7)) == 0) {
521 msg_pdbg("IMC is not active.\n");
522 return 0;
523 }
524
525 if (!amd_imc_force)
526 programmer_may_write = 0;
Stefan Tauner463dd692013-08-08 12:00:19 +0000527 msg_pinfo("Writes have been disabled for safety reasons because the presence of the IMC\n"
528 "was detected and it could interfere with accessing flash memory. Flashrom will\n"
529 "try to disable it temporarily but even then this might not be safe:\n"
Stefan Tauner0be072c2016-03-13 15:16:30 +0000530 "when it is re-enabled and after a reboot it expects to find working code\n"
Rudolf Marek70e14592013-07-25 22:58:56 +0000531 "in the flash and it is unpredictable what happens if there is none.\n"
532 "\n"
533 "To be safe make sure that there is a working IMC firmware at the right\n"
534 "location in the image you intend to write and do not attempt to erase.\n"
535 "\n"
536 "You can enforce write support with the amd_imc_force programmer option.\n");
537 if (amd_imc_force)
538 msg_pinfo("Continuing with write support because the user forced us to!\n");
539
540 return amd_imc_shutdown(dev);
541}
542
Michael Karcherb05b9e12010-07-22 18:04:19 +0000543int sb600_probe_spi(struct pci_dev *dev)
544{
545 struct pci_dev *smbus_dev;
546 uint32_t tmp;
547 uint8_t reg;
Rudolf Marek70e14592013-07-25 22:58:56 +0000548
Michael Karcherb05b9e12010-07-22 18:04:19 +0000549 /* Read SPI_BaseAddr */
550 tmp = pci_read_long(dev, 0xa0);
551 tmp &= 0xffffffe0; /* remove bits 4-0 (reserved) */
552 msg_pdbg("SPI base address is at 0x%x\n", tmp);
553
554 /* If the BAR has address 0, it is unlikely SPI is used. */
555 if (!tmp)
556 return 0;
557
558 /* Physical memory has to be mapped at page (4k) boundaries. */
Stefan Tauner7fb5aa02013-08-14 15:48:44 +0000559 sb600_spibar = rphysmap("SB600 SPI registers", tmp & 0xfffff000, 0x1000);
560 if (sb600_spibar == ERROR_PTR)
Niklas Söderlund5d307202013-09-14 09:02:27 +0000561 return ERROR_FATAL;
Stefan Tauner7fb5aa02013-08-14 15:48:44 +0000562
Michael Karcherb05b9e12010-07-22 18:04:19 +0000563 /* The low bits of the SPI base address are used as offset into
564 * the mapped page.
565 */
566 sb600_spibar += tmp & 0xfff;
567
Stefan Tauner463dd692013-08-08 12:00:19 +0000568 determine_generation(dev);
Stefan Tauner4442b812013-09-12 15:48:35 +0000569 if (amd_gen == CHIPSET_AMD_UNKNOWN) {
570 msg_perr("Could not determine chipset generation.");
571 return ERROR_NONFATAL;
572 }
Stefan Tauner463dd692013-08-08 12:00:19 +0000573
Stefan Tauner4442b812013-09-12 15:48:35 +0000574 /* How to read the following table and similar ones in this file:
575 * "?" means we have no datasheet for this chipset generation or it doesn't have any relevant info.
576 * "<-" means the bit/register meaning is identical to the next non-"?" chipset to the left. "<-" thus
577 * never refers to another "?".
578 * If a "?" chipset is between two chipsets with identical meaning, we assume the meaning didn't change
579 * twice in between, i.e. the meaning is unchanged for the "?" chipset. Usually we assume that
580 * succeeding hardware supports the same functionality as its predecessor unless proven different by
581 * tests or documentation, hence "?" will often be implemented equally to "<-".
582 *
583 * Chipset support matrix for SPI Base_Addr (LPC PCI reg 0xa0)
584 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson2+ yangtze
585 * 3 rsvd <- <- ? <- ? RouteTpm2Spi
586 * 2 rsvd AbortEnable rsvd ? <- ? <-
587 * 1 rsvd SpiRomEnable <- ? <- ? <-
588 * 0 rsvd AltSpiCSEnable rsvd ? <- ? <-
589 */
590 if (amd_gen >= CHIPSET_SB7XX) {
591 tmp = pci_read_long(dev, 0xa0);
592 msg_pdbg("SpiRomEnable=%i", (tmp >> 1) & 0x1);
593 if (amd_gen == CHIPSET_SB7XX)
594 msg_pdbg(", AltSpiCSEnable=%i, AbortEnable=%i", tmp & 0x1, (tmp >> 2) & 0x1);
Wei Hu31402ee2014-05-16 21:39:33 +0000595 else if (amd_gen == CHIPSET_YANGTZE)
596 msg_pdbg(", RouteTpm2Sp=%i", (tmp >> 3) & 0x1);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000597
Stefan Tauner4442b812013-09-12 15:48:35 +0000598 tmp = pci_read_byte(dev, 0xba);
599 msg_pdbg(", PrefetchEnSPIFromIMC=%i", (tmp & 0x4) >> 2);
600
601 tmp = pci_read_byte(dev, 0xbb);
602 /* FIXME: Set bit 3,6,7 if not already set.
603 * Set bit 5, otherwise SPI accesses are pointless in LPC mode.
604 * See doc 42413 AMD SB700/710/750 RPR.
605 */
606 if (amd_gen == CHIPSET_SB7XX)
607 msg_pdbg(", SpiOpEnInLpcMode=%i", (tmp >> 5) & 0x1);
608 msg_pdbg(", PrefetchEnSPIFromHost=%i\n", tmp & 0x1);
609 }
610
611 /* Chipset support matrix for SPI_Cntrl0 (spibar + 0x0)
612 * See the chipset support matrix for SPI Base_Addr above for an explanation of the symbols used.
613 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson2+ yangtze
614 * 17 rsvd <- <- ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000615 * 18 rsvd <- fastReadEnable<1> ? <- ? SpiReadMode[0]<1>
Stefan Tauner4442b812013-09-12 15:48:35 +0000616 * 19 SpiArbEnable <- <- ? <- ? <-
617 * 20 (FifoPtrClr) <- <- ? <- ? <-
618 * 21 (FifoPtrInc) <- <- ? <- ? IllegalAccess
619 * 22 SpiAccessMacRomEn <- <- ? <- ? <-
620 * 23 SpiHostAccessRomEn <- <- ? <- ? <-
621 * 24:26 ArbWaitCount <- <- ? <- ? <-
622 * 27 SpiBridgeDisable <- <- ? <- ? rsvd
623 * 28 rsvd DropOneClkOnRd = SPIClkGate ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000624 * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]<1>
Stefan Tauner4442b812013-09-12 15:48:35 +0000625 * 31 rsvd <- SpiBusy ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000626 *
627 * <1> see handle_speed
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000628 */
Stefan Tauner4442b812013-09-12 15:48:35 +0000629 tmp = mmio_readl(sb600_spibar + 0x00);
630 msg_pdbg("(0x%08" PRIx32 ") SpiArbEnable=%i", tmp, (tmp >> 19) & 0x1);
Wei Hu31402ee2014-05-16 21:39:33 +0000631 if (amd_gen == CHIPSET_YANGTZE)
632 msg_pdbg(", IllegalAccess=%i", (tmp >> 21) & 0x1);
Stefan Tauner4442b812013-09-12 15:48:35 +0000633
634 msg_pdbg(", SpiAccessMacRomEn=%i, SpiHostAccessRomEn=%i, ArbWaitCount=%i",
635 (tmp >> 22) & 0x1, (tmp >> 23) & 0x1, (tmp >> 24) & 0x7);
636
637 if (amd_gen != CHIPSET_YANGTZE)
638 msg_pdbg(", SpiBridgeDisable=%i", (tmp >> 27) & 0x1);
639
640 switch (amd_gen) {
641 case CHIPSET_SB7XX:
642 msg_pdbg(", DropOneClkOnRd/SpiClkGate=%i", (tmp >> 28) & 0x1);
Richard Hughesdb7482b2018-12-19 12:04:30 +0000643 /* Fall through. */
Stefan Tauner4442b812013-09-12 15:48:35 +0000644 case CHIPSET_SB89XX:
645 case CHIPSET_HUDSON234:
Wei Hu31402ee2014-05-16 21:39:33 +0000646 case CHIPSET_YANGTZE:
Stefan Tauner4442b812013-09-12 15:48:35 +0000647 msg_pdbg(", SpiBusy=%i", (tmp >> 31) & 0x1);
648 default: break;
649 }
650 msg_pdbg("\n");
651
652 if (((tmp >> 22) & 0x1) == 0 || ((tmp >> 23) & 0x1) == 0) {
653 msg_perr("ERROR: State of SpiAccessMacRomEn or SpiHostAccessRomEn prohibits full access.\n");
654 return ERROR_NONFATAL;
655 }
656
Stefan Tauner4442b812013-09-12 15:48:35 +0000657 if (amd_gen >= CHIPSET_SB89XX) {
658 tmp = mmio_readb(sb600_spibar + 0x1D);
659 msg_pdbg("Using SPI_CS%d\n", tmp & 0x3);
Wei Hu31402ee2014-05-16 21:39:33 +0000660 /* FIXME: Handle SpiProtect* configuration on Yangtze. */
Stefan Tauner4442b812013-09-12 15:48:35 +0000661 }
662
Michael Karcherb05b9e12010-07-22 18:04:19 +0000663 /* Look for the SMBus device. */
664 smbus_dev = pci_dev_find(0x1002, 0x4385);
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100665 if (!smbus_dev)
Stefan Tauner463dd692013-08-08 12:00:19 +0000666 smbus_dev = pci_dev_find(0x1022, 0x780b); /* AMD FCH */
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100667 if (!smbus_dev)
668 smbus_dev = pci_dev_find(0x1022, 0x790b); /* AMD FP4 */
669 if (!smbus_dev) {
670 msg_perr("ERROR: SMBus device not found. Not enabling SPI.\n");
671 return ERROR_NONFATAL;
Michael Karcherb05b9e12010-07-22 18:04:19 +0000672 }
673
674 /* Note about the bit tests below: If a bit is zero, the GPIO is SPI. */
675 /* GPIO11/SPI_DO and GPIO12/SPI_DI status */
676 reg = pci_read_byte(smbus_dev, 0xAB);
677 reg &= 0xC0;
678 msg_pdbg("GPIO11 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_DO");
679 msg_pdbg("GPIO12 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_DI");
680 if (reg != 0x00) {
681 msg_pdbg("Not enabling SPI");
682 return 0;
683 }
684 /* GPIO31/SPI_HOLD and GPIO32/SPI_CS status */
685 reg = pci_read_byte(smbus_dev, 0x83);
686 reg &= 0xC0;
687 msg_pdbg("GPIO31 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_HOLD");
688 msg_pdbg("GPIO32 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_CS");
689 /* SPI_HOLD is not used on all boards, filter it out. */
690 if ((reg & 0x80) != 0x00) {
691 msg_pdbg("Not enabling SPI");
692 return 0;
693 }
694 /* GPIO47/SPI_CLK status */
695 reg = pci_read_byte(smbus_dev, 0xA7);
696 reg &= 0x40;
697 msg_pdbg("GPIO47 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_CLK");
698 if (reg != 0x00) {
699 msg_pdbg("Not enabling SPI");
700 return 0;
701 }
702
Stefan Taunera6a0d202013-09-15 14:17:39 +0000703 if (handle_speed(dev) != 0)
704 return ERROR_FATAL;
705
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000706 if (handle_imc(dev) != 0)
Rudolf Marek70e14592013-07-25 22:58:56 +0000707 return ERROR_FATAL;
Carl-Daniel Hailfinger39446e32010-09-15 12:02:07 +0000708
Wei Hu31402ee2014-05-16 21:39:33 +0000709 /* Starting with Yangtze the SPI controller got a different interface with a much bigger buffer. */
710 if (amd_gen != CHIPSET_YANGTZE)
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000711 register_spi_master(&spi_master_sb600);
Wei Hu31402ee2014-05-16 21:39:33 +0000712 else
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000713 register_spi_master(&spi_master_yangtze);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000714 return 0;
715}
716
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000717#endif