diff options
Diffstat (limited to 'src/southbridge/intel/lynxpoint/pch.c')
-rw-r--r-- | src/southbridge/intel/lynxpoint/pch.c | 80 |
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 */ |