aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/amd/agesa/s3_resume.c12
-rw-r--r--src/drivers/spi/eon.c1
-rw-r--r--src/drivers/spi/gigadevice.c1
-rw-r--r--src/drivers/spi/macronix.c1
-rw-r--r--src/drivers/spi/spansion.c1
-rw-r--r--src/drivers/spi/spi_flash.c3
-rw-r--r--src/drivers/spi/sst.c1
-rw-r--r--src/drivers/spi/stmicro.c1
-rw-r--r--src/drivers/spi/winbond.c1
-rw-r--r--src/include/spi.h6
-rw-r--r--src/southbridge/amd/agesa/hudson/spi.c25
-rw-r--r--src/southbridge/amd/cimx/sb800/spi.c57
12 files changed, 109 insertions, 1 deletions
diff --git a/src/cpu/amd/agesa/s3_resume.c b/src/cpu/amd/agesa/s3_resume.c
index 6302c3d304..42e950f26b 100644
--- a/src/cpu/amd/agesa/s3_resume.c
+++ b/src/cpu/amd/agesa/s3_resume.c
@@ -165,6 +165,9 @@ void OemAgesaSaveMtrr(void)
return;
}
+ flash->spi->rw = SPI_WRITE_FLAG;
+ spi_claim_bus(flash->spi);
+
/* Enable access to AMD RdDram and WrDram extension bits */
msr_data = rdmsr(SYS_CFG);
msr_data.lo |= SYSCFG_MSR_MtrrFixDramModEn;
@@ -233,6 +236,9 @@ void OemAgesaSaveMtrr(void)
flash->write(flash, nvram_pos, 4, &msr_data.hi);
nvram_pos += 4;
+ flash->spi->rw = SPI_WRITE_FLAG;
+ spi_release_bus(flash->spi);
+
#endif
}
@@ -273,6 +279,9 @@ u32 OemAgesaSaveS3Info(S3_DATA_TYPE S3DataType, u32 DataSize, void *Data)
return AGESA_SUCCESS;
}
+ flash->spi->rw = SPI_WRITE_FLAG;
+ spi_claim_bus(flash->spi);
+
if (S3DataType == S3DataTypeNonVolatile) {
flash->erase(flash, S3_DATA_NONVOLATILE_POS, 0x1000);
} else {
@@ -287,6 +296,9 @@ u32 OemAgesaSaveS3Info(S3_DATA_TYPE S3DataType, u32 DataSize, void *Data)
flash->write(flash, nvram_pos + pos + 4, sizeof(u32), (u32 *)(Data + nvram_pos));
}
+ flash->spi->rw = SPI_WRITE_FLAG;
+ spi_release_bus(flash->spi);
+
return AGESA_SUCCESS;
}
#endif
diff --git a/src/drivers/spi/eon.c b/src/drivers/spi/eon.c
index 2215a74d8a..21103ae221 100644
--- a/src/drivers/spi/eon.c
+++ b/src/drivers/spi/eon.c
@@ -70,6 +70,7 @@ static int eon_write(struct spi_flash *flash,
page_addr = offset / page_size;
byte_addr = offset % page_size;
+ flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
diff --git a/src/drivers/spi/gigadevice.c b/src/drivers/spi/gigadevice.c
index ece6978c2b..5a8f82f053 100644
--- a/src/drivers/spi/gigadevice.c
+++ b/src/drivers/spi/gigadevice.c
@@ -131,6 +131,7 @@ static int gigadevice_write(struct spi_flash *flash, u32 offset,
page_size = min(1 << stm->params->l2_page_size, CONTROLLER_PAGE_LIMIT);
byte_addr = offset % page_size;
+ flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_WARNING,
diff --git a/src/drivers/spi/macronix.c b/src/drivers/spi/macronix.c
index 0a0d62bdac..910b874cd4 100644
--- a/src/drivers/spi/macronix.c
+++ b/src/drivers/spi/macronix.c
@@ -134,6 +134,7 @@ static int macronix_write(struct spi_flash *flash,
page_size = min(mcx->params->page_size, CONTROLLER_PAGE_LIMIT);
byte_addr = offset % page_size;
+ flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
diff --git a/src/drivers/spi/spansion.c b/src/drivers/spi/spansion.c
index 328892ccb1..37bf5a859c 100644
--- a/src/drivers/spi/spansion.c
+++ b/src/drivers/spi/spansion.c
@@ -147,6 +147,7 @@ static int spansion_write(struct spi_flash *flash,
page_addr = offset / page_size;
byte_addr = offset % page_size;
+ flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c
index 75a5c21619..6b658f894d 100644
--- a/src/drivers/spi/spi_flash.c
+++ b/src/drivers/spi/spi_flash.c
@@ -69,6 +69,7 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
struct spi_slave *spi = flash->spi;
int ret;
+ spi->rw = SPI_READ_FLAG;
spi_claim_bus(spi);
ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
spi_release_bus(spi);
@@ -148,6 +149,7 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd,
return -1;
}
+ flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
@@ -258,6 +260,7 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
return NULL;
}
+ spi->rw = SPI_READ_FLAG;
ret = spi_claim_bus(spi);
if (ret) {
printk(BIOS_WARNING, "SF: Failed to claim SPI bus: %d\n", ret);
diff --git a/src/drivers/spi/sst.c b/src/drivers/spi/sst.c
index 2609591723..8cf3f964fd 100644
--- a/src/drivers/spi/sst.c
+++ b/src/drivers/spi/sst.c
@@ -153,6 +153,7 @@ sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
int ret;
u8 cmd[4];
+ flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
diff --git a/src/drivers/spi/stmicro.c b/src/drivers/spi/stmicro.c
index d10429b2c4..b741d30feb 100644
--- a/src/drivers/spi/stmicro.c
+++ b/src/drivers/spi/stmicro.c
@@ -148,6 +148,7 @@ static int stmicro_write(struct spi_flash *flash,
page_addr = offset / page_size;
byte_addr = offset % page_size;
+ flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
diff --git a/src/drivers/spi/winbond.c b/src/drivers/spi/winbond.c
index 28786756ae..c44afea832 100644
--- a/src/drivers/spi/winbond.c
+++ b/src/drivers/spi/winbond.c
@@ -117,6 +117,7 @@ static int winbond_write(struct spi_flash *flash,
page_size = min(1 << stm->params->l2_page_size, CONTROLLER_PAGE_LIMIT);
byte_addr = offset % page_size;
+ flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
diff --git a/src/include/spi.h b/src/include/spi.h
index 5fbe51e1ab..d394531712 100644
--- a/src/include/spi.h
+++ b/src/include/spi.h
@@ -48,6 +48,9 @@
#define SPI_OPCODE_WREN 0x06
#define SPI_OPCODE_FAST_READ 0x0b
+#define SPI_READ_FLAG 0x01
+#define SPI_WRITE_FLAG 0x02
+
/*-----------------------------------------------------------------------
* Representation of a SPI slave, i.e. what we're communicating with.
*
@@ -55,16 +58,17 @@
*
* bus: ID of the bus that the slave is attached to.
* cs: ID of the chip select connected to the slave.
+ * rw: Read or Write flag
*/
struct spi_slave {
unsigned int bus;
unsigned int cs;
+ unsigned int rw;
};
/*-----------------------------------------------------------------------
* Initialization, must be called once on start up.
*
- * TODO: I don't think we really need this.
*/
void spi_init(void);
diff --git a/src/southbridge/amd/agesa/hudson/spi.c b/src/southbridge/amd/agesa/hudson/spi.c
index 3b54490117..aebe4b5cec 100644
--- a/src/southbridge/amd/agesa/hudson/spi.c
+++ b/src/southbridge/amd/agesa/hudson/spi.c
@@ -25,6 +25,12 @@
#include <device/pci.h>
#include <device/pci_ops.h>
+#if defined (CONFIG_HUDSON_IMC_FWM)
+#include "FchPlatform.h"
+
+static int bus_claimed = 0;
+#endif
+
static u32 spibar;
static void reset_internal_fifo_pointer(void)
@@ -92,11 +98,30 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
}
int spi_claim_bus(struct spi_slave *slave)
{
+#if defined (CONFIG_HUDSON_IMC_FWM)
+
+ if (slave->rw == SPI_WRITE_FLAG) {
+ bus_claimed++;
+ if (bus_claimed == 1)
+ ImcSleep(NULL);
+ }
+#endif
+
return 0;
}
void spi_release_bus(struct spi_slave *slave)
{
+#if defined (CONFIG_HUDSON_IMC_FWM)
+
+ if (slave->rw == SPI_WRITE_FLAG) {
+ bus_claimed--;
+ if (bus_claimed <= 0) {
+ bus_claimed = 0;
+ ImcWakeup(NULL);
+ }
+ }
+#endif
}
void spi_cs_activate(struct spi_slave *slave)
diff --git a/src/southbridge/amd/cimx/sb800/spi.c b/src/southbridge/amd/cimx/sb800/spi.c
index 3b54490117..46cc7419ba 100644
--- a/src/southbridge/amd/cimx/sb800/spi.c
+++ b/src/southbridge/amd/cimx/sb800/spi.c
@@ -25,6 +25,13 @@
#include <device/pci.h>
#include <device/pci_ops.h>
+#if defined (CONFIG_SB800_IMC_FWM)
+#include "SBPLATFORM.h"
+#include <vendorcode/amd/cimx/sb800/ECfan.h>
+
+static int bus_claimed = 0;
+#endif
+
static u32 spibar;
static void reset_internal_fifo_pointer(void)
@@ -90,13 +97,63 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
return 0;
}
+
+#if defined (CONFIG_SB800_IMC_FWM)
+
+static void ImcSleep(void)
+{
+ u8 cmd_val = 0x96; /* Kick off IMC Mailbox command 96 */
+ u8 reg0_val = 0; /* clear response register */
+ u8 reg1_val = 0xB4; /* request ownership flag */
+
+ WriteECmsg (MSG_REG0, AccWidthUint8, &reg0_val);
+ WriteECmsg (MSG_REG1, AccWidthUint8, &reg1_val);
+ WriteECmsg (MSG_SYS_TO_IMC, AccWidthUint8, &cmd_val);
+
+ WaitForEcLDN9MailboxCmdAck();
+}
+
+
+static void ImcWakeup(void)
+{
+ u8 cmd_val = 0x96; /* Kick off IMC Mailbox command 96 */
+ u8 reg0_val = 0;; /* clear response register */
+ u8 reg1_val = 0xB5; /* release ownership flag */
+
+ WriteECmsg (MSG_REG0, AccWidthUint8, &reg0_val);
+ WriteECmsg (MSG_REG1, AccWidthUint8, &reg1_val);
+ WriteECmsg (MSG_SYS_TO_IMC, AccWidthUint8, &cmd_val);
+
+ WaitForEcLDN9MailboxCmdAck();
+}
+#endif
+
int spi_claim_bus(struct spi_slave *slave)
{
+#if defined (CONFIG_SB800_IMC_FWM)
+
+ if (slave->rw == SPI_WRITE_FLAG) {
+ bus_claimed++;
+ if (bus_claimed == 1)
+ ImcSleep();
+ }
+#endif
+
return 0;
}
void spi_release_bus(struct spi_slave *slave)
{
+#if defined (CONFIG_SB800_IMC_FWM)
+
+ if (slave->rw == SPI_WRITE_FLAG) {
+ bus_claimed--;
+ if (bus_claimed <= 0) {
+ bus_claimed = 0;
+ ImcWakeup();
+ }
+ }
+#endif
}
void spi_cs_activate(struct spi_slave *slave)