Richard Spiegel has uploaded this change for review.

View Change

soc/amd/stoneyridge: Replace magic registers

Replace southbridge registers and register values from magic numbers to
literals, provided these registers are currently defined in publicly or
NDA datasheet.
Registers available only internally to AMD are left unchanged.

Code Files: smbus_spd.c, lpc.c, early_setup.c
Include Files: smbus.h, southbridge.h

Change-Id: I9187ba1c41ebb1201ddc177e8184672c60cd5f5d
Signed-off-by: Richard Spiegel <richard.spiegel@amd.corp-partner.google.com>
---
M src/soc/amd/stoneyridge/early_setup.c
M src/soc/amd/stoneyridge/include/soc/smbus.h
M src/soc/amd/stoneyridge/include/soc/southbridge.h
M src/soc/amd/stoneyridge/lpc.c
M src/soc/amd/stoneyridge/smbus_spd.c
5 files changed, 432 insertions(+), 206 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/67/21767/1
diff --git a/src/soc/amd/stoneyridge/early_setup.c b/src/soc/amd/stoneyridge/early_setup.c
index 5166a7f..e4c16ba 100644
--- a/src/soc/amd/stoneyridge/early_setup.c
+++ b/src/soc/amd/stoneyridge/early_setup.c
@@ -33,11 +33,11 @@

byte = read8((void *)ACPI_MMIO_BASE + AOAC_BASE + FCH_AOAC_REG56
+ CONFIG_UART_FOR_CONSOLE * 2);
- byte |= 1 << 3;
+ byte |= AOAC_PWR_ON_DEV;
write8((void *)ACPI_MMIO_BASE + AOAC_BASE + FCH_AOAC_REG56
+ CONFIG_UART_FOR_CONSOLE * 2, byte);
byte = read8((void *)ACPI_MMIO_BASE + AOAC_BASE + FCH_AOAC_REG62);
- byte |= 1 << 3;
+ byte |= AOAC_PWR_ON_DEV;
write8((void *)ACPI_MMIO_BASE + AOAC_BASE + FCH_AOAC_REG62, byte);
write8((void *)FCH_IOMUXx89_UART0_RTS_L_EGPIO137, 0);
write8((void *)FCH_IOMUXx8A_UART0_TXD_EGPIO138, 0);
@@ -57,9 +57,9 @@

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)
@@ -68,17 +68,17 @@
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)
@@ -233,7 +233,7 @@
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);
}

@@ -317,16 +317,18 @@

dev = PCI_DEV(0, PCU_DEV, LPC_FUNC);

- /* Decode variable LPC ROM address ranges 1 and 2. */
- reg8 = pci_io_read_config8(dev, 0x48);
+ /* 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, 0x48, reg8);
+ 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, 0x68, 0x000e);
+ pci_io_write_config16(dev, ROM_ADDRESS_RANGE1_START, 0x000e);
/* Enable LPC ROM range mirroring end at 0x000f(ffff). */
- pci_io_write_config16(dev, 0x6a, 0x000f);
+ pci_io_write_config16(dev, ROM_ADDRESS_RANGE1_END, 0x000f);

/* LPC ROM address range 2: */
/*
@@ -336,10 +338,10 @@
* 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)
diff --git a/src/soc/amd/stoneyridge/include/soc/smbus.h b/src/soc/amd/stoneyridge/include/soc/smbus.h
index 90a59e4..a9b80eb 100644
--- a/src/soc/amd/stoneyridge/include/soc/smbus.h
+++ b/src/soc/amd/stoneyridge/include/soc/smbus.h
@@ -19,17 +19,46 @@
#include <stdint.h>

#define SMBHSTSTAT 0x0
-#define SMBSLVSTAT 0x1
+#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_KILL 0x02
+#define SMBHST_CTRL_IEN 0x01
+
#define SMBHSTCMD 0x3
#define SMBHSTADDR 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
-#define SMBHSTBLKDAT 0x7
+#define SMBHSTBLKDAT 0x7
#define SMBSLVCTRL 0x8
#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
diff --git a/src/soc/amd/stoneyridge/include/soc/southbridge.h b/src/soc/amd/stoneyridge/include/soc/southbridge.h
index 20edf5f..31f4b8e 100644
--- a/src/soc/amd/stoneyridge/include/soc/southbridge.h
+++ b/src/soc/amd/stoneyridge/include/soc/southbridge.h
@@ -23,6 +23,109 @@
#include <device/device.h>
#include "chip.h"

+/* Some older include files such as fch.h use predefined bits values
+ * instead of using BIT(x) macro. As they are used in early_setup.c,
+ * they need to be defined, and southbridge.h needs to be included
+ * before the ofending file.
+ */
+
+#ifndef BIT0
+#define BIT0 BIT(0)
+#endif
+#ifndef BIT1
+#define BIT1 BIT(1)
+#endif
+#ifndef BIT2
+#define BIT2 BIT(2)
+#endif
+#ifndef BIT3
+#define BIT3 BIT(3)
+#endif
+#ifndef BIT4
+#define BIT4 BIT(4)
+#endif
+#ifndef BIT5
+#define BIT5 BIT(5)
+#endif
+#ifndef BIT6
+#define BIT6 BIT(6)
+#endif
+#ifndef BIT7
+#define BIT7 BIT(7)
+#endif
+#ifndef BIT8
+#define BIT8 BIT(8)
+#endif
+#ifndef BIT9
+#define BIT9 BIT(9)
+#endif
+#ifndef BIT10
+#define BIT10 BIT(10)
+#endif
+#ifndef BIT11
+#define BIT11 BIT(11)
+#endif
+#ifndef BIT12
+#define BIT12 BIT(12)
+#endif
+#ifndef BIT13
+#define BIT13 BIT(13)
+#endif
+#ifndef BIT14
+#define BIT14 BIT(14)
+#endif
+#ifndef BIT15
+#define BIT15 BIT(15)
+#endif
+#ifndef BIT16
+#define BIT16 BIT(16)
+#endif
+#ifndef BIT17
+#define BIT17 BIT(17)
+#endif
+#ifndef BIT18
+#define BIT18 BIT(18)
+#endif
+#ifndef BIT19
+#define BIT19 BIT(19)
+#endif
+#ifndef BIT20
+#define BIT20 BIT(20)
+#endif
+#ifndef BIT21
+#define BIT21 BIT(21)
+#endif
+#ifndef BIT22
+#define BIT22 BIT(22)
+#endif
+#ifndef BIT23
+#define BIT23 BIT(23)
+#endif
+#ifndef BIT24
+#define BIT24 BIT(24)
+#endif
+#ifndef BIT25
+#define BIT25 BIT(25)
+#endif
+#ifndef BIT26
+#define BIT26 BIT(26)
+#endif
+#ifndef BIT27
+#define BIT27 BIT(27)
+#endif
+#ifndef BIT28
+#define BIT28 BIT(28)
+#endif
+#ifndef BIT29
+#define BIT29 BIT(29)
+#endif
+#ifndef BIT30
+#define BIT30 BIT(30)
+#endif
+#ifndef BIT31
+#define BIT31 BIT(31)
+#endif
+
#define IO_APIC2_ADDR 0xfec20000

/* Offsets from ACPI_MMIO_BASE
@@ -37,25 +140,40 @@
/* Power management index/data registers */
#define BIOSRAM_INDEX 0xcd4
#define BIOSRAM_DATA 0xcd5
-#define PM_INDEX 0xcd6
-#define PM_DATA 0xcd7
-#define PM2_INDEX 0xcd0
-#define PM2_DATA 0xcd1
+#define PM_INDEX 0xcd6
+#define PM_DATA 0xcd7
+#define PM2_INDEX 0xcd0
+#define PM2_DATA 0xcd1

#define PM_ACPI_MMIO_EN 0x24
#define PM_SERIRQ_CONF 0x54
-#define PM_EVT_BLK 0x60
-#define PM1_CNT_BLK 0x62
-#define PM_TMR_BLK 0x64
-#define PM_CPU_CTRL 0x66
-#define PM_GPE0_BLK 0x68
+#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
+#define PM_CPU_CTRL 0x66
+#define PM_GPE0_BLK 0x68
#define PM_ACPI_SMI_CMD 0x6a
#define PM_ACPI_CONF 0x74
#define PM_PMIO_DEBUG 0xd2
#define PM_MANUAL_RESET 0xd3
-#define PM_HUD_SD_FLASH_CTRL 0xe7
-#define PM_YANG_SD_FLASH_CTRL 0xe8
-#define PM_PCIB_CFG 0xea
+#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

@@ -78,8 +196,14 @@

#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)
@@ -118,16 +242,55 @@
#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 definition 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))
@@ -165,6 +328,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. */
diff --git a/src/soc/amd/stoneyridge/lpc.c b/src/soc/amd/stoneyridge/lpc.c
index 7886433..1580d0e 100644
--- a/src/soc/amd/stoneyridge/lpc.c
+++ b/src/soc/amd/stoneyridge/lpc.c
@@ -40,7 +40,9 @@
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,33 +52,33 @@
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
* 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
+ /* bit3: Fix SPI_CS# timing issue when running at 66M. TODO:A12.
+ * 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();

@@ -94,9 +96,9 @@
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 +119,8 @@
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,11 +147,141 @@
/* 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);

pci_dev_set_resources(dev);
+}
+
+static void set_lpc_resource(device_t child,
+ int *variable_num,
+ u16 *reg_var,
+ u32 *reg,
+ u32 *reg_x,
+ u16 reg_size,
+ u8 *wiosize)
+{
+ struct resource *res;
+ u32 base, end; /* don't need long long */
+ u32 rsize = 0, set = 0, set_x = 0;
+ u16 var_num;
+
+ var_num = *variable_num;
+ for (res = child->resource_list ; res ; res = res->next) {
+ if (!(res->flags & IORESOURCE_IO))
+ continue;
+ base = res->base;
+ end = resource_end(res);
+ 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 |= DECODE_ENABLE_KBC_PORT;
+ rsize = 1;
+ break;
+ case 0x3f8: /* COM1 */
+ set |= DECODE_ENABLE_SERIAL_PORT0;
+ rsize = 8;
+ break;
+ case 0x2f8: /* COM2 */
+ set |= DECODE_ENABLE_SERIAL_PORT1;
+ rsize = 8;
+ break;
+ case 0x378: /* Parallel 1 */
+ set |= DECODE_ENABLE_PARALLEL_PORT0;
+ /* enable 0x778 for ECP mode */
+ set |= DECODE_ENABLE_PARALLEL_PORT1;
+ rsize = 8;
+ break;
+ case 0x3f0: /* FD0 */
+ set |= DECODE_ENABLE_FDC_PORT0;
+ rsize = 8;
+ break;
+ case 0x220: /* 0x220 - 0x227 */
+ set |= DECODE_ENABLE_SERIAL_PORT2;
+ rsize = 8;
+ break;
+ case 0x228: /* 0x228 - 0x22f */
+ set |= DECODE_ENABLE_SERIAL_PORT3;
+ rsize = 8;
+ break;
+ case 0x238: /* 0x238 - 0x23f */
+ set |= DECODE_ENABLE_SERIAL_PORT4;
+ rsize = 8;
+ break;
+ case 0x300: /* 0x300 - 0x301 */
+ set |= DECODE_ENABLE_MIDI_PORT0;
+ rsize = 2;
+ break;
+ case 0x400:
+ set_x |= DECODE_IO_PORT_ENABLE0;
+ rsize = 0x40;
+ break;
+ case 0x480:
+ set_x |= DECODE_IO_PORT_ENABLE1;
+ rsize = 0x40;
+ break;
+ case 0x500:
+ set_x |= DECODE_IO_PORT_ENABLE2;
+ rsize = 0x40;
+ break;
+ case 0x580:
+ set_x |= DECODE_IO_PORT_ENABLE3;
+ rsize = 0x40;
+ break;
+ case 0x4700:
+ set_x |= DECODE_IO_PORT_ENABLE5;
+ rsize = 0xc;
+ break;
+ case 0xfd60:
+ set_x |= DECODE_IO_PORT_ENABLE6;
+ rsize = 16;
+ break;
+ default:
+ rsize = 0;
+ /* try AGESA allocated region in region 0 */
+ if ((var_num > 0) && ((base >= reg_var[0]) &&
+ ((base + res->size) <= (reg_var[0] + reg_size))))
+ rsize = reg_size;
+ }
+ /* check if region found and matches the enable */
+ if (res->size <= rsize) {
+ *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))) {
+ /* use variable ranges if pre-defined do not match */
+ switch (var_num) {
+ case 0:
+ *reg_x |= LPC_WIDEIO0_ENABLE;
+ if (res->size <= 16)
+ *wiosize |= LPC_ALT_WIDEIO0_ENABLE;
+ break;
+ case 1:
+ *reg_x |= LPC_WIDEIO1_ENABLE;
+ if (res->size <= 16)
+ *wiosize |= LPC_ALT_WIDEIO1_ENABLE;
+ break;
+ case 2:
+ *reg_x |= LPC_WIDEIO2_ENABLE;
+ if (res->size <= 16)
+ *wiosize |= LPC_ALT_WIDEIO2_ENABLE;
+ break;
+ }
+ reg_var[var_num++] = base & 0xffff;
+ } else {
+ printk(BIOS_ERR,
+ "cannot fit LPC decode region:");
+ printk(BIOS_ERR, "%s, base = 0x%08x, end = 0x%08x\n",
+ dev_path(child), base, end);
+ }
+ }
+ *variable_num = var_num;
}

/**
@@ -165,7 +297,7 @@
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
* resource we try to fit, do it like this for all regions < 16 bytes.
@@ -177,26 +309,26 @@
* 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) {
@@ -205,137 +337,31 @@
child = child->sibling) {
if (child->enabled
&& (child->path.type == DEVICE_PATH_PNP)) {
- struct resource *res;
- for (res = child->resource_list ; res ; res = res->next) {
- u32 base, end; /* don't need long long */
- u32 rsize, set = 0, set_x = 0;
- if (!(res->flags & IORESOURCE_IO))
- 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);
- switch (base) {
- case 0x60: /* KB */
- case 0x64: /* MS */
- set |= (1 << 29);
- rsize = 1;
- break;
- case 0x3f8: /* COM1 */
- set |= (1 << 6);
- rsize = 8;
- break;
- case 0x2f8: /* COM2 */
- set |= (1 << 7);
- rsize = 8;
- break;
- case 0x378: /* Parallel 1 */
- set |= (1 << 0);
- set |= (1 << 1); /* + 0x778 for ECP */
- rsize = 8;
- break;
- case 0x3f0: /* FD0 */
- set |= (1 << 26);
- rsize = 8;
- break;
- case 0x220: /* 0x220 - 0x227 */
- set |= (1 << 8);
- rsize = 8;
- break;
- case 0x228: /* 0x228 - 0x22f */
- set |= (1 << 9);
- rsize = 8;
- break;
- case 0x238: /* 0x238 - 0x23f */
- set |= (1 << 10);
- rsize = 8;
- break;
- case 0x300: /* 0x300 - 0x301 */
- set |= (1 << 18);
- rsize = 2;
- break;
- case 0x400:
- set_x |= (1 << 16);
- rsize = 0x40;
- break;
- case 0x480:
- set_x |= (1 << 17);
- rsize = 0x40;
- break;
- case 0x500:
- set_x |= (1 << 18);
- rsize = 0x40;
- break;
- case 0x580:
- set_x |= (1 << 19);
- rsize = 0x40;
- break;
- case 0x4700:
- set_x |= (1 << 22);
- rsize = 0xc;
- break;
- case 0xfd60:
- set_x |= (1 << 23);
- rsize = 16;
- break;
- default:
- rsize = 0;
- /* try AGESA allocated region in region 0 */
- if ((var_num > 0) && ((base >= reg_var[0]) &&
- ((base + res->size) <= (reg_var[0] + reg_size[0]))))
- rsize = reg_size[0];
- }
- /* check if region found and matches the enable */
- if (res->size <= rsize) {
- 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))) {
- /* use variable ranges if pre-defined do not match */
- switch (var_num) {
- case 0:
- reg_x |= (1 << 2);
- if (res->size <= 16)
- wiosize |= (1 << 0);
- break;
- case 1:
- reg_x |= (1 << 24);
- if (res->size <= 16)
- wiosize |= (1 << 2);
- break;
- case 2:
- reg_x |= (1 << 25);
- if (res->size <= 16)
- wiosize |= (1 << 3);
- break;
- }
- reg_var[var_num++] =
- base & 0xffff;
- } else {
- printk(BIOS_ERR, "cannot fit LPC decode region:%s, base=0x%08x, end=0x%08x\n",
- dev_path(child), base, end);
- }
- }
+ set_lpc_resource(child,
+ &var_num,
+ reg_var,
+ &reg,
+ &reg_x,
+ reg_size[0],
+ &wiosize);
}
}
}
- 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)
diff --git a/src/soc/amd/stoneyridge/smbus_spd.c b/src/soc/amd/stoneyridge/smbus_spd.c
index 6669ccb..94deed5 100644
--- a/src/soc/amd/stoneyridge/smbus_spd.c
+++ b/src/soc/amd/stoneyridge/smbus_spd.c
@@ -21,6 +21,7 @@
#include <AGESA.h>
#include <amdlib.h>
#include <soc/southbridge.h>
+#include <soc/smbus.h>
#include <dimmSpd.h>

/*-----------------------------------------------------------------------------
@@ -34,28 +35,28 @@

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;
}

@@ -69,25 +70,25 @@
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;
}

@@ -138,15 +139,16 @@

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);
}

To view, visit change 21767. To unsubscribe, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9187ba1c41ebb1201ddc177e8184672c60cd5f5d
Gerrit-Change-Number: 21767
Gerrit-PatchSet: 1
Gerrit-Owner: Richard Spiegel <richard.spiegel@silverbackltd.com>