soc/amd/stoneyridge: Replace magic registers

Replace southbridge registers and register values from magic numbers to
literals, provided these registers are currently defined publicly or in
NDA datasheet.

Registers available only internally to AMD are left unchanged.

BUG=b:62199625

Change-Id: I9187ba1c41ebb1201ddc177e8184672c60cd5f5d
Signed-off-by: Richard Spiegel <richard.spiegel@silverbackltd.com>
Reviewed-on: https://review.coreboot.org/21767
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Richard Spiegel 2017-09-29 10:05:35 -07:00 committed by Martin Roth
parent 782b9a7b75
commit c5ecd3e14d
5 changed files with 272 additions and 148 deletions

View File

@ -76,9 +76,9 @@ void sb_pci_port80(void)
dev = PCI_DEV(0, PCU_DEV, LPC_FUNC);
byte = pci_read_config8(dev, 0x4a);
byte &= ~(1 << 5); /* disable lpc port 80 */
pci_write_config8(dev, 0x4a, byte);
byte = pci_read_config8(dev, LPC_IO_OR_MEM_DEC_EN_HIGH);
byte &= ~DECODE_IO_PORT_ENABLE4_H; /* disable lpc port 80 */
pci_write_config8(dev, LPC_IO_OR_MEM_DEC_EN_HIGH, byte);
}
void sb_lpc_port80(void)
@ -87,17 +87,17 @@ void sb_lpc_port80(void)
pci_devfn_t dev;
/* Enable LPC controller */
outb(0xec, PM_INDEX);
outb(PM_LPC_GATING, PM_INDEX);
byte = inb(PM_DATA);
byte |= 1;
outb(0xec, PM_INDEX);
byte |= PM_LPC_ENABLE;
outb(PM_LPC_GATING, PM_INDEX);
outb(byte, PM_DATA);
/* Enable port 80 LPC decode in pci function 3 configuration space. */
dev = PCI_DEV(0, PCU_DEV, LPC_FUNC);
byte = pci_read_config8(dev, 0x4a);
byte |= 1 << 5; /* enable port 80 */
pci_write_config8(dev, 0x4a, byte);
byte = pci_read_config8(dev, LPC_IO_OR_MEM_DEC_EN_HIGH);
byte |= DECODE_IO_PORT_ENABLE4_H; /* enable port 80 */
pci_write_config8(dev, LPC_IO_OR_MEM_DEC_EN_HIGH, byte);
}
void sb_lpc_decode(void)
@ -252,7 +252,7 @@ void sb_clk_output_48Mhz(void)
ctrl = read32((void *)(ACPI_MMIO_BASE + MISC_BASE + FCH_MISC_REG40));
/* clear the OSCOUT1_ClkOutputEnb to enable the 48 Mhz clock */
ctrl &= ~(1<<2);
ctrl &= ~FCH_MISC_REG40_OSCOUT1_EN;
write32((void *)(ACPI_MMIO_BASE + MISC_BASE + FCH_MISC_REG40), ctrl);
}
@ -336,29 +336,37 @@ void sb_enable_rom(void)
dev = PCI_DEV(0, PCU_DEV, LPC_FUNC);
/* Decode variable LPC ROM address ranges 1 and 2. */
reg8 = pci_io_read_config8(dev, 0x48);
reg8 |= (1 << 3) | (1 << 4);
pci_io_write_config8(dev, 0x48, reg8);
/* LPC ROM address range 1: */
/* Enable LPC ROM range mirroring start at 0x000e(0000). */
pci_io_write_config16(dev, 0x68, 0x000e);
/* Enable LPC ROM range mirroring end at 0x000f(ffff). */
pci_io_write_config16(dev, 0x6a, 0x000f);
/* LPC ROM address range 2: */
/*
* Decode variable LPC ROM address ranges 1 and 2.
* Bits 3-4 are not defined in any publicly available datasheet
*/
reg8 = pci_io_read_config8(dev, LPC_IO_OR_MEM_DECODE_ENABLE);
reg8 |= (1 << 3) | (1 << 4);
pci_io_write_config8(dev, LPC_IO_OR_MEM_DECODE_ENABLE, reg8);
/*
* LPC ROM address range 1:
* Enable LPC ROM range mirroring start at 0x000e(0000).
*/
pci_io_write_config16(dev, ROM_ADDRESS_RANGE1_START, 0x000e);
/* Enable LPC ROM range mirroring end at 0x000f(ffff). */
pci_io_write_config16(dev, ROM_ADDRESS_RANGE1_END, 0x000f);
/*
* LPC ROM address range 2:
*
* Enable LPC ROM range start at:
* 0xfff8(0000): 512KB
* 0xfff0(0000): 1MB
* 0xffe0(0000): 2MB
* 0xffc0(0000): 4MB
*/
pci_io_write_config16(dev, 0x6c, 0x10000
pci_io_write_config16(dev, ROM_ADDRESS_RANGE2_START, 0x10000
- (CONFIG_COREBOOT_ROMSIZE_KB >> 6));
/* Enable LPC ROM range end at 0xffff(ffff). */
pci_io_write_config16(dev, 0x6e, 0xffff);
pci_io_write_config16(dev, ROM_ADDRESS_RANGE2_END, 0xffff);
}
void bootblock_fch_early_init(void)

View File

@ -19,8 +19,35 @@
#include <stdint.h>
#define SMBHSTSTAT 0x0
#define SMBHST_STAT_FAILED 0x10
#define SMBHST_STAT_COLLISION 0x08
#define SMBHST_STAT_ERROR 0x04
#define SMBHST_STAT_INTERRUPT 0x02
#define SMBHST_STAT_BUSY 0x01
#define SMBHST_STAT_CLEAR 0xff
#define SMBHST_STAT_NOERROR 0x02
#define SMBSLVSTAT 0x1
#define SMBSLV_STAT_ALERT 0x20
#define SMBSLV_STAT_SHADOW2 0x10
#define SMBSLV_STAT_SHADOW1 0x08
#define SMBSLV_STAT_SLV_STS 0x04
#define SMBSLV_STAT_SLV_INIT 0x02
#define SMBSLV_STAT_SLV_BUSY 0x01
#define SMBSLV_STAT_CLEAR 0x1f
#define SMBHSTCTRL 0x2
#define SMBHST_CTRL_RST 0x80
#define SMBHST_CTRL_STRT 0x40
#define SMBHST_CTRL_QCK_RW 0x00
#define SMBHST_CTRL_BTE_RW 0x04
#define SMBHST_CTRL_BDT_RW 0x08
#define SMBHST_CTRL_WDT_RW 0x0c
#define SMBHST_CTRL_BLK_RW 0x14
#define SMBHST_CTRL_MODE_BITS 0x1c
#define SMBHST_CTRL_KILL 0x02
#define SMBHST_CTRL_IEN 0x01
#define SMBHSTCMD 0x3
#define SMBHSTADDR 0x4
#define SMBHSTDAT0 0x5
@ -30,6 +57,9 @@
#define SMBSLVCMD_SHADOW 0x9
#define SMBSLVEVT 0xa
#define SMBSLVDAT 0xc
#define SMBTIMING 0xe
#define SMB_BASE_ADDR 0xb00
#define AX_INDXC 0
#define AX_INDXP 2
@ -41,7 +71,8 @@
#define AB_INDX 0xcd8
#define AB_DATA (AB_INDX+4)
/* Between 1-10 seconds, We should never timeout normally
/*
* Between 1-10 seconds, We should never timeout normally
* Longer than this is just painful when a timeout condition occurs.
*/
#define SMBUS_TIMEOUT (100 * 1000 * 10)

View File

@ -28,6 +28,11 @@
/* Offsets from ACPI_MMIO_BASE */
#define APU_SMI_BASE 0xfed80200
/*
* Offsets from ACPI_MMIO_BASE
* This is defined by AGESA, but we don't include AGESA headers to avoid
* polluting the namespace.
*/
#define PM_MMIO_BASE 0xfed80300
#define APU_UART0_BASE 0xfedc6000
@ -46,6 +51,17 @@
#define FORCE_STPCLK_RETRY BIT(24)
#define PM_ACPI_MMIO_EN 0x24
#define PM_SERIRQ_CONF 0x54
#define PM_SERIRQ_NUM_BITS_17 0x0000
#define PM_SERIRQ_NUM_BITS_18 0x0004
#define PM_SERIRQ_NUM_BITS_19 0x0008
#define PM_SERIRQ_NUM_BITS_20 0x000c
#define PM_SERIRQ_NUM_BITS_21 0x0010
#define PM_SERIRQ_NUM_BITS_22 0x0014
#define PM_SERIRQ_NUM_BITS_23 0x0018
#define PM_SERIRQ_NUM_BITS_24 0x001c
#define PM_SERIRQ_MODE BIT(6)
#define PM_SERIRQ_ENABLE BIT(7)
#define PM_EVT_BLK 0x60
#define PM1_CNT_BLK 0x62
#define PM_TMR_BLK 0x64
@ -60,6 +76,10 @@
#define PM_HUD_SD_FLASH_CTRL 0xe7
#define PM_YANG_SD_FLASH_CTRL 0xe8
#define PM_PCIB_CFG 0xea
#define PM_LPC_GATING 0xec
#define PM_LPC_AB_NO_BYPASS_EN BIT(2)
#define PM_LPC_A20_EN BIT(1)
#define PM_LPC_ENABLE BIT(0)
#define SYS_RESET 0xcf9
@ -70,14 +90,27 @@
#define ACPI_GPE0_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x10) /* 8 bytes */
#define ACPI_CPU_CONTROL (STONEYRIDGE_ACPI_IO_BASE + 0x08) /* 6 bytes */
#define ACPI_SMI_CTL_PORT 0xb2
#define ACPI_SMI_CMD_CST_CONTROL 0xde
#define ACPI_SMI_CMD_PST_CONTROL 0xad
#define ACPI_SMI_CMD_DISABLE 0xbe
#define ACPI_SMI_CMD_ENABLE 0xef
#define ACPI_SMI_CMD_S4_REQ 0xc0
#define REV_STONEYRIDGE_A11 0x11
#define REV_STONEYRIDGE_A12 0x12
#define SPIROM_BASE_ADDRESS_REGISTER 0xa0
#define ROUTE_TPM_2_SPI BIT(3)
#define SPI_ROM_ENABLE 0x02
#define SPI_ABORT_ENABLE BIT(2)
#define SPI_ROM_ENABLE BIT(1)
#define SPI_ROM_ALT_ENABLE BIT(0)
#define SPI_PRESERVE_BITS (BIT(0) | BIT(1) | BIT(2) | BIT(3))
#define SPI_BASE_ADDRESS 0xfec10000
#define LPC_PCI_CONTROL 0x40
#define LEGACY_DMA_EN BIT(2)
#define LPC_IO_PORT_DECODE_ENABLE 0x44
#define DECODE_ENABLE_PARALLEL_PORT0 BIT(0)
#define DECODE_ENABLE_PARALLEL_PORT1 BIT(1)
@ -115,17 +148,58 @@
#define LPC_IO_OR_MEM_DECODE_ENABLE 0x48
#define LPC_WIDEIO2_ENABLE BIT(25)
#define LPC_WIDEIO1_ENABLE BIT(24)
#define DECODE_IO_PORT_ENABLE6 BIT(23)
#define DECODE_IO_PORT_ENABLE5 BIT(22)
#define DECODE_IO_PORT_ENABLE4 BIT(21)
#define DECODE_IO_PORT_ENABLE3 BIT(19)
#define DECODE_IO_PORT_ENABLE2 BIT(18)
#define DECODE_IO_PORT_ENABLE1 BIT(17)
#define DECODE_IO_PORT_ENABLE0 BIT(16)
#define LPC_SYNC_TIMEOUT_COUNT_ENABLE BIT(7)
#define LPC_WIDEIO0_ENABLE BIT(2)
/* Assuming word access to higher word (register 0x4a) */
#define LPC_IO_OR_MEM_DEC_EN_HIGH 0x4a
#define LPC_WIDEIO2_ENABLE_H BIT(9)
#define LPC_WIDEIO1_ENABLE_H BIT(8)
#define DECODE_IO_PORT_ENABLE6_H BIT(7)
#define DECODE_IO_PORT_ENABLE5_H BIT(6)
#define DECODE_IO_PORT_ENABLE4_H BIT(5)
#define DECODE_IO_PORT_ENABLE3_H BIT(3)
#define DECODE_IO_PORT_ENABLE2_H BIT(2)
#define DECODE_IO_PORT_ENABLE1_H BIT(1)
#define DECODE_IO_PORT_ENABLE0_H BIT(0)
/*
* Register 0x64 is 32-bit, composed by two 16-bit sub-registers.
* For ease of access, each sub-register is declared separetely.
*/
#define LPC_WIDEIO_GENERIC_PORT 0x64
#define LPC_WIDEIO1_GENERIC_PORT 0x66
#define ROM_ADDRESS_RANGE1_START 0x68
#define ROM_ADDRESS_RANGE1_END 0x6a
#define ROM_ADDRESS_RANGE2_START 0x6c
#define ROM_ADDRESS_RANGE2_END 0x6e
#define LPC_ALT_WIDEIO_RANGE_ENABLE 0x74
#define LPC_ALT_WIDEIO2_ENABLE BIT(3)
#define LPC_ALT_WIDEIO1_ENABLE BIT(2)
#define LPC_ALT_WIDEIO0_ENABLE BIT(0)
#define LPC_MISC_CONTROL_BITS 0x78
#define LPC_NOHOG BIT(0)
#define LPC_WIDEIO2_GENERIC_PORT 0x90
/*
* LPC register 0xb8 is DWORD, here there are definitions for byte
* access. For example, bits 31-24 are accessed through byte access
* at register 0xbb ().
*/
#define LPC_ROM_DMA_EC_HOST_CONTROL 0xb8
#define LPC_HOST_CONTROL 0xbb
#define SPI_FROM_HOST_PREFETCH_EN BIT(0)
#define SPI_CNTRL0 0x00
#define SPI_READ_MODE_MASK (BIT(30) | BIT(29) | BIT(18))
/* Nominal is 16.7MHz on older devices, 33MHz on newer */
@ -162,6 +236,10 @@
#define SPI100_HOST_PREF_CONFIG 0x2c
#define SPI_RD4DW_EN_HOST BIT(15)
#define FCH_MISC_REG40_OSCOUT1_EN BIT(2)
#define FLASH_BASE_ADDR ((0xffffffff - CONFIG_ROM_SIZE) + 1)
static inline int sb_sata_enable(void)
{
/* True if IDE or AHCI. */

View File

@ -40,7 +40,10 @@ static void lpc_init(device_t dev)
u32 dword;
device_t sm_dev;
/* Enable the LPC Controller */
/*
* Enable the LPC Controller
* SMBus register 0x64 is not defined in public datasheet.
*/
sm_dev = dev_find_slot(0, PCI_DEVFN(SMBUS_DEV, SMBUS_FUNC));
dword = pci_read_config32(sm_dev, 0x64);
dword |= 1 << 20;
@ -50,37 +53,40 @@ static void lpc_init(device_t dev)
isa_dma_init();
/* Enable DMA transaction on the LPC bus */
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 2);
pci_write_config8(dev, 0x40, byte);
byte = pci_read_config8(dev, LPC_PCI_CONTROL);
byte |= LEGACY_DMA_EN;
pci_write_config8(dev, LPC_PCI_CONTROL, byte);
/* Disable the timeout mechanism on LPC */
byte = pci_read_config8(dev, 0x48);
byte &= ~(1 << 7);
pci_write_config8(dev, 0x48, byte);
byte = pci_read_config8(dev, LPC_IO_OR_MEM_DECODE_ENABLE);
byte &= ~LPC_SYNC_TIMEOUT_COUNT_ENABLE;
pci_write_config8(dev, LPC_IO_OR_MEM_DECODE_ENABLE, byte);
/* Disable LPC MSI Capability */
byte = pci_read_config8(dev, 0x78);
byte = pci_read_config8(dev, LPC_MISC_CONTROL_BITS);
/* BIT 1 is not defined in public datasheet. */
byte &= ~(1 << 1);
/* Keep the old way. i.e., when bus master/DMA cycle is going
/*
* Keep the old way. i.e., when bus master/DMA cycle is going
* on on LPC, it holds PCI grant, so no LPC slave cycle can
* interrupt and visit LPC.
*/
byte &= ~(1 << 0);
pci_write_config8(dev, 0x78, byte);
byte &= ~LPC_NOHOG;
pci_write_config8(dev, LPC_MISC_CONTROL_BITS, byte);
/* bit0: Enable prefetch a cacheline (64 bytes) when Host reads
* code from SPI ROM
/*
* bit3: Fix SPI_CS# timing issue when running at 66M. TODO:A12.
* todo: verify both these against BKDG
* todo: verify against BKDG
*/
byte = pci_read_config8(dev, 0xbb);
byte |= 1 << 0 | 1 << 3;
pci_write_config8(dev, 0xbb, byte);
byte = pci_read_config8(dev, LPC_HOST_CONTROL);
byte |= SPI_FROM_HOST_PREFETCH_EN | 1 << 3;
pci_write_config8(dev, LPC_HOST_CONTROL, byte);
cmos_check_update_date();
/* Initialize the real time clock.
/*
* Initialize the real time clock.
* The 0 argument tells cmos_init not to
* update CMOS unless it is invalid.
* 1 tells cmos_init to always initialize the CMOS.
@ -94,9 +100,9 @@ static void lpc_init(device_t dev)
setup_i8254();
/* Set up SERIRQ, enable continuous mode */
byte = (BIT(4) | BIT(7));
byte = (PM_SERIRQ_NUM_BITS_21 | PM_SERIRQ_ENABLE);
if (!IS_ENABLED(CONFIG_SERIRQ_CONTINUOUS_MODE))
byte |= BIT(6);
byte |= PM_SERIRQ_MODE;
pm_write8(PM_SERIRQ_CONF, byte);
}
@ -117,8 +123,8 @@ static void lpc_read_resources(device_t dev)
IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
res->base = 0xff800000;
res->size = 0x00800000; /* 8 MB for flash */
res->base = FLASH_BASE_ADDR;
res->size = CONFIG_ROM_SIZE;
res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
@ -145,7 +151,7 @@ static void lpc_set_resources(struct device *dev)
/* Special case. The SpiRomEnable and other enables should STAY set. */
res = find_resource(dev, 2);
spi_enable_bits = pci_read_config32(dev, SPIROM_BASE_ADDRESS_REGISTER);
spi_enable_bits &= 0xf;
spi_enable_bits &= SPI_PRESERVE_BITS;
pci_write_config32(dev, SPIROM_BASE_ADDRESS_REGISTER,
res->base | spi_enable_bits);
@ -171,71 +177,72 @@ static void set_lpc_resource(device_t child,
continue;
base = res->base;
end = resource_end(res);
/* find a resource size */
printk(BIOS_DEBUG,
"Southbridge LPC decode:%s, base=0x%08x, end=0x%08x\n",
dev_path(child), base, end);
/* find a resource size */
switch (base) {
case 0x60: /* KB */
case 0x64: /* MS */
set |= (1 << 29);
set |= DECODE_ENABLE_KBC_PORT;
rsize = 1;
break;
case 0x3f8: /* COM1 */
set |= (1 << 6);
set |= DECODE_ENABLE_SERIAL_PORT0;
rsize = 8;
break;
case 0x2f8: /* COM2 */
set |= (1 << 7);
set |= DECODE_ENABLE_SERIAL_PORT1;
rsize = 8;
break;
case 0x378: /* Parallel 1 */
set |= (1 << 0);
set |= (1 << 1); /* + 0x778 for ECP */
set |= DECODE_ENABLE_PARALLEL_PORT0;
/* enable 0x778 for ECP mode */
set |= DECODE_ENABLE_PARALLEL_PORT1;
rsize = 8;
break;
case 0x3f0: /* FD0 */
set |= (1 << 26);
set |= DECODE_ENABLE_FDC_PORT0;
rsize = 8;
break;
case 0x220: /* 0x220 - 0x227 */
set |= (1 << 8);
set |= DECODE_ENABLE_SERIAL_PORT2;
rsize = 8;
break;
case 0x228: /* 0x228 - 0x22f */
set |= (1 << 9);
set |= DECODE_ENABLE_SERIAL_PORT3;
rsize = 8;
break;
case 0x238: /* 0x238 - 0x23f */
set |= (1 << 10);
set |= DECODE_ENABLE_SERIAL_PORT4;
rsize = 8;
break;
case 0x300: /* 0x300 - 0x301 */
set |= (1 << 18);
set |= DECODE_ENABLE_MIDI_PORT0;
rsize = 2;
break;
case 0x400:
set_x |= (1 << 16);
set_x |= DECODE_IO_PORT_ENABLE0;
rsize = 0x40;
break;
case 0x480:
set_x |= (1 << 17);
set_x |= DECODE_IO_PORT_ENABLE1;
rsize = 0x40;
break;
case 0x500:
set_x |= (1 << 18);
set_x |= DECODE_IO_PORT_ENABLE2;
rsize = 0x40;
break;
case 0x580:
set_x |= (1 << 19);
set_x |= DECODE_IO_PORT_ENABLE3;
rsize = 0x40;
break;
case 0x4700:
set_x |= (1 << 22);
set_x |= DECODE_IO_PORT_ENABLE5;
rsize = 0xc;
break;
case 0xfd60:
set_x |= (1 << 23);
set_x |= DECODE_IO_PORT_ENABLE6;
rsize = 16;
break;
default:
@ -250,30 +257,30 @@ static void set_lpc_resource(device_t child,
*reg |= set;
*reg_x |= set_x;
/* check if we can fit resource in variable range */
} else if ((var_num < 3) && ((res->size <= 16) ||
(res->size == 512))) {
} else if ((var_num < 3) &&
((res->size <= 16) || (res->size == 512))) {
/* use variable ranges if pre-defined do not match */
switch (var_num) {
case 0:
*reg_x |= (1 << 2);
*reg_x |= LPC_WIDEIO0_ENABLE;
if (res->size <= 16)
*wiosize |= (1 << 0);
*wiosize |= LPC_ALT_WIDEIO0_ENABLE;
break;
case 1:
*reg_x |= (1 << 24);
*reg_x |= LPC_WIDEIO1_ENABLE;
if (res->size <= 16)
*wiosize |= (1 << 2);
*wiosize |= LPC_ALT_WIDEIO1_ENABLE;
break;
case 2:
*reg_x |= (1 << 25);
*reg_x |= LPC_WIDEIO2_ENABLE;
if (res->size <= 16)
*wiosize |= (1 << 3);
*wiosize |= LPC_ALT_WIDEIO2_ENABLE;
break;
}
reg_var[var_num++] =
base & 0xffff;
reg_var[var_num++] = base & 0xffff;
} else {
printk(BIOS_ERR, "cannot fit LPC decode region:");
printk(BIOS_ERR,
"cannot fit LPC decode region:");
printk(BIOS_ERR, "%s, base = 0x%08x, end = 0x%08x\n",
dev_path(child), base, end);
}
@ -294,9 +301,10 @@ static void lpc_enable_childrens_resources(device_t dev)
int var_num = 0;
u16 reg_var[3];
u16 reg_size[1] = {512};
u8 wiosize = pci_read_config8(dev, 0x74);
u8 wiosize = pci_read_config8(dev, LPC_ALT_WIDEIO_RANGE_ENABLE);
/* Be a bit relaxed, tolerate that LPC region might be bigger than
/*
* Be a bit relaxed, tolerate that LPC region might be bigger than
* resource we try to fit, do it like this for all regions < 16 bytes.
* If there is a resource > 16 bytes it must be 512 bytes to be able
* to allocate the fresh LPC window.
@ -306,26 +314,26 @@ static void lpc_enable_childrens_resources(device_t dev)
* The code tries to check if resource can fit into this region.
*/
reg = pci_read_config32(dev, 0x44);
reg_x = pci_read_config32(dev, 0x48);
reg = pci_read_config32(dev, LPC_IO_PORT_DECODE_ENABLE);
reg_x = pci_read_config32(dev, LPC_IO_OR_MEM_DECODE_ENABLE);
/* check if ranges are free and don't use them if already taken */
if (reg_x & (1 << 2))
if (reg_x & LPC_WIDEIO0_ENABLE)
var_num = 1;
/* just in case check if someone did not manually set other ranges */
if (reg_x & (1 << 24))
if (reg_x & LPC_WIDEIO1_ENABLE)
var_num = 2;
if (reg_x & (1 << 25))
if (reg_x & LPC_WIDEIO2_ENABLE)
var_num = 3;
/* check AGESA region size */
if (wiosize & (1 << 0))
if (wiosize & LPC_ALT_WIDEIO0_ENABLE)
reg_size[0] = 16;
reg_var[2] = pci_read_config16(dev, 0x90);
reg_var[1] = pci_read_config16(dev, 0x66);
reg_var[0] = pci_read_config16(dev, 0x64);
reg_var[2] = pci_read_config16(dev, LPC_WIDEIO2_GENERIC_PORT);
reg_var[1] = pci_read_config16(dev, LPC_WIDEIO1_GENERIC_PORT);
reg_var[0] = pci_read_config16(dev, LPC_WIDEIO_GENERIC_PORT);
/* todo: clean up the code style here */
for (link = dev->link_list; link; link = link->next) {
@ -344,21 +352,21 @@ static void lpc_enable_childrens_resources(device_t dev)
}
}
}
pci_write_config32(dev, 0x44, reg);
pci_write_config32(dev, 0x48, reg_x);
pci_write_config32(dev, LPC_IO_PORT_DECODE_ENABLE, reg);
pci_write_config32(dev, LPC_IO_OR_MEM_DECODE_ENABLE, reg_x);
/* Set WideIO for as many IOs found (fall through is on purpose) */
switch (var_num) {
case 3:
pci_write_config16(dev, 0x90, reg_var[2]);
pci_write_config16(dev, LPC_WIDEIO2_GENERIC_PORT, reg_var[2]);
/* fall through */
case 2:
pci_write_config16(dev, 0x66, reg_var[1]);
pci_write_config16(dev, LPC_WIDEIO1_GENERIC_PORT, reg_var[1]);
/* fall through */
case 1:
pci_write_config16(dev, 0x64, reg_var[0]);
pci_write_config16(dev, LPC_WIDEIO_GENERIC_PORT, reg_var[0]);
break;
}
pci_write_config8(dev, 0x74, wiosize);
pci_write_config8(dev, LPC_ALT_WIDEIO_RANGE_ENABLE, wiosize);
}
static void lpc_enable_resources(device_t dev)

View File

@ -20,10 +20,10 @@
#include <Porting.h>
#include <AGESA.h>
#include <soc/southbridge.h>
#include <soc/smbus.h>
#include <dimmSpd.h>
/*-----------------------------------------------------------------------------
*
/*
* readSmbusByteData - read a single SPD byte from any offset
*/
static int readSmbusByteData(int iobase, int address, char *buffer, int offset)
@ -33,33 +33,32 @@ static int readSmbusByteData(int iobase, int address, char *buffer, int offset)
address |= 1; // set read bit
__outbyte(iobase + 0, 0xff); // clear error status
__outbyte(iobase + 1, 0x1f); // clear error status
__outbyte(iobase + 3, offset); // offset in eeprom
__outbyte(iobase + 4, address); // slave address and read bit
__outbyte(iobase + 2, 0x48); // read byte command
__outbyte(iobase + SMBHSTSTAT, SMBHST_STAT_CLEAR);
__outbyte(iobase + SMBSLVSTAT, SMBSLV_STAT_CLEAR);
__outbyte(iobase + SMBHSTCMD, offset); // offset in eeprom
__outbyte(iobase + SMBHSTADDR, address); // slave addr & read bit
__outbyte(iobase + SMBHSTCTRL, SMBHST_CTRL_STRT + SMBHST_CTRL_BDT_RW);
// time limit to avoid hanging for unexpected error status
limit = __rdtsc() + 2000000000 / 10;
for (;;) {
status = __inbyte(iobase);
status = __inbyte(iobase + SMBHSTSTAT);
if (__rdtsc() > limit)
break;
if ((status & 2) == 0)
if ((status & SMBHST_STAT_INTERRUPT) == 0)
continue; // SMBusInterrupt not set, keep waiting
if ((status & 1) == 1)
if ((status & SMBHST_STAT_BUSY) == SMBHST_STAT_BUSY)
continue; // HostBusy set, keep waiting
break;
}
buffer[0] = __inbyte(iobase + 5);
if (status == 2)
status = 0; // check for done with no errors
buffer[0] = __inbyte(iobase + SMBHSTDAT0);
if (status == SMBHST_STAT_NOERROR)
status = 0; // done with no errors
return status;
}
/*-----------------------------------------------------------------------------
*
/*
* readSmbusByte - read a single SPD byte from the default offset
* this function is faster function readSmbusByteData
*/
@ -68,30 +67,29 @@ static int readSmbusByte(int iobase, int address, char *buffer)
unsigned int status;
UINT64 limit;
__outbyte(iobase + 0, 0xff); // clear error status
__outbyte(iobase + 2, 0x44); // read command
__outbyte(iobase + SMBHSTSTAT, SMBHST_STAT_CLEAR);
__outbyte(iobase + SMBHSTCTRL, SMBHST_CTRL_STRT + SMBHST_CTRL_BTE_RW);
// time limit to avoid hanging for unexpected error status
limit = __rdtsc() + 2000000000 / 10;
for (;;) {
status = __inbyte(iobase);
status = __inbyte(iobase + SMBHSTSTAT);
if (__rdtsc() > limit)
break;
if ((status & 2) == 0)
if ((status & SMBHST_STAT_INTERRUPT) == 0)
continue; // SMBusInterrupt not set, keep waiting
if ((status & 1) == 1)
if ((status & SMBHST_STAT_BUSY) == SMBHST_STAT_BUSY)
continue; // HostBusy set, keep waiting
break;
}
buffer[0] = __inbyte(iobase + 5);
if (status == 2)
status = 0; // check for done with no errors
buffer[0] = __inbyte(iobase + SMBHSTDAT0);
if (status == SMBHST_STAT_NOERROR)
status = 0; // done with no errors
return status;
}
/*---------------------------------------------------------------------------
*
/*
* readspd - Read one or more SPD bytes from a DIMM.
* Start with offset zero and read sequentially.
* Optimization relies on autoincrement to avoid
@ -137,15 +135,16 @@ static void writePmReg(int reg, int data)
static void setupFch(int ioBase)
{
/* register 0x2c and 0x2d are not defined in public datasheet */
writePmReg(0x2d, ioBase >> 8);
writePmReg(0x2c, ioBase | 1);
/* set SMBus clock to 400 KHz */
__outbyte(ioBase + 0x0e, 66000000 / 400000 / 4);
__outbyte(ioBase + SMBTIMING, 66000000 / 400000 / 4);
}
int sb_readSpd(int spdAddress, char *buf, size_t len)
{
int ioBase = 0xb00;
int ioBase = SMB_BASE_ADDR;
setupFch(ioBase);
return readspd(ioBase, spdAddress, buf, len);
}