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>
This commit is contained in:
Duncan Laurie 2013-01-10 13:19:23 -08:00 committed by Ronald G. Minnich
parent 50a34648cd
commit 7302d1e4ce
2 changed files with 67 additions and 27 deletions

View File

@ -113,56 +113,92 @@ static void pch_hide_devfn(unsigned devfn)
#define IOBP_RETRY 1000 #define IOBP_RETRY 1000
static inline int iobp_poll(void) static inline int iobp_poll(void)
{ {
unsigned try = IOBP_RETRY; unsigned try;
u32 data;
while (try--) { for (try = IOBP_RETRY; try > 0; try--) {
data = RCBA32(IOBPS); u16 status = RCBA16(IOBPS);
if ((data & 1) == 0) if ((status & IOBPS_READY) == 0)
return 1; return 1;
udelay(10); udelay(10);
} }
printk(BIOS_ERR, "IOBP timeout\n"); printk(BIOS_ERR, "IOBP: timeout waiting for transaction to complete\n");
return 0; 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 */ /* Set the address */
RCBA32(IOBPIRI) = address; RCBA32(IOBPIRI) = address;
/* READ OPCODE */ /* READ OPCODE */
RCBA32(IOBPS) = IOBPS_RW_BX; status = RCBA16(IOBPS);
if (!iobp_poll()) status &= ~IOBPS_MASK;
return; 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()) if (!iobp_poll())
return; return 0;
/* Check for successful transaction */ /* Check for successful transaction */
if ((RCBA32(IOBPS) & 0x6) != 0) { status = RCBA16(IOBPS);
printk(BIOS_ERR, "IOBP read 0x%08x failed\n", address); if (status & IOBPS_TX_MASK) {
return; 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 */ /* Update the data */
data &= andvalue; data &= andvalue;
data |= orvalue; data |= orvalue;
/* WRITE OPCODE */
RCBA32(IOBPS) = IOBPS_RW_BX;
if (!iobp_poll())
return;
/* Write IOBP data */
RCBA32(IOBPD) = data; RCBA32(IOBPD) = data;
/* Undocumented magic */
RCBA16(IOBPU) = IOBPU_MAGIC;
/* Set ready bit */
status = RCBA16(IOBPS);
status |= IOBPS_READY;
RCBA16(IOBPS) = status;
if (!iobp_poll()) if (!iobp_poll())
return; return;
/* 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 */ /* Check if any port in set X to X+3 is enabled */

View File

@ -355,9 +355,13 @@ int early_spi_read(u32 offset, u32 size, u8 *buffer);
#define IOBPIRI 0x2330 #define IOBPIRI 0x2330
#define IOBPD 0x2334 #define IOBPD 0x2334
#define IOBPS 0x2338 #define IOBPS 0x2338
#define IOBPS_RW_BX ((1 << 9)|(1 << 10)) #define IOBPS_READY 0x0001
#define IOBPS_WRITE_AX ((1 << 9)|(1 << 10)) #define IOBPS_TX_MASK 0x0006
#define IOBPS_READ_AX ((1 << 8)|(1 << 9)|(1 << 10)) #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 0x3100 /* 32bit */
#define D31IP_TTIP 24 /* Thermal Throttle Pin */ #define D31IP_TTIP 24 /* Thermal Throttle Pin */