blob: 050d21045d50bc234265cca2158ffc49351dcc4e [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
Edward O'Callaghan9355e6f2019-10-29 18:18:18 +110094/* Determine the chipset's version and identify the respective SMBUS device. */
95static int determine_generation(struct pci_dev *dev)
Stefan Tauner463dd692013-08-08 12:00:19 +000096{
97 amd_gen = CHIPSET_AMD_UNKNOWN;
Stefan Tauner4442b812013-09-12 15:48:35 +000098 msg_pdbg2("Trying to determine the generation of the SPI interface... ");
99 if (dev->device_id == 0x438d) {
100 amd_gen = CHIPSET_SB6XX;
101 msg_pdbg("SB6xx detected.\n");
102 } else if (dev->device_id == 0x439d) {
Edward O'Callaghanc0a27e12019-10-29 17:05:39 +1100103 int rev = find_smbus_dev_rev(0x1002, 0x4385);
104 if (rev < 0)
Edward O'Callaghan9355e6f2019-10-29 18:18:18 +1100105 return -1;
Stefan Tauner4442b812013-09-12 15:48:35 +0000106 if (rev >= 0x39 && rev <= 0x3D) {
107 amd_gen = CHIPSET_SB7XX;
108 msg_pdbg("SB7xx/SP5100 detected.\n");
109 } else if (rev >= 0x40 && rev <= 0x42) {
110 amd_gen = CHIPSET_SB89XX;
111 msg_pdbg("SB8xx/SB9xx/Hudson-1 detected.\n");
112 } else {
113 msg_pwarn("SB device found but SMBus revision 0x%02x does not match known values.\n"
114 "Assuming SB8xx/SB9xx/Hudson-1. Please send a log to flashrom@flashrom.org\n",
115 rev);
116 amd_gen = CHIPSET_SB89XX;
117 }
118 } else if (dev->device_id == 0x780e) {
Stefan Tauner463dd692013-08-08 12:00:19 +0000119 /* The PCI ID of the LPC bridge doesn't change between Hudson-2/3/4 and Yangtze (Kabini/Temash)
120 * although they use different SPI interfaces. */
121#ifdef USE_YANGTZE_HEURISTICS
122 /* This heuristic accesses the SPI interface MMIO BAR at locations beyond those supported by
123 * Hudson in the hope of getting 0xff readback on older chipsets and non-0xff readback on
124 * Yangtze (and newer, compatible chipsets). */
125 int i;
126 msg_pdbg("Checking for AMD Yangtze (Kabini/Temash) or later... ");
127 for (i = 0x20; i <= 0x4f; i++) {
128 if (mmio_readb(sb600_spibar + i) != 0xff) {
129 amd_gen = CHIPSET_YANGTZE;
130 msg_pdbg("found.\n");
Edward O'Callaghan9355e6f2019-10-29 18:18:18 +1100131 return 0;
Stefan Tauner463dd692013-08-08 12:00:19 +0000132 }
133 }
134 msg_pdbg("not found. Assuming Hudson.\n");
135 amd_gen = CHIPSET_HUDSON234;
136#else
Edward O'Callaghanc0a27e12019-10-29 17:05:39 +1100137 int rev = find_smbus_dev_rev(0x1022, 0x780B);
138 if (rev < 0)
Edward O'Callaghan9355e6f2019-10-29 18:18:18 +1100139 return -1;
Stefan Tauner463dd692013-08-08 12:00:19 +0000140 if (rev >= 0x11 && rev <= 0x15) {
141 amd_gen = CHIPSET_HUDSON234;
142 msg_pdbg("Hudson-2/3/4 detected.\n");
Martin Roth82b6ec12014-07-15 13:50:58 +0000143 } else if (rev == 0x16) {
144 amd_gen = CHIPSET_BOLTON;
145 msg_pdbg("Bolton detected.\n");
Stefan Tauner5c316f92015-02-08 21:57:52 +0000146 } else if ((rev >= 0x39 && rev <= 0x3A) || rev == 0x42) {
Stefan Tauner463dd692013-08-08 12:00:19 +0000147 amd_gen = CHIPSET_YANGTZE;
148 msg_pdbg("Yangtze detected.\n");
149 } else {
150 msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n"
151 "Please report this to flashrom@flashrom.org and include this log and\n"
152 "the output of lspci -nnvx, thanks!.\n", rev);
153 }
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100154 } else if (dev->device_id == 0x790e) {
Edward O'Callaghanc0a27e12019-10-29 17:05:39 +1100155 int rev = find_smbus_dev_rev(0x1022, 0x790B);
156 if (rev < 0)
Edward O'Callaghan9355e6f2019-10-29 18:18:18 +1100157 return -1;
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100158 if (rev == 0x4a) {
159 amd_gen = CHIPSET_YANGTZE;
160 msg_pdbg("Yangtze detected.\n");
161 } else {
162 msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n"
163 "Please report this to flashrom@flashrom.org and include this log and\n"
164 "the output of lspci -nnvx, thanks!.\n", rev);
165 }
166
167
Stefan Tauner463dd692013-08-08 12:00:19 +0000168#endif
Stefan Tauner4442b812013-09-12 15:48:35 +0000169 } else
170 msg_pwarn("%s: Unknown LPC device %" PRIx16 ":%" PRIx16 ".\n"
171 "Please report this to flashrom@flashrom.org and include this log and\n"
172 "the output of lspci -nnvx, thanks!\n",
173 __func__, dev->vendor_id, dev->device_id);
Edward O'Callaghan9355e6f2019-10-29 18:18:18 +1100174 if (amd_gen == CHIPSET_AMD_UNKNOWN) {
175 msg_perr("Could not determine chipset generation.");
176 return -1;
177 }
178 return 0;
Stefan Tauner463dd692013-08-08 12:00:19 +0000179}
Jason Wanga3f04be2008-11-28 21:36:51 +0000180
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +0000181static void reset_internal_fifo_pointer(void)
Jason Wanga3f04be2008-11-28 21:36:51 +0000182{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000183 mmio_writeb(mmio_readb(sb600_spibar + 2) | 0x10, sb600_spibar + 2);
Jason Wanga3f04be2008-11-28 21:36:51 +0000184
Rudolf Marek70e14592013-07-25 22:58:56 +0000185 /* FIXME: This loop needs a timeout and a clearer message. */
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000186 while (mmio_readb(sb600_spibar + 0xD) & 0x7)
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000187 msg_pspew("reset\n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000188}
189
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000190static int compare_internal_fifo_pointer(uint8_t want)
191{
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000192 uint8_t have = mmio_readb(sb600_spibar + 0xd) & 0x07;
193 want %= FIFO_SIZE_OLD;
194 if (have != want) {
195 msg_perr("AMD SPI FIFO pointer corruption! Pointer is %d, wanted %d\n", have, want);
196 msg_perr("Something else is accessing the flash chip and causes random corruption.\n"
197 "Please stop all applications and drivers and IPMI which access the flash chip.\n");
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000198 return 1;
199 } else {
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000200 msg_pspew("AMD SPI FIFO pointer is %d, wanted %d\n", have, want);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000201 return 0;
202 }
203}
204
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000205/* Check the number of bytes to be transmitted and extract opcode. */
206static int check_readwritecnt(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt)
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000207{
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000208 unsigned int maxwritecnt = flash->mst->spi.max_data_write + 3;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000209 if (writecnt > maxwritecnt) {
210 msg_pinfo("%s: SPI controller can not send %d bytes, it is limited to %d bytes\n",
211 __func__, writecnt, maxwritecnt);
212 return SPI_INVALID_LENGTH;
213 }
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000214
Stefan Tauner6697f712014-08-06 15:09:15 +0000215 unsigned int maxreadcnt = flash->mst->spi.max_data_read;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000216 if (readcnt > maxreadcnt) {
217 msg_pinfo("%s: SPI controller can not receive %d bytes, it is limited to %d bytes\n",
218 __func__, readcnt, maxreadcnt);
219 return SPI_INVALID_LENGTH;
220 }
221 return 0;
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000222}
223
Carl-Daniel Hailfinger2c7ba8c2009-06-23 00:47:26 +0000224static void execute_command(void)
Jason Wanga3f04be2008-11-28 21:36:51 +0000225{
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000226 msg_pspew("Executing... ");
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000227 mmio_writeb(mmio_readb(sb600_spibar + 2) | 1, sb600_spibar + 2);
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000228 while (mmio_readb(sb600_spibar + 2) & 1)
Jason Wanga3f04be2008-11-28 21:36:51 +0000229 ;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000230 msg_pspew("done\n");
Jason Wanga3f04be2008-11-28 21:36:51 +0000231}
232
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000233static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt,
234 unsigned int readcnt,
235 const unsigned char *writearr,
236 unsigned char *readarr)
Jason Wanga3f04be2008-11-28 21:36:51 +0000237{
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000238 /* First byte is cmd which can not be sent through the FIFO. */
Jason Wanga3f04be2008-11-28 21:36:51 +0000239 unsigned char cmd = *writearr++;
Jason Wanga3f04be2008-11-28 21:36:51 +0000240 writecnt--;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000241 msg_pspew("%s, cmd=0x%02x, writecnt=%d, readcnt=%d\n", __func__, cmd, writecnt, readcnt);
242 mmio_writeb(cmd, sb600_spibar + 0);
Jason Wanga3f04be2008-11-28 21:36:51 +0000243
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000244 int ret = check_readwritecnt(flash, writecnt, readcnt);
245 if (ret != 0)
246 return ret;
Jason Wanga3f04be2008-11-28 21:36:51 +0000247
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000248 /* This is a workaround for a bug in SPI controller. If we only send
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000249 * an opcode and no additional data/address, the SPI controller will
250 * read one byte too few from the chip. Basically, the last byte of
251 * the chip response is discarded and will not end up in the FIFO.
252 * It is unclear if the CS# line is set high too early as well.
253 */
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000254 unsigned int readoffby1 = (writecnt > 0) ? 0 : 1;
255 uint8_t readwrite = (readcnt + readoffby1) << 4 | (writecnt);
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000256 mmio_writeb(readwrite, sb600_spibar + 1);
Jason Wanga3f04be2008-11-28 21:36:51 +0000257
Jason Wanga3f04be2008-11-28 21:36:51 +0000258 reset_internal_fifo_pointer();
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000259 msg_pspew("Filling FIFO: ");
Nico Huber519be662018-12-23 20:03:35 +0100260 unsigned int count;
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000261 for (count = 0; count < writecnt; count++) {
262 msg_pspew("[%02x]", writearr[count]);
263 mmio_writeb(writearr[count], sb600_spibar + 0xC);
Jason Wanga3f04be2008-11-28 21:36:51 +0000264 }
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000265 msg_pspew("\n");
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000266 if (compare_internal_fifo_pointer(writecnt))
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000267 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000268
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000269 /*
270 * We should send the data in sequence, which means we need to reset
271 * the FIFO pointer to the first byte we want to send.
272 */
273 reset_internal_fifo_pointer();
Jason Wanga3f04be2008-11-28 21:36:51 +0000274 execute_command();
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000275 if (compare_internal_fifo_pointer(writecnt + readcnt))
276 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000277
278 /*
279 * After the command executed, we should find out the index of the
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000280 * received byte. Here we just reset the FIFO pointer and skip the
281 * writecnt.
282 * It would be possible to increase the FIFO pointer by one instead
283 * of reading and discarding one byte from the FIFO.
284 * The FIFO is implemented on top of an 8 byte ring buffer and the
285 * buffer is never cleared. For every byte that is shifted out after
286 * the opcode, the FIFO already stores the response from the chip.
287 * Usually, the chip will respond with 0x00 or 0xff.
Jason Wanga3f04be2008-11-28 21:36:51 +0000288 */
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000289 reset_internal_fifo_pointer();
Jason Wanga3f04be2008-11-28 21:36:51 +0000290
Carl-Daniel Hailfingerf8555e22009-07-23 01:36:08 +0000291 /* Skip the bytes we sent. */
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000292 msg_pspew("Skipping: ");
Jason Wanga3f04be2008-11-28 21:36:51 +0000293 for (count = 0; count < writecnt; count++) {
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000294 msg_pspew("[%02x]", mmio_readb(sb600_spibar + 0xC));
Jason Wanga3f04be2008-11-28 21:36:51 +0000295 }
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000296 msg_pspew("\n");
297 if (compare_internal_fifo_pointer(writecnt))
298 return SPI_PROGRAMMER_ERROR;
Jason Wanga3f04be2008-11-28 21:36:51 +0000299
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000300 msg_pspew("Reading FIFO: ");
301 for (count = 0; count < readcnt; count++) {
302 readarr[count] = mmio_readb(sb600_spibar + 0xC);
303 msg_pspew("[%02x]", readarr[count]);
Jason Wanga3f04be2008-11-28 21:36:51 +0000304 }
Carl-Daniel Hailfinger643415b2010-01-10 01:59:50 +0000305 msg_pspew("\n");
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000306 if (compare_internal_fifo_pointer(writecnt+readcnt))
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000307 return SPI_PROGRAMMER_ERROR;
308
309 if (mmio_readb(sb600_spibar + 1) != readwrite) {
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000310 msg_perr("Unexpected change in AMD SPI read/write count!\n");
311 msg_perr("Something else is accessing the flash chip and causes random corruption.\n"
312 "Please stop all applications and drivers and IPMI which access the flash chip.\n");
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000313 return SPI_PROGRAMMER_ERROR;
314 }
Jason Wanga3f04be2008-11-28 21:36:51 +0000315
316 return 0;
317}
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000318
Wei Hu31402ee2014-05-16 21:39:33 +0000319static int spi100_spi_send_command(struct flashctx *flash, unsigned int writecnt,
320 unsigned int readcnt,
321 const unsigned char *writearr,
322 unsigned char *readarr)
323{
324 /* First byte is cmd which can not be sent through the buffer. */
325 unsigned char cmd = *writearr++;
326 writecnt--;
327 msg_pspew("%s, cmd=0x%02x, writecnt=%d, readcnt=%d\n", __func__, cmd, writecnt, readcnt);
328 mmio_writeb(cmd, sb600_spibar + 0);
329
330 int ret = check_readwritecnt(flash, writecnt, readcnt);
331 if (ret != 0)
332 return ret;
333
334 /* Use the extended TxByteCount and RxByteCount registers. */
335 mmio_writeb(writecnt, sb600_spibar + 0x48);
336 mmio_writeb(readcnt, sb600_spibar + 0x4b);
337
338 msg_pspew("Filling buffer: ");
Nico Huber519be662018-12-23 20:03:35 +0100339 unsigned int count;
Wei Hu31402ee2014-05-16 21:39:33 +0000340 for (count = 0; count < writecnt; count++) {
341 msg_pspew("[%02x]", writearr[count]);
342 mmio_writeb(writearr[count], sb600_spibar + 0x80 + count);
343 }
344 msg_pspew("\n");
345
346 execute_command();
347
348 msg_pspew("Reading buffer: ");
349 for (count = 0; count < readcnt; count++) {
350 readarr[count] = mmio_readb(sb600_spibar + 0x80 + (writecnt + count) % FIFO_SIZE_YANGTZE);
351 msg_pspew("[%02x]", readarr[count]);
352 }
353 msg_pspew("\n");
354
355 return 0;
356}
357
Stefan Taunera6a0d202013-09-15 14:17:39 +0000358struct spispeed {
359 const char *const name;
360 const uint8_t speed;
361};
362
363static const struct spispeed spispeeds[] = {
364 { "66 MHz", 0x00 },
365 { "33 MHz", 0x01 },
366 { "22 MHz", 0x02 },
367 { "16.5 MHz", 0x03 },
Wei Hu31402ee2014-05-16 21:39:33 +0000368 { "100 MHz", 0x04 },
369 { "Reserved", 0x05 },
370 { "Reserved", 0x06 },
371 { "800 kHz", 0x07 },
Stefan Taunera6a0d202013-09-15 14:17:39 +0000372};
373
374static int set_speed(struct pci_dev *dev, const struct spispeed *spispeed)
375{
376 bool success = false;
377 uint8_t speed = spispeed->speed;
378
379 msg_pdbg("Setting SPI clock to %s (0x%x).\n", spispeed->name, speed);
Wei Hu31402ee2014-05-16 21:39:33 +0000380 if (amd_gen >= CHIPSET_YANGTZE) {
381 rmmio_writew((speed << 12) | (speed << 8) | (speed << 4) | speed, sb600_spibar + 0x22);
382 uint16_t tmp = mmio_readw(sb600_spibar + 0x22);
383 success = (((tmp >> 12) & 0xf) == speed && ((tmp >> 8) & 0xf) == speed &&
384 ((tmp >> 4) & 0xf) == speed && ((tmp >> 0) & 0xf) == speed);
385 } else {
Stefan Taunera6a0d202013-09-15 14:17:39 +0000386 rmmio_writeb((mmio_readb(sb600_spibar + 0xd) & ~(0x3 << 4)) | (speed << 4), sb600_spibar + 0xd);
387 success = (speed == ((mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3));
388 }
389
390 if (!success) {
391 msg_perr("Setting SPI clock failed.\n");
392 return 1;
393 }
394 return 0;
395}
396
Wei Hu31402ee2014-05-16 21:39:33 +0000397static int set_mode(struct pci_dev *dev, uint8_t read_mode)
398{
399 uint32_t tmp = mmio_readl(sb600_spibar + 0x00);
400 tmp &= ~(0x6 << 28 | 0x1 << 18); /* Clear mode bits */
401 tmp |= ((read_mode & 0x6) << 28) | ((read_mode & 0x1) << 18);
402 rmmio_writel(tmp, sb600_spibar + 0x00);
403 if (tmp != mmio_readl(sb600_spibar + 0x00))
404 return 1;
405 return 0;
406}
407
Stefan Taunera6a0d202013-09-15 14:17:39 +0000408static int handle_speed(struct pci_dev *dev)
409{
410 uint32_t tmp;
Carl-Daniel Hailfinger57cdd6b2016-03-12 19:49:14 +0000411 uint8_t spispeed_idx = 3; /* Default to 16.5 MHz */
Stefan Taunera6a0d202013-09-15 14:17:39 +0000412
Stefan Tauner21071b02014-05-16 21:39:48 +0000413 char *spispeed = extract_programmer_param("spispeed");
414 if (spispeed != NULL) {
Carl-Daniel Hailfinger57cdd6b2016-03-12 19:49:14 +0000415 unsigned int i;
416 for (i = 0; i < ARRAY_SIZE(spispeeds); i++) {
417 if (strcasecmp(spispeeds[i].name, spispeed) == 0) {
418 spispeed_idx = i;
419 break;
Stefan Tauner21071b02014-05-16 21:39:48 +0000420 }
Stefan Tauner21071b02014-05-16 21:39:48 +0000421 }
Carl-Daniel Hailfinger57cdd6b2016-03-12 19:49:14 +0000422 /* "reserved" is not a valid speed.
423 * Error out on speeds not present in the spispeeds array.
424 * Only Yangtze supports the second half of indices.
425 * No 66 MHz before SB8xx. */
426 if ((strcasecmp(spispeed, "reserved") == 0) ||
427 (i == ARRAY_SIZE(spispeeds)) ||
428 (amd_gen < CHIPSET_YANGTZE && spispeed_idx > 3) ||
429 (amd_gen < CHIPSET_SB89XX && spispeed_idx == 0)) {
Stefan Tauner21071b02014-05-16 21:39:48 +0000430 msg_perr("Error: Invalid spispeed value: '%s'.\n", spispeed);
431 free(spispeed);
432 return 1;
433 }
434 free(spispeed);
435 }
436
Stefan Taunera6a0d202013-09-15 14:17:39 +0000437 /* See the chipset support matrix for SPI Base_Addr below for an explanation of the symbols used.
Martin Roth82b6ec12014-07-15 13:50:58 +0000438 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson234 bolton/yangtze
Stefan Taunera6a0d202013-09-15 14:17:39 +0000439 * 18 rsvd <- fastReadEnable ? <- ? SpiReadMode[0]
440 * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]
441 */
Martin Roth82b6ec12014-07-15 13:50:58 +0000442 if (amd_gen >= CHIPSET_BOLTON) {
Wei Hu31402ee2014-05-16 21:39:33 +0000443 static const char *spireadmodes[] = {
444 "Normal (up to 33 MHz)", /* 0 */
445 "Reserved", /* 1 */
446 "Dual IO (1-1-2)", /* 2 */
447 "Quad IO (1-1-4)", /* 3 */
448 "Dual IO (1-2-2)", /* 4 */
449 "Quad IO (1-4-4)", /* 5 */
450 "Normal (up to 66 MHz)", /* 6 */
Martin Roth82b6ec12014-07-15 13:50:58 +0000451 "Fast Read", /* 7 (Not defined in the Bolton datasheet.) */
Wei Hu31402ee2014-05-16 21:39:33 +0000452 };
453 tmp = mmio_readl(sb600_spibar + 0x00);
454 uint8_t read_mode = ((tmp >> 28) & 0x6) | ((tmp >> 18) & 0x1);
455 msg_pdbg("SpiReadMode=%s (%i)\n", spireadmodes[read_mode], read_mode);
456 if (read_mode != 6) {
457 read_mode = 6; /* Default to "Normal (up to 66 MHz)" */
458 if (set_mode(dev, read_mode) != 0) {
459 msg_perr("Setting read mode to \"%s\" failed.\n", spireadmodes[read_mode]);
460 return 1;
461 }
462 msg_pdbg("Setting read mode to \"%s\" succeeded.\n", spireadmodes[read_mode]);
463 }
464
Martin Roth82b6ec12014-07-15 13:50:58 +0000465 if (amd_gen >= CHIPSET_YANGTZE) {
466 tmp = mmio_readb(sb600_spibar + 0x20);
467 msg_pdbg("UseSpi100 is %sabled\n", (tmp & 0x1) ? "en" : "dis");
468 if ((tmp & 0x1) == 0) {
469 rmmio_writeb(tmp | 0x1, sb600_spibar + 0x20);
470 tmp = mmio_readb(sb600_spibar + 0x20) & 0x1;
471 if (tmp == 0) {
472 msg_perr("Enabling Spi100 failed.\n");
473 return 1;
474 }
475 msg_pdbg("Enabling Spi100 succeeded.\n");
476 }
477
478 tmp = mmio_readw(sb600_spibar + 0x22); /* SPI 100 Speed Config */
479 msg_pdbg("NormSpeedNew is %s\n", spispeeds[(tmp >> 12) & 0xf].name);
480 msg_pdbg("FastSpeedNew is %s\n", spispeeds[(tmp >> 8) & 0xf].name);
481 msg_pdbg("AltSpeedNew is %s\n", spispeeds[(tmp >> 4) & 0xf].name);
482 msg_pdbg("TpmSpeedNew is %s\n", spispeeds[(tmp >> 0) & 0xf].name);
483 }
Wei Hu31402ee2014-05-16 21:39:33 +0000484 } else {
Stefan Taunera6a0d202013-09-15 14:17:39 +0000485 if (amd_gen >= CHIPSET_SB89XX && amd_gen <= CHIPSET_HUDSON234) {
486 bool fast_read = (mmio_readl(sb600_spibar + 0x00) >> 18) & 0x1;
487 msg_pdbg("Fast Reads are %sabled\n", fast_read ? "en" : "dis");
488 if (fast_read) {
489 msg_pdbg("Disabling them temporarily.\n");
490 rmmio_writel(mmio_readl(sb600_spibar + 0x00) & ~(0x1 << 18),
491 sb600_spibar + 0x00);
492 }
493 }
494 tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3;
495 msg_pdbg("NormSpeed is %s\n", spispeeds[tmp].name);
496 }
497 return set_speed(dev, &spispeeds[spispeed_idx]);
498}
499
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000500static int handle_imc(struct pci_dev *dev)
Rudolf Marek70e14592013-07-25 22:58:56 +0000501{
502 /* Handle IMC everywhere but sb600 which does not have one. */
Stefan Tauner4442b812013-09-12 15:48:35 +0000503 if (amd_gen == CHIPSET_SB6XX)
Rudolf Marek70e14592013-07-25 22:58:56 +0000504 return 0;
505
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000506 bool amd_imc_force = false;
507 char *arg = extract_programmer_param("amd_imc_force");
508 if (arg && !strcmp(arg, "yes")) {
509 amd_imc_force = true;
510 msg_pspew("amd_imc_force enabled.\n");
511 } else if (arg && !strlen(arg)) {
512 msg_perr("Missing argument for amd_imc_force.\n");
513 free(arg);
514 return 1;
515 } else if (arg) {
516 msg_perr("Unknown argument for amd_imc_force: \"%s\" (not \"yes\").\n", arg);
517 free(arg);
518 return 1;
519 }
520 free(arg);
521
Rudolf Marek70e14592013-07-25 22:58:56 +0000522 /* TODO: we should not only look at IntegratedImcPresent (LPC Dev 20, Func 3, 40h) but also at
Stefan Tauner5c316f92015-02-08 21:57:52 +0000523 * IMCEnable(Strap) and Override EcEnable(Strap) (sb8xx, sb9xx?, a50, Bolton: Misc_Reg: 80h-87h;
Rudolf Marek70e14592013-07-25 22:58:56 +0000524 * sb7xx, sp5100: PM_Reg: B0h-B1h) etc. */
525 uint8_t reg = pci_read_byte(dev, 0x40);
526 if ((reg & (1 << 7)) == 0) {
527 msg_pdbg("IMC is not active.\n");
528 return 0;
529 }
530
531 if (!amd_imc_force)
532 programmer_may_write = 0;
Stefan Tauner463dd692013-08-08 12:00:19 +0000533 msg_pinfo("Writes have been disabled for safety reasons because the presence of the IMC\n"
534 "was detected and it could interfere with accessing flash memory. Flashrom will\n"
535 "try to disable it temporarily but even then this might not be safe:\n"
Stefan Tauner0be072c2016-03-13 15:16:30 +0000536 "when it is re-enabled and after a reboot it expects to find working code\n"
Rudolf Marek70e14592013-07-25 22:58:56 +0000537 "in the flash and it is unpredictable what happens if there is none.\n"
538 "\n"
539 "To be safe make sure that there is a working IMC firmware at the right\n"
540 "location in the image you intend to write and do not attempt to erase.\n"
541 "\n"
542 "You can enforce write support with the amd_imc_force programmer option.\n");
543 if (amd_imc_force)
544 msg_pinfo("Continuing with write support because the user forced us to!\n");
545
546 return amd_imc_shutdown(dev);
547}
548
Michael Karcherb05b9e12010-07-22 18:04:19 +0000549int sb600_probe_spi(struct pci_dev *dev)
550{
551 struct pci_dev *smbus_dev;
552 uint32_t tmp;
553 uint8_t reg;
Rudolf Marek70e14592013-07-25 22:58:56 +0000554
Michael Karcherb05b9e12010-07-22 18:04:19 +0000555 /* Read SPI_BaseAddr */
556 tmp = pci_read_long(dev, 0xa0);
557 tmp &= 0xffffffe0; /* remove bits 4-0 (reserved) */
558 msg_pdbg("SPI base address is at 0x%x\n", tmp);
559
560 /* If the BAR has address 0, it is unlikely SPI is used. */
561 if (!tmp)
562 return 0;
563
564 /* Physical memory has to be mapped at page (4k) boundaries. */
Stefan Tauner7fb5aa02013-08-14 15:48:44 +0000565 sb600_spibar = rphysmap("SB600 SPI registers", tmp & 0xfffff000, 0x1000);
566 if (sb600_spibar == ERROR_PTR)
Niklas Söderlund5d307202013-09-14 09:02:27 +0000567 return ERROR_FATAL;
Stefan Tauner7fb5aa02013-08-14 15:48:44 +0000568
Michael Karcherb05b9e12010-07-22 18:04:19 +0000569 /* The low bits of the SPI base address are used as offset into
570 * the mapped page.
571 */
572 sb600_spibar += tmp & 0xfff;
573
Edward O'Callaghan9355e6f2019-10-29 18:18:18 +1100574 if (determine_generation(dev) < 0)
Stefan Tauner4442b812013-09-12 15:48:35 +0000575 return ERROR_NONFATAL;
Stefan Tauner463dd692013-08-08 12:00:19 +0000576
Stefan Tauner4442b812013-09-12 15:48:35 +0000577 /* How to read the following table and similar ones in this file:
578 * "?" means we have no datasheet for this chipset generation or it doesn't have any relevant info.
579 * "<-" means the bit/register meaning is identical to the next non-"?" chipset to the left. "<-" thus
580 * never refers to another "?".
581 * If a "?" chipset is between two chipsets with identical meaning, we assume the meaning didn't change
582 * twice in between, i.e. the meaning is unchanged for the "?" chipset. Usually we assume that
583 * succeeding hardware supports the same functionality as its predecessor unless proven different by
584 * tests or documentation, hence "?" will often be implemented equally to "<-".
585 *
586 * Chipset support matrix for SPI Base_Addr (LPC PCI reg 0xa0)
587 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson2+ yangtze
588 * 3 rsvd <- <- ? <- ? RouteTpm2Spi
589 * 2 rsvd AbortEnable rsvd ? <- ? <-
590 * 1 rsvd SpiRomEnable <- ? <- ? <-
591 * 0 rsvd AltSpiCSEnable rsvd ? <- ? <-
592 */
593 if (amd_gen >= CHIPSET_SB7XX) {
594 tmp = pci_read_long(dev, 0xa0);
595 msg_pdbg("SpiRomEnable=%i", (tmp >> 1) & 0x1);
596 if (amd_gen == CHIPSET_SB7XX)
597 msg_pdbg(", AltSpiCSEnable=%i, AbortEnable=%i", tmp & 0x1, (tmp >> 2) & 0x1);
Wei Hu31402ee2014-05-16 21:39:33 +0000598 else if (amd_gen == CHIPSET_YANGTZE)
599 msg_pdbg(", RouteTpm2Sp=%i", (tmp >> 3) & 0x1);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000600
Stefan Tauner4442b812013-09-12 15:48:35 +0000601 tmp = pci_read_byte(dev, 0xba);
602 msg_pdbg(", PrefetchEnSPIFromIMC=%i", (tmp & 0x4) >> 2);
603
604 tmp = pci_read_byte(dev, 0xbb);
605 /* FIXME: Set bit 3,6,7 if not already set.
606 * Set bit 5, otherwise SPI accesses are pointless in LPC mode.
607 * See doc 42413 AMD SB700/710/750 RPR.
608 */
609 if (amd_gen == CHIPSET_SB7XX)
610 msg_pdbg(", SpiOpEnInLpcMode=%i", (tmp >> 5) & 0x1);
611 msg_pdbg(", PrefetchEnSPIFromHost=%i\n", tmp & 0x1);
612 }
613
614 /* Chipset support matrix for SPI_Cntrl0 (spibar + 0x0)
615 * See the chipset support matrix for SPI Base_Addr above for an explanation of the symbols used.
616 * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson2+ yangtze
617 * 17 rsvd <- <- ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000618 * 18 rsvd <- fastReadEnable<1> ? <- ? SpiReadMode[0]<1>
Stefan Tauner4442b812013-09-12 15:48:35 +0000619 * 19 SpiArbEnable <- <- ? <- ? <-
620 * 20 (FifoPtrClr) <- <- ? <- ? <-
621 * 21 (FifoPtrInc) <- <- ? <- ? IllegalAccess
622 * 22 SpiAccessMacRomEn <- <- ? <- ? <-
623 * 23 SpiHostAccessRomEn <- <- ? <- ? <-
624 * 24:26 ArbWaitCount <- <- ? <- ? <-
625 * 27 SpiBridgeDisable <- <- ? <- ? rsvd
626 * 28 rsvd DropOneClkOnRd = SPIClkGate ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000627 * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]<1>
Stefan Tauner4442b812013-09-12 15:48:35 +0000628 * 31 rsvd <- SpiBusy ? <- ? <-
Stefan Taunera6a0d202013-09-15 14:17:39 +0000629 *
630 * <1> see handle_speed
Carl-Daniel Hailfingereb0e7fc2010-08-18 15:12:43 +0000631 */
Stefan Tauner4442b812013-09-12 15:48:35 +0000632 tmp = mmio_readl(sb600_spibar + 0x00);
633 msg_pdbg("(0x%08" PRIx32 ") SpiArbEnable=%i", tmp, (tmp >> 19) & 0x1);
Wei Hu31402ee2014-05-16 21:39:33 +0000634 if (amd_gen == CHIPSET_YANGTZE)
635 msg_pdbg(", IllegalAccess=%i", (tmp >> 21) & 0x1);
Stefan Tauner4442b812013-09-12 15:48:35 +0000636
637 msg_pdbg(", SpiAccessMacRomEn=%i, SpiHostAccessRomEn=%i, ArbWaitCount=%i",
638 (tmp >> 22) & 0x1, (tmp >> 23) & 0x1, (tmp >> 24) & 0x7);
639
640 if (amd_gen != CHIPSET_YANGTZE)
641 msg_pdbg(", SpiBridgeDisable=%i", (tmp >> 27) & 0x1);
642
643 switch (amd_gen) {
644 case CHIPSET_SB7XX:
645 msg_pdbg(", DropOneClkOnRd/SpiClkGate=%i", (tmp >> 28) & 0x1);
Richard Hughesdb7482b2018-12-19 12:04:30 +0000646 /* Fall through. */
Stefan Tauner4442b812013-09-12 15:48:35 +0000647 case CHIPSET_SB89XX:
648 case CHIPSET_HUDSON234:
Wei Hu31402ee2014-05-16 21:39:33 +0000649 case CHIPSET_YANGTZE:
Stefan Tauner4442b812013-09-12 15:48:35 +0000650 msg_pdbg(", SpiBusy=%i", (tmp >> 31) & 0x1);
651 default: break;
652 }
653 msg_pdbg("\n");
654
655 if (((tmp >> 22) & 0x1) == 0 || ((tmp >> 23) & 0x1) == 0) {
656 msg_perr("ERROR: State of SpiAccessMacRomEn or SpiHostAccessRomEn prohibits full access.\n");
657 return ERROR_NONFATAL;
658 }
659
Stefan Tauner4442b812013-09-12 15:48:35 +0000660 if (amd_gen >= CHIPSET_SB89XX) {
661 tmp = mmio_readb(sb600_spibar + 0x1D);
662 msg_pdbg("Using SPI_CS%d\n", tmp & 0x3);
Wei Hu31402ee2014-05-16 21:39:33 +0000663 /* FIXME: Handle SpiProtect* configuration on Yangtze. */
Stefan Tauner4442b812013-09-12 15:48:35 +0000664 }
665
Michael Karcherb05b9e12010-07-22 18:04:19 +0000666 /* Look for the SMBus device. */
667 smbus_dev = pci_dev_find(0x1002, 0x4385);
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100668 if (!smbus_dev)
Stefan Tauner463dd692013-08-08 12:00:19 +0000669 smbus_dev = pci_dev_find(0x1022, 0x780b); /* AMD FCH */
Ricardo Ribalda Delgado7b629bc2017-03-22 14:08:31 +0100670 if (!smbus_dev)
671 smbus_dev = pci_dev_find(0x1022, 0x790b); /* AMD FP4 */
672 if (!smbus_dev) {
673 msg_perr("ERROR: SMBus device not found. Not enabling SPI.\n");
674 return ERROR_NONFATAL;
Michael Karcherb05b9e12010-07-22 18:04:19 +0000675 }
676
677 /* Note about the bit tests below: If a bit is zero, the GPIO is SPI. */
678 /* GPIO11/SPI_DO and GPIO12/SPI_DI status */
679 reg = pci_read_byte(smbus_dev, 0xAB);
680 reg &= 0xC0;
681 msg_pdbg("GPIO11 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_DO");
682 msg_pdbg("GPIO12 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_DI");
683 if (reg != 0x00) {
684 msg_pdbg("Not enabling SPI");
685 return 0;
686 }
687 /* GPIO31/SPI_HOLD and GPIO32/SPI_CS status */
688 reg = pci_read_byte(smbus_dev, 0x83);
689 reg &= 0xC0;
690 msg_pdbg("GPIO31 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_HOLD");
691 msg_pdbg("GPIO32 used for %s\n", (reg & (1 << 7)) ? "GPIO" : "SPI_CS");
692 /* SPI_HOLD is not used on all boards, filter it out. */
693 if ((reg & 0x80) != 0x00) {
694 msg_pdbg("Not enabling SPI");
695 return 0;
696 }
697 /* GPIO47/SPI_CLK status */
698 reg = pci_read_byte(smbus_dev, 0xA7);
699 reg &= 0x40;
700 msg_pdbg("GPIO47 used for %s\n", (reg & (1 << 6)) ? "GPIO" : "SPI_CLK");
701 if (reg != 0x00) {
702 msg_pdbg("Not enabling SPI");
703 return 0;
704 }
705
Stefan Taunera6a0d202013-09-15 14:17:39 +0000706 if (handle_speed(dev) != 0)
707 return ERROR_FATAL;
708
Stefan Taunerd5b2aef2014-05-16 21:39:28 +0000709 if (handle_imc(dev) != 0)
Rudolf Marek70e14592013-07-25 22:58:56 +0000710 return ERROR_FATAL;
Carl-Daniel Hailfinger39446e32010-09-15 12:02:07 +0000711
Wei Hu31402ee2014-05-16 21:39:33 +0000712 /* Starting with Yangtze the SPI controller got a different interface with a much bigger buffer. */
713 if (amd_gen != CHIPSET_YANGTZE)
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000714 register_spi_master(&spi_master_sb600);
Wei Hu31402ee2014-05-16 21:39:33 +0000715 else
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000716 register_spi_master(&spi_master_yangtze);
Michael Karcherb05b9e12010-07-22 18:04:19 +0000717 return 0;
718}
719
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000720#endif