mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-26 22:52:34 +02:00
sbxxx: Add support for new AMD SPI controller
This patch adds support for the "SPI 100" SPI engine in Yangtze FCHs (found in Kabini and Temash). Tested reading/writing on ASRock IMB-A180 and PC Engines' APU board. Corresponding to flashrom svn r1794. Signed-off-by: Wei Hu <wei@aristanetworks.com> Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at> Acked-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
This commit is contained in:
parent
d5b2aef69d
commit
31402ee687
2
print.c
2
print.c
@ -577,6 +577,7 @@ const struct board_info boards_known[] = {
|
|||||||
B("ASRock", "G31M-S rev 2.0", OK, "http://www.asrock.com/mb/overview.asp?model=G31M-S", NULL),
|
B("ASRock", "G31M-S rev 2.0", OK, "http://www.asrock.com/mb/overview.asp?model=G31M-S", NULL),
|
||||||
B("ASRock", "H61M-ITX", BAD, "http://www.asrock.com/mb/overview.asp?Model=H61M-ITX", "Probing works (Macronix MX25L3205, 4096 kB, SPI), but parts of the flash are problematic: descriptor is r/o (conforming to ICH reqs), ME region is locked."),
|
B("ASRock", "H61M-ITX", BAD, "http://www.asrock.com/mb/overview.asp?Model=H61M-ITX", "Probing works (Macronix MX25L3205, 4096 kB, SPI), but parts of the flash are problematic: descriptor is r/o (conforming to ICH reqs), ME region is locked."),
|
||||||
B("ASRock", "H67M", BAD, "http://www.asrock.com/mb/overview.asp?Model=H67M", "Probing works (Winbond W25Q64, 8192 kB, SPI), but parts of the flash are problematic: descriptor is r/o (conforming to ICH reqs), ME region is locked."),
|
B("ASRock", "H67M", BAD, "http://www.asrock.com/mb/overview.asp?Model=H67M", "Probing works (Winbond W25Q64, 8192 kB, SPI), but parts of the flash are problematic: descriptor is r/o (conforming to ICH reqs), ME region is locked."),
|
||||||
|
B("ASRock", "IMB-180-H", OK, "http://www.asrock.com/ipc/overview.asp?Model=IMB-A180-H", NULL),
|
||||||
B("ASRock", "K7S41", OK, "http://www.asrock.com/mb/overview.asp?Model=K7S41", NULL),
|
B("ASRock", "K7S41", OK, "http://www.asrock.com/mb/overview.asp?Model=K7S41", NULL),
|
||||||
B("ASRock", "K7S41GX", OK, "http://www.asrock.com/mb/overview.asp?Model=K7S41GX", NULL),
|
B("ASRock", "K7S41GX", OK, "http://www.asrock.com/mb/overview.asp?Model=K7S41GX", NULL),
|
||||||
B("ASRock", "K7VT4A+", BAD, "http://www.asrock.com/mb/overview.asp?Model=K7VT4A%2b", "No chip found, probably due to flash translation. http://www.flashrom.org/pipermail/flashrom/2009-August/000393.html"),
|
B("ASRock", "K7VT4A+", BAD, "http://www.asrock.com/mb/overview.asp?Model=K7VT4A%2b", "No chip found, probably due to flash translation. http://www.flashrom.org/pipermail/flashrom/2009-August/000393.html"),
|
||||||
@ -989,6 +990,7 @@ const struct board_info boards_known[] = {
|
|||||||
B("PC Engines", "Alix.3c3", OK, "http://pcengines.ch/alix3c3.htm", NULL),
|
B("PC Engines", "Alix.3c3", OK, "http://pcengines.ch/alix3c3.htm", NULL),
|
||||||
B("PC Engines", "Alix.3d3", OK, "http://pcengines.ch/alix3d3.htm", NULL),
|
B("PC Engines", "Alix.3d3", OK, "http://pcengines.ch/alix3d3.htm", NULL),
|
||||||
B("PC Engines", "Alix.6f2", OK, "http://pcengines.ch/alix6f2.htm", NULL),
|
B("PC Engines", "Alix.6f2", OK, "http://pcengines.ch/alix6f2.htm", NULL),
|
||||||
|
B("PC Engines", "APU", OK, "http://pcengines.ch/apu.htm", NULL),
|
||||||
B("PC Engines", "WRAP.2E", OK, "http://pcengines.ch/wrap2e1.htm", NULL),
|
B("PC Engines", "WRAP.2E", OK, "http://pcengines.ch/wrap2e1.htm", NULL),
|
||||||
B("PCWARE", "APM80-D3", OK, "http://www.pcwarebr.com.br/produtos_mb_apm80-d3.php", "Probably manufactured by ASUS"),
|
B("PCWARE", "APM80-D3", OK, "http://www.pcwarebr.com.br/produtos_mb_apm80-d3.php", "Probably manufactured by ASUS"),
|
||||||
B("Pegatron", "IPP7A-CP", OK, NULL, NULL),
|
B("Pegatron", "IPP7A-CP", OK, NULL, NULL),
|
||||||
|
@ -499,6 +499,7 @@ enum spi_controller {
|
|||||||
SPI_CONTROLLER_IT85XX,
|
SPI_CONTROLLER_IT85XX,
|
||||||
SPI_CONTROLLER_IT87XX,
|
SPI_CONTROLLER_IT87XX,
|
||||||
SPI_CONTROLLER_SB600,
|
SPI_CONTROLLER_SB600,
|
||||||
|
SPI_CONTROLLER_YANGTZE,
|
||||||
SPI_CONTROLLER_VIA,
|
SPI_CONTROLLER_VIA,
|
||||||
SPI_CONTROLLER_WBSIO,
|
SPI_CONTROLLER_WBSIO,
|
||||||
#endif
|
#endif
|
||||||
|
138
sb600spi.c
138
sb600spi.c
@ -4,7 +4,8 @@
|
|||||||
* Copyright (C) 2008 Wang Qingpei <Qingpei.Wang@amd.com>
|
* Copyright (C) 2008 Wang Qingpei <Qingpei.Wang@amd.com>
|
||||||
* Copyright (C) 2008 Joe Bao <Zheng.Bao@amd.com>
|
* Copyright (C) 2008 Joe Bao <Zheng.Bao@amd.com>
|
||||||
* Copyright (C) 2008 Advanced Micro Devices, Inc.
|
* Copyright (C) 2008 Advanced Micro Devices, Inc.
|
||||||
* Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
|
* Copyright (C) 2009, 2010, 2013 Carl-Daniel Hailfinger
|
||||||
|
* Copyright (C) 2013 Stefan Tauner
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -55,9 +56,12 @@ enum amd_chipset {
|
|||||||
static enum amd_chipset amd_gen = CHIPSET_AMD_UNKNOWN;
|
static enum amd_chipset amd_gen = CHIPSET_AMD_UNKNOWN;
|
||||||
|
|
||||||
#define FIFO_SIZE_OLD 8
|
#define FIFO_SIZE_OLD 8
|
||||||
|
#define FIFO_SIZE_YANGTZE 71
|
||||||
|
|
||||||
static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
|
static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
|
||||||
const unsigned char *writearr, unsigned char *readarr);
|
const unsigned char *writearr, unsigned char *readarr);
|
||||||
|
static int spi100_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
|
||||||
|
const unsigned char *writearr, unsigned char *readarr);
|
||||||
|
|
||||||
static struct spi_programmer spi_programmer_sb600 = {
|
static struct spi_programmer spi_programmer_sb600 = {
|
||||||
.type = SPI_CONTROLLER_SB600,
|
.type = SPI_CONTROLLER_SB600,
|
||||||
@ -70,6 +74,17 @@ static struct spi_programmer spi_programmer_sb600 = {
|
|||||||
.write_aai = default_spi_write_aai,
|
.write_aai = default_spi_write_aai,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct spi_programmer spi_programmer_yangtze = {
|
||||||
|
.type = SPI_CONTROLLER_YANGTZE,
|
||||||
|
.max_data_read = FIFO_SIZE_YANGTZE - 3, /* Apparently the big SPI 100 buffer is not a ring buffer. */
|
||||||
|
.max_data_write = FIFO_SIZE_YANGTZE - 3,
|
||||||
|
.command = spi100_spi_send_command,
|
||||||
|
.multicommand = default_spi_send_multicommand,
|
||||||
|
.read = default_spi_read,
|
||||||
|
.write_256 = default_spi_write_256,
|
||||||
|
.write_aai = default_spi_write_aai,
|
||||||
|
};
|
||||||
|
|
||||||
static void determine_generation(struct pci_dev *dev)
|
static void determine_generation(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
amd_gen = CHIPSET_AMD_UNKNOWN;
|
amd_gen = CHIPSET_AMD_UNKNOWN;
|
||||||
@ -276,6 +291,45 @@ static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int spi100_spi_send_command(struct flashctx *flash, unsigned int writecnt,
|
||||||
|
unsigned int readcnt,
|
||||||
|
const unsigned char *writearr,
|
||||||
|
unsigned char *readarr)
|
||||||
|
{
|
||||||
|
/* First byte is cmd which can not be sent through the buffer. */
|
||||||
|
unsigned char cmd = *writearr++;
|
||||||
|
writecnt--;
|
||||||
|
msg_pspew("%s, cmd=0x%02x, writecnt=%d, readcnt=%d\n", __func__, cmd, writecnt, readcnt);
|
||||||
|
mmio_writeb(cmd, sb600_spibar + 0);
|
||||||
|
|
||||||
|
int ret = check_readwritecnt(flash, writecnt, readcnt);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Use the extended TxByteCount and RxByteCount registers. */
|
||||||
|
mmio_writeb(writecnt, sb600_spibar + 0x48);
|
||||||
|
mmio_writeb(readcnt, sb600_spibar + 0x4b);
|
||||||
|
|
||||||
|
msg_pspew("Filling buffer: ");
|
||||||
|
int count;
|
||||||
|
for (count = 0; count < writecnt; count++) {
|
||||||
|
msg_pspew("[%02x]", writearr[count]);
|
||||||
|
mmio_writeb(writearr[count], sb600_spibar + 0x80 + count);
|
||||||
|
}
|
||||||
|
msg_pspew("\n");
|
||||||
|
|
||||||
|
execute_command();
|
||||||
|
|
||||||
|
msg_pspew("Reading buffer: ");
|
||||||
|
for (count = 0; count < readcnt; count++) {
|
||||||
|
readarr[count] = mmio_readb(sb600_spibar + 0x80 + (writecnt + count) % FIFO_SIZE_YANGTZE);
|
||||||
|
msg_pspew("[%02x]", readarr[count]);
|
||||||
|
}
|
||||||
|
msg_pspew("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct spispeed {
|
struct spispeed {
|
||||||
const char *const name;
|
const char *const name;
|
||||||
const uint8_t speed;
|
const uint8_t speed;
|
||||||
@ -286,6 +340,10 @@ static const struct spispeed spispeeds[] = {
|
|||||||
{ "33 MHz", 0x01 },
|
{ "33 MHz", 0x01 },
|
||||||
{ "22 MHz", 0x02 },
|
{ "22 MHz", 0x02 },
|
||||||
{ "16.5 MHz", 0x03 },
|
{ "16.5 MHz", 0x03 },
|
||||||
|
{ "100 MHz", 0x04 },
|
||||||
|
{ "Reserved", 0x05 },
|
||||||
|
{ "Reserved", 0x06 },
|
||||||
|
{ "800 kHz", 0x07 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int set_speed(struct pci_dev *dev, const struct spispeed *spispeed)
|
static int set_speed(struct pci_dev *dev, const struct spispeed *spispeed)
|
||||||
@ -294,7 +352,12 @@ static int set_speed(struct pci_dev *dev, const struct spispeed *spispeed)
|
|||||||
uint8_t speed = spispeed->speed;
|
uint8_t speed = spispeed->speed;
|
||||||
|
|
||||||
msg_pdbg("Setting SPI clock to %s (0x%x).\n", spispeed->name, speed);
|
msg_pdbg("Setting SPI clock to %s (0x%x).\n", spispeed->name, speed);
|
||||||
if (amd_gen != CHIPSET_YANGTZE) {
|
if (amd_gen >= CHIPSET_YANGTZE) {
|
||||||
|
rmmio_writew((speed << 12) | (speed << 8) | (speed << 4) | speed, sb600_spibar + 0x22);
|
||||||
|
uint16_t tmp = mmio_readw(sb600_spibar + 0x22);
|
||||||
|
success = (((tmp >> 12) & 0xf) == speed && ((tmp >> 8) & 0xf) == speed &&
|
||||||
|
((tmp >> 4) & 0xf) == speed && ((tmp >> 0) & 0xf) == speed);
|
||||||
|
} else {
|
||||||
rmmio_writeb((mmio_readb(sb600_spibar + 0xd) & ~(0x3 << 4)) | (speed << 4), sb600_spibar + 0xd);
|
rmmio_writeb((mmio_readb(sb600_spibar + 0xd) & ~(0x3 << 4)) | (speed << 4), sb600_spibar + 0xd);
|
||||||
success = (speed == ((mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3));
|
success = (speed == ((mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3));
|
||||||
}
|
}
|
||||||
@ -306,6 +369,17 @@ static int set_speed(struct pci_dev *dev, const struct spispeed *spispeed)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_mode(struct pci_dev *dev, uint8_t read_mode)
|
||||||
|
{
|
||||||
|
uint32_t tmp = mmio_readl(sb600_spibar + 0x00);
|
||||||
|
tmp &= ~(0x6 << 28 | 0x1 << 18); /* Clear mode bits */
|
||||||
|
tmp |= ((read_mode & 0x6) << 28) | ((read_mode & 0x1) << 18);
|
||||||
|
rmmio_writel(tmp, sb600_spibar + 0x00);
|
||||||
|
if (tmp != mmio_readl(sb600_spibar + 0x00))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int handle_speed(struct pci_dev *dev)
|
static int handle_speed(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
@ -316,7 +390,47 @@ static int handle_speed(struct pci_dev *dev)
|
|||||||
* 18 rsvd <- fastReadEnable ? <- ? SpiReadMode[0]
|
* 18 rsvd <- fastReadEnable ? <- ? SpiReadMode[0]
|
||||||
* 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]
|
* 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]
|
||||||
*/
|
*/
|
||||||
if (amd_gen != CHIPSET_YANGTZE) {
|
if (amd_gen >= CHIPSET_YANGTZE) {
|
||||||
|
tmp = mmio_readb(sb600_spibar + 0x20);
|
||||||
|
msg_pdbg("UseSpi100 is %sabled\n", (tmp & 0x1) ? "en" : "dis");
|
||||||
|
if ((tmp & 0x1) == 0) {
|
||||||
|
rmmio_writeb(tmp | 0x1, sb600_spibar + 0x20);
|
||||||
|
tmp = mmio_readb(sb600_spibar + 0x20) & 0x1;
|
||||||
|
if (tmp == 0) {
|
||||||
|
msg_perr("Enabling Spi100 failed.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
msg_pdbg("Enabling Spi100 succeeded.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *spireadmodes[] = {
|
||||||
|
"Normal (up to 33 MHz)", /* 0 */
|
||||||
|
"Reserved", /* 1 */
|
||||||
|
"Dual IO (1-1-2)", /* 2 */
|
||||||
|
"Quad IO (1-1-4)", /* 3 */
|
||||||
|
"Dual IO (1-2-2)", /* 4 */
|
||||||
|
"Quad IO (1-4-4)", /* 5 */
|
||||||
|
"Normal (up to 66 MHz)", /* 6 */
|
||||||
|
"Fast Read", /* 7 */
|
||||||
|
};
|
||||||
|
tmp = mmio_readl(sb600_spibar + 0x00);
|
||||||
|
uint8_t read_mode = ((tmp >> 28) & 0x6) | ((tmp >> 18) & 0x1);
|
||||||
|
msg_pdbg("SpiReadMode=%s (%i)\n", spireadmodes[read_mode], read_mode);
|
||||||
|
if (read_mode != 6) {
|
||||||
|
read_mode = 6; /* Default to "Normal (up to 66 MHz)" */
|
||||||
|
if (set_mode(dev, read_mode) != 0) {
|
||||||
|
msg_perr("Setting read mode to \"%s\" failed.\n", spireadmodes[read_mode]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
msg_pdbg("Setting read mode to \"%s\" succeeded.\n", spireadmodes[read_mode]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = mmio_readw(sb600_spibar + 0x22); /* SPI 100 Speed Config */
|
||||||
|
msg_pdbg("NormSpeedNew is %s\n", spispeeds[(tmp >> 12) & 0xf].name);
|
||||||
|
msg_pdbg("FastSpeedNew is %s\n", spispeeds[(tmp >> 8) & 0xf].name);
|
||||||
|
msg_pdbg("AltSpeedNew is %s\n", spispeeds[(tmp >> 4) & 0xf].name);
|
||||||
|
msg_pdbg("TpmSpeedNew is %s\n", spispeeds[(tmp >> 0) & 0xf].name);
|
||||||
|
} else {
|
||||||
if (amd_gen >= CHIPSET_SB89XX && amd_gen <= CHIPSET_HUDSON234) {
|
if (amd_gen >= CHIPSET_SB89XX && amd_gen <= CHIPSET_HUDSON234) {
|
||||||
bool fast_read = (mmio_readl(sb600_spibar + 0x00) >> 18) & 0x1;
|
bool fast_read = (mmio_readl(sb600_spibar + 0x00) >> 18) & 0x1;
|
||||||
msg_pdbg("Fast Reads are %sabled\n", fast_read ? "en" : "dis");
|
msg_pdbg("Fast Reads are %sabled\n", fast_read ? "en" : "dis");
|
||||||
@ -412,12 +526,6 @@ int sb600_probe_spi(struct pci_dev *dev)
|
|||||||
return ERROR_NONFATAL;
|
return ERROR_NONFATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amd_gen == CHIPSET_YANGTZE) {
|
|
||||||
msg_perr("SPI on Kabini/Temash and newer chipsets are not yet supported.\n"
|
|
||||||
"Please try a newer version of flashrom.\n");
|
|
||||||
return ERROR_NONFATAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* How to read the following table and similar ones in this file:
|
/* How to read the following table and similar ones in this file:
|
||||||
* "?" means we have no datasheet for this chipset generation or it doesn't have any relevant info.
|
* "?" means we have no datasheet for this chipset generation or it doesn't have any relevant info.
|
||||||
* "<-" means the bit/register meaning is identical to the next non-"?" chipset to the left. "<-" thus
|
* "<-" means the bit/register meaning is identical to the next non-"?" chipset to the left. "<-" thus
|
||||||
@ -439,6 +547,8 @@ int sb600_probe_spi(struct pci_dev *dev)
|
|||||||
msg_pdbg("SpiRomEnable=%i", (tmp >> 1) & 0x1);
|
msg_pdbg("SpiRomEnable=%i", (tmp >> 1) & 0x1);
|
||||||
if (amd_gen == CHIPSET_SB7XX)
|
if (amd_gen == CHIPSET_SB7XX)
|
||||||
msg_pdbg(", AltSpiCSEnable=%i, AbortEnable=%i", tmp & 0x1, (tmp >> 2) & 0x1);
|
msg_pdbg(", AltSpiCSEnable=%i, AbortEnable=%i", tmp & 0x1, (tmp >> 2) & 0x1);
|
||||||
|
else if (amd_gen == CHIPSET_YANGTZE)
|
||||||
|
msg_pdbg(", RouteTpm2Sp=%i", (tmp >> 3) & 0x1);
|
||||||
|
|
||||||
tmp = pci_read_byte(dev, 0xba);
|
tmp = pci_read_byte(dev, 0xba);
|
||||||
msg_pdbg(", PrefetchEnSPIFromIMC=%i", (tmp & 0x4) >> 2);
|
msg_pdbg(", PrefetchEnSPIFromIMC=%i", (tmp & 0x4) >> 2);
|
||||||
@ -473,6 +583,8 @@ int sb600_probe_spi(struct pci_dev *dev)
|
|||||||
*/
|
*/
|
||||||
tmp = mmio_readl(sb600_spibar + 0x00);
|
tmp = mmio_readl(sb600_spibar + 0x00);
|
||||||
msg_pdbg("(0x%08" PRIx32 ") SpiArbEnable=%i", tmp, (tmp >> 19) & 0x1);
|
msg_pdbg("(0x%08" PRIx32 ") SpiArbEnable=%i", tmp, (tmp >> 19) & 0x1);
|
||||||
|
if (amd_gen == CHIPSET_YANGTZE)
|
||||||
|
msg_pdbg(", IllegalAccess=%i", (tmp >> 21) & 0x1);
|
||||||
|
|
||||||
msg_pdbg(", SpiAccessMacRomEn=%i, SpiHostAccessRomEn=%i, ArbWaitCount=%i",
|
msg_pdbg(", SpiAccessMacRomEn=%i, SpiHostAccessRomEn=%i, ArbWaitCount=%i",
|
||||||
(tmp >> 22) & 0x1, (tmp >> 23) & 0x1, (tmp >> 24) & 0x7);
|
(tmp >> 22) & 0x1, (tmp >> 23) & 0x1, (tmp >> 24) & 0x7);
|
||||||
@ -485,6 +597,7 @@ int sb600_probe_spi(struct pci_dev *dev)
|
|||||||
msg_pdbg(", DropOneClkOnRd/SpiClkGate=%i", (tmp >> 28) & 0x1);
|
msg_pdbg(", DropOneClkOnRd/SpiClkGate=%i", (tmp >> 28) & 0x1);
|
||||||
case CHIPSET_SB89XX:
|
case CHIPSET_SB89XX:
|
||||||
case CHIPSET_HUDSON234:
|
case CHIPSET_HUDSON234:
|
||||||
|
case CHIPSET_YANGTZE:
|
||||||
msg_pdbg(", SpiBusy=%i", (tmp >> 31) & 0x1);
|
msg_pdbg(", SpiBusy=%i", (tmp >> 31) & 0x1);
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@ -498,6 +611,7 @@ int sb600_probe_spi(struct pci_dev *dev)
|
|||||||
if (amd_gen >= CHIPSET_SB89XX) {
|
if (amd_gen >= CHIPSET_SB89XX) {
|
||||||
tmp = mmio_readb(sb600_spibar + 0x1D);
|
tmp = mmio_readb(sb600_spibar + 0x1D);
|
||||||
msg_pdbg("Using SPI_CS%d\n", tmp & 0x3);
|
msg_pdbg("Using SPI_CS%d\n", tmp & 0x3);
|
||||||
|
/* FIXME: Handle SpiProtect* configuration on Yangtze. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Look for the SMBus device. */
|
/* Look for the SMBus device. */
|
||||||
@ -545,7 +659,11 @@ int sb600_probe_spi(struct pci_dev *dev)
|
|||||||
if (handle_imc(dev) != 0)
|
if (handle_imc(dev) != 0)
|
||||||
return ERROR_FATAL;
|
return ERROR_FATAL;
|
||||||
|
|
||||||
register_spi_programmer(&spi_programmer_sb600);
|
/* Starting with Yangtze the SPI controller got a different interface with a much bigger buffer. */
|
||||||
|
if (amd_gen != CHIPSET_YANGTZE)
|
||||||
|
register_spi_programmer(&spi_programmer_sb600);
|
||||||
|
else
|
||||||
|
register_spi_programmer(&spi_programmer_yangtze);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user