diff options
-rw-r--r-- | src/southbridge/intel/lynxpoint/pch.c | 80 | ||||
-rw-r--r-- | src/southbridge/intel/lynxpoint/pch.h | 10 |
2 files changed, 65 insertions, 25 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 */ diff --git a/src/southbridge/intel/lynxpoint/pch.h b/src/southbridge/intel/lynxpoint/pch.h index d00ee621f6..3738a13dbd 100644 --- a/src/southbridge/intel/lynxpoint/pch.h +++ b/src/southbridge/intel/lynxpoint/pch.h @@ -355,9 +355,13 @@ int early_spi_read(u32 offset, u32 size, u8 *buffer); #define IOBPIRI 0x2330 #define IOBPD 0x2334 #define IOBPS 0x2338 -#define IOBPS_RW_BX ((1 << 9)|(1 << 10)) -#define IOBPS_WRITE_AX ((1 << 9)|(1 << 10)) -#define IOBPS_READ_AX ((1 << 8)|(1 << 9)|(1 << 10)) +#define IOBPS_READY 0x0001 +#define IOBPS_TX_MASK 0x0006 +#define IOBPS_MASK 0xff00 +#define IOBPS_READ 0x0600 +#define IOBPS_WRITE 0x0700 +#define IOBPU 0x233a +#define IOBPU_MAGIC 0xf000 #define D31IP 0x3100 /* 32bit */ #define D31IP_TTIP 24 /* Thermal Throttle Pin */ |