summaryrefslogtreecommitdiff
path: root/src/southbridge/intel/lynxpoint/pch.c
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@chromium.org>2013-01-10 13:19:23 -0800
committerRonald G. Minnich <rminnich@gmail.com>2013-03-14 05:02:44 +0100
commit7302d1e4cec1149a3da61824497160cea514e2ca (patch)
tree884ca2a1906b6cc41fe260fac5955fb0bf277191 /src/southbridge/intel/lynxpoint/pch.c
parent50a34648cdc7fc55e1fa75d51ece608c0e27245a (diff)
downloadcoreboot-7302d1e4cec1149a3da61824497160cea514e2ca.tar.xz
lynxpoint: Update IOBP programming method
This follows the new method outlined in the LPT BWG. It is also very pedantic about its operation so it is easier to read and compare against the docs and the reference code implementation. Change-Id: I235d634cded0c75ec0e9f53488f5b366107a18fa Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: http://review.coreboot.org/2694 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Diffstat (limited to 'src/southbridge/intel/lynxpoint/pch.c')
-rw-r--r--src/southbridge/intel/lynxpoint/pch.c80
1 files changed, 58 insertions, 22 deletions
diff --git a/src/southbridge/intel/lynxpoint/pch.c b/src/southbridge/intel/lynxpoint/pch.c
index c4a3acf8b6..c2765e91eb 100644
--- a/src/southbridge/intel/lynxpoint/pch.c
+++ b/src/southbridge/intel/lynxpoint/pch.c
@@ -113,56 +113,92 @@ static void pch_hide_devfn(unsigned devfn)
#define IOBP_RETRY 1000
static inline int iobp_poll(void)
{
- unsigned try = IOBP_RETRY;
- u32 data;
+ unsigned try;
- while (try--) {
- data = RCBA32(IOBPS);
- if ((data & 1) == 0)
+ for (try = IOBP_RETRY; try > 0; try--) {
+ u16 status = RCBA16(IOBPS);
+ if ((status & IOBPS_READY) == 0)
return 1;
udelay(10);
}
- printk(BIOS_ERR, "IOBP timeout\n");
+ printk(BIOS_ERR, "IOBP: timeout waiting for transaction to complete\n");
return 0;
}
-void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
+static u32 pch_iobp_read(u32 address)
{
- u32 data;
+ u16 status;
+
+ if (!iobp_poll())
+ return 0;
/* Set the address */
RCBA32(IOBPIRI) = address;
/* READ OPCODE */
- RCBA32(IOBPS) = IOBPS_RW_BX;
- if (!iobp_poll())
- return;
+ status = RCBA16(IOBPS);
+ status &= ~IOBPS_MASK;
+ status |= IOBPS_READ;
+ RCBA16(IOBPS) = status;
+
+ /* Undocumented magic */
+ RCBA16(IOBPU) = IOBPU_MAGIC;
+
+ /* Set ready bit */
+ status = RCBA16(IOBPS);
+ status |= IOBPS_READY;
+ RCBA16(IOBPS) = status;
- /* Read IOBP data */
- data = RCBA32(IOBPD);
if (!iobp_poll())
- return;
+ return 0;
/* Check for successful transaction */
- if ((RCBA32(IOBPS) & 0x6) != 0) {
- printk(BIOS_ERR, "IOBP read 0x%08x failed\n", address);
- return;
+ status = RCBA16(IOBPS);
+ if (status & IOBPS_TX_MASK) {
+ printk(BIOS_ERR, "IOBP: read 0x%08x failed\n", address);
+ return 0;
}
+ /* Read IOBP data */
+ return RCBA32(IOBPD);
+}
+
+void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
+{
+ u16 status;
+ u32 data = pch_iobp_read(address);
+
+ /* WRITE OPCODE */
+ status = RCBA16(IOBPS);
+ status &= ~IOBPS_MASK;
+ status |= IOBPS_WRITE;
+ RCBA16(IOBPS) = status;
+
/* Update the data */
data &= andvalue;
data |= orvalue;
+ RCBA32(IOBPD) = data;
+
+ /* Undocumented magic */
+ RCBA16(IOBPU) = IOBPU_MAGIC;
+
+ /* Set ready bit */
+ status = RCBA16(IOBPS);
+ status |= IOBPS_READY;
+ RCBA16(IOBPS) = status;
- /* WRITE OPCODE */
- RCBA32(IOBPS) = IOBPS_RW_BX;
if (!iobp_poll())
return;
- /* Write IOBP data */
- RCBA32(IOBPD) = data;
- if (!iobp_poll())
+ /* Check for successful transaction */
+ status = RCBA16(IOBPS);
+ if (status & IOBPS_TX_MASK) {
+ printk(BIOS_ERR, "IOBP: write 0x%08x failed\n", address);
return;
+ }
+
+ printk(BIOS_INFO, "IOBP: set 0x%08x to 0x%08x\n", address, data);
}
/* Check if any port in set X to X+3 is enabled */