soc/amd/stoneyridge: Access SMBUS through MMIO

Currently SMBUS registers are accessed through IO, but with stoneyridge
they can be accessed through MMIO. This reduces the time of execution by
a tiny amount (MMIO write is faster than IO write, though MMIO read is about
as fast as IO read) as most of the time consumed is actually transaction
time. Convert code to MMIO access.

BUG=b:117754784
TEST=Used IO to write and MMIO to read, to confirm a one to one relationship
between IO and MMIO. Then build and boot grunt.

Change-Id: Ibe1471d1d578611e7d666f70bc97de4c3b74d7f8
Signed-off-by: Richard Spiegel <richard.spiegel@silverbackltd.com>
Reviewed-on: https://review.coreboot.org/c/29258
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Richard Spiegel 2018-10-24 12:51:21 -07:00 committed by Patrick Georgi
parent 9ca43191ab
commit b40e193948
8 changed files with 135 additions and 134 deletions

View File

@ -38,6 +38,8 @@
#define PM_MMIO_BASE 0xfed80300 #define PM_MMIO_BASE 0xfed80300
#define BIOSRAM_MMIO_BASE 0xfed80500 #define BIOSRAM_MMIO_BASE 0xfed80500
#define ACPI_REG_MMIO_BASE 0xfed80800 #define ACPI_REG_MMIO_BASE 0xfed80800
#define ASF_MMIO_BASE 0xfed80900
#define SMBUS_MMIO_BASE 0xfed80a00
#define GPIO_IOMUX_MMIO_BASE 0xfed80d00 #define GPIO_IOMUX_MMIO_BASE 0xfed80d00
#define MISC_MMIO_BASE 0xfed80e00 #define MISC_MMIO_BASE 0xfed80e00
#define XHCI_ACPI_PM_MMIO_BASE 0xfed81c00 #define XHCI_ACPI_PM_MMIO_BASE 0xfed81c00

View File

@ -19,50 +19,6 @@
#include <stdint.h> #include <stdint.h>
#include <soc/iomap.h> #include <soc/iomap.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 SMBHST_STAT_VAL_BITS 0x1f
#define SMBHST_STAT_ERROR_BITS 0x1c
#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
#define SMBHSTDAT1 0x6
#define SMBHSTBLKDAT 0x7
#define SMBSLVCTRL 0x8
#define SMBSLVCMD_SHADOW 0x9
#define SMBSLVEVT 0xa
#define SMBSLVDAT 0xc
#define SMBTIMING 0xe
#define SMB_ASF_IO_BASE 0x01
#define SMB_SPEED_400KHZ (66000000 / (400000 * 4)) #define SMB_SPEED_400KHZ (66000000 / (400000 * 4))
#define AX_INDXC 0 #define AX_INDXC 0
@ -91,10 +47,10 @@
#define rcindxp_reg(reg, port, mask, val) \ #define rcindxp_reg(reg, port, mask, val) \
alink_rc_indx((RC_INDXP), (reg), (port), (mask), (val)) alink_rc_indx((RC_INDXP), (reg), (port), (mask), (val))
int do_smbus_read_byte(u16 smbus_io_base, u8 device, u8 address); int do_smbus_read_byte(u32 mmio, u8 device, u8 address);
int do_smbus_write_byte(u16 smbus_io_base, u8 device, u8 address, u8 val); int do_smbus_write_byte(u32 mmio, u8 device, u8 address, u8 val);
int do_smbus_recv_byte(u16 smbus_io_base, u8 device); int do_smbus_recv_byte(u32 mmio, u8 device);
int do_smbus_send_byte(u16 smbus_io_base, u8 device, u8 val); int do_smbus_send_byte(u32 mmio, u8 device, u8 val);
void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, u32 mask, u32 val); void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, u32 mask, u32 val);
void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val); void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val);
void alink_ax_indx(u32 space /*c or p? */, u32 axindc, u32 mask, u32 val); void alink_ax_indx(u32 space /*c or p? */, u32 axindc, u32 mask, u32 val);

View File

@ -39,6 +39,8 @@
#define FORCE_SLPSTATE_RETRY BIT(25) #define FORCE_SLPSTATE_RETRY BIT(25)
#define FORCE_STPCLK_RETRY BIT(24) #define FORCE_STPCLK_RETRY BIT(24)
#define SMB_ASF_IO_BASE 0x01 /* part of PM_DECODE_EN */
#define PWR_RESET_CFG 0x10 #define PWR_RESET_CFG 0x10
#define TOGGLE_ALL_PWR_GOOD BIT(1) #define TOGGLE_ALL_PWR_GOOD BIT(1)
@ -111,6 +113,50 @@
#define MMIO_ACPI_GPE0_EN 0x18 #define MMIO_ACPI_GPE0_EN 0x18
#define MMIO_ACPI_PM_TMR_BLK 0x08 #define MMIO_ACPI_PM_TMR_BLK 0x08
/* SMBUS MMIO offsets 0xfed80a00 */
#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 SMBHST_STAT_VAL_BITS 0x1f
#define SMBHST_STAT_ERROR_BITS 0x1c
#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
#define SMBHSTDAT1 0x6
#define SMBHSTBLKDAT 0x7
#define SMBSLVCTRL 0x8
#define SMBSLVCMD_SHADOW 0x9
#define SMBSLVEVT 0xa
#define SMBSLVDAT 0xc
#define SMBTIMING 0xe
/* FCH MISC Registers 0xfed80e00 */ /* FCH MISC Registers 0xfed80e00 */
#define GPP_CLK_CNTRL 0x00 #define GPP_CLK_CNTRL 0x00
#define GPP_CLK2_REQ_MAP_SHIFT 8 #define GPP_CLK2_REQ_MAP_SHIFT 8
@ -480,6 +526,8 @@ void xhci_pm_write16(uint8_t reg, uint16_t value);
uint16_t xhci_pm_read16(uint8_t reg); uint16_t xhci_pm_read16(uint8_t reg);
void xhci_pm_write32(uint8_t reg, uint32_t value); void xhci_pm_write32(uint8_t reg, uint32_t value);
uint32_t xhci_pm_read32(uint8_t reg); uint32_t xhci_pm_read32(uint8_t reg);
void smbus_write8(uint32_t mmio, uint8_t reg, uint8_t value);
uint8_t smbus_read8(uint32_t mmio, uint8_t reg);
void bootblock_fch_early_init(void); void bootblock_fch_early_init(void);
void bootblock_fch_init(void); void bootblock_fch_init(void);
/** /**

View File

@ -200,6 +200,16 @@ uint32_t xhci_pm_read32(uint8_t reg)
return read32((void *)(XHCI_ACPI_PM_MMIO_BASE + reg)); return read32((void *)(XHCI_ACPI_PM_MMIO_BASE + reg));
} }
void smbus_write8(uint32_t mmio, uint8_t reg, uint8_t value)
{
write8((void *)(mmio + reg), value);
}
uint8_t smbus_read8(uint32_t mmio, uint8_t reg)
{
return read8((void *)(mmio + reg));
}
int acpi_get_sleep_type(void) int acpi_get_sleep_type(void)
{ {
return acpi_sleep_from_pm1(inw(pm_acpi_pm_cnt_blk())); return acpi_sleep_from_pm1(inw(pm_acpi_pm_cnt_blk()));

View File

@ -35,60 +35,49 @@ static void sm_init(struct device *dev)
setup_ioapic(VIO_APIC_VADDR, CONFIG_MAX_CPUS); setup_ioapic(VIO_APIC_VADDR, CONFIG_MAX_CPUS);
} }
static int lsmbus_recv_byte(struct device *dev) static u32 get_sm_mmio(struct device *dev)
{ {
u8 device;
struct resource *res; struct resource *res;
struct bus *pbus; struct bus *pbus;
device = dev->path.i2c.device;
pbus = get_pbus_smbus(dev); pbus = get_pbus_smbus(dev);
res = find_resource(pbus->dev, 0x90); res = find_resource(pbus->dev, 0x90);
if (res->base == SMB_BASE_ADDR)
return SMBUS_MMIO_BASE;
return do_smbus_recv_byte(res->base, device); return ASF_MMIO_BASE;
}
static int lsmbus_recv_byte(struct device *dev)
{
u8 device;
device = dev->path.i2c.device;
return do_smbus_recv_byte(get_sm_mmio(dev), device);
} }
static int lsmbus_send_byte(struct device *dev, u8 val) static int lsmbus_send_byte(struct device *dev, u8 val)
{ {
u8 device; u8 device;
struct resource *res;
struct bus *pbus;
device = dev->path.i2c.device; device = dev->path.i2c.device;
pbus = get_pbus_smbus(dev); return do_smbus_send_byte(get_sm_mmio(dev), device, val);
res = find_resource(pbus->dev, 0x90);
return do_smbus_send_byte(res->base, device, val);
} }
static int lsmbus_read_byte(struct device *dev, u8 address) static int lsmbus_read_byte(struct device *dev, u8 address)
{ {
u8 device; u8 device;
struct resource *res;
struct bus *pbus;
device = dev->path.i2c.device; device = dev->path.i2c.device;
pbus = get_pbus_smbus(dev); return do_smbus_read_byte(get_sm_mmio(dev), device, address);
res = find_resource(pbus->dev, 0x90);
return do_smbus_read_byte(res->base, device, address);
} }
static int lsmbus_write_byte(struct device *dev, u8 address, u8 val) static int lsmbus_write_byte(struct device *dev, u8 address, u8 val)
{ {
u8 device; u8 device;
struct resource *res;
struct bus *pbus;
device = dev->path.i2c.device; device = dev->path.i2c.device;
pbus = get_pbus_smbus(dev); return do_smbus_write_byte(get_sm_mmio(dev), device, address, val);
res = find_resource(pbus->dev, 0x90);
return do_smbus_write_byte(res->base, device, address, val);
} }
static struct smbus_bus_operations lops_smbus_bus = { static struct smbus_bus_operations lops_smbus_bus = {
.recv_byte = lsmbus_recv_byte, .recv_byte = lsmbus_recv_byte,

View File

@ -16,143 +16,144 @@
#include <io.h> #include <io.h>
#include <stdint.h> #include <stdint.h>
#include <soc/smbus.h> #include <soc/smbus.h>
#include <soc/southbridge.h>
static int smbus_wait_until_ready(u16 smbus_io_base) static int smbus_wait_until_ready(u32 mmio)
{ {
u32 loops; u32 loops;
loops = SMBUS_TIMEOUT; loops = SMBUS_TIMEOUT;
do { do {
u8 val; u8 val;
val = inb(smbus_io_base + SMBHSTSTAT); val = smbus_read8(mmio, SMBHSTSTAT);
val &= SMBHST_STAT_VAL_BITS; val &= SMBHST_STAT_VAL_BITS;
if (val == 0) { /* ready now */ if (val == 0) { /* ready now */
return 0; return 0;
} }
outb(val, smbus_io_base + SMBHSTSTAT); smbus_write8(mmio, SMBHSTSTAT, val);
} while (--loops); } while (--loops);
return -2; /* time out */ return -2; /* time out */
} }
static int smbus_wait_until_done(u16 smbus_io_base) static int smbus_wait_until_done(u32 mmio)
{ {
u32 loops; u32 loops;
loops = SMBUS_TIMEOUT; loops = SMBUS_TIMEOUT;
do { do {
u8 val; u8 val;
val = inb(smbus_io_base + SMBHSTSTAT); val = smbus_read8(mmio, SMBHSTSTAT);
val &= SMBHST_STAT_VAL_BITS; /* mask off reserved bits */ val &= SMBHST_STAT_VAL_BITS; /* mask off reserved bits */
if (val & SMBHST_STAT_ERROR_BITS) if (val & SMBHST_STAT_ERROR_BITS)
return -5; /* error */ return -5; /* error */
if (val == SMBHST_STAT_NOERROR) { if (val == SMBHST_STAT_NOERROR) {
outb(val, smbus_io_base + SMBHSTSTAT); /* clear sts */ smbus_write8(mmio, SMBHSTSTAT, val); /* clear sts */
return 0; return 0;
} }
} while (--loops); } while (--loops);
return -3; /* timeout */ return -3; /* timeout */
} }
int do_smbus_recv_byte(u16 smbus_io_base, u8 device) int do_smbus_recv_byte(u32 mmio, u8 device)
{ {
u8 byte; u8 byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) if (smbus_wait_until_ready(mmio) < 0)
return -2; /* not ready */ return -2; /* not ready */
/* set the device I'm talking to */ /* set the device I'm talking to */
outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR); smbus_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1);
byte = inb(smbus_io_base + SMBHSTCTRL); byte = smbus_read8(mmio, SMBHSTCTRL);
byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */ byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */
outb(byte, smbus_io_base + SMBHSTCTRL); smbus_write8(mmio, SMBHSTCTRL, byte);
/* poll for transaction completion */ /* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) if (smbus_wait_until_done(mmio) < 0)
return -3; /* timeout or error */ return -3; /* timeout or error */
/* read results of transaction */ /* read results of transaction */
byte = inb(smbus_io_base + SMBHSTDAT0); byte = smbus_read8(mmio, SMBHSTDAT0);
return byte; return byte;
} }
int do_smbus_send_byte(u16 smbus_io_base, u8 device, u8 val) int do_smbus_send_byte(u32 mmio, u8 device, u8 val)
{ {
u8 byte; u8 byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) if (smbus_wait_until_ready(mmio) < 0)
return -2; /* not ready */ return -2; /* not ready */
/* set the command... */ /* set the command... */
outb(val, smbus_io_base + SMBHSTDAT0); smbus_write8(mmio, SMBHSTDAT0, val);
/* set the device I'm talking to */ /* set the device I'm talking to */
outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR); smbus_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0);
byte = inb(smbus_io_base + SMBHSTCTRL); byte = smbus_read8(mmio, SMBHSTCTRL);
byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */ byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */
outb(byte, smbus_io_base + SMBHSTCTRL); smbus_write8(mmio, SMBHSTCTRL, byte);
/* poll for transaction completion */ /* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) if (smbus_wait_until_done(mmio) < 0)
return -3; /* timeout or error */ return -3; /* timeout or error */
return 0; return 0;
} }
int do_smbus_read_byte(u16 smbus_io_base, u8 device, u8 address) int do_smbus_read_byte(u32 mmio, u8 device, u8 address)
{ {
u8 byte; u8 byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) if (smbus_wait_until_ready(mmio) < 0)
return -2; /* not ready */ return -2; /* not ready */
/* set the command/address... */ /* set the command/address... */
outb(address & 0xff, smbus_io_base + SMBHSTCMD); smbus_write8(mmio, SMBHSTCMD, address & 0xff);
/* set the device I'm talking to */ /* set the device I'm talking to */
outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR); smbus_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1);
byte = inb(smbus_io_base + SMBHSTCTRL); byte = smbus_read8(mmio, SMBHSTCTRL);
byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */ byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */
outb(byte, smbus_io_base + SMBHSTCTRL); smbus_write8(mmio, SMBHSTCTRL, byte);
/* poll for transaction completion */ /* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) if (smbus_wait_until_done(mmio) < 0)
return -3; /* timeout or error */ return -3; /* timeout or error */
/* read results of transaction */ /* read results of transaction */
byte = inb(smbus_io_base + SMBHSTDAT0); byte = smbus_read8(mmio, SMBHSTDAT0);
return byte; return byte;
} }
int do_smbus_write_byte(u16 smbus_io_base, u8 device, u8 address, u8 val) int do_smbus_write_byte(u32 mmio, u8 device, u8 address, u8 val)
{ {
u8 byte; u8 byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) if (smbus_wait_until_ready(mmio) < 0)
return -2; /* not ready */ return -2; /* not ready */
/* set the command/address... */ /* set the command/address... */
outb(address & 0xff, smbus_io_base + SMBHSTCMD); smbus_write8(mmio, SMBHSTCMD, address & 0xff);
/* set the device I'm talking to */ /* set the device I'm talking to */
outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR); smbus_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0);
/* output value */ /* output value */
outb(val, smbus_io_base + SMBHSTDAT0); smbus_write8(mmio, SMBHSTDAT0, val);
byte = inb(smbus_io_base + SMBHSTCTRL); byte = smbus_read8(mmio, SMBHSTCTRL);
byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */ byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */ byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */
outb(byte, smbus_io_base + SMBHSTCTRL); smbus_write8(mmio, SMBHSTCTRL, byte);
/* poll for transaction completion */ /* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) if (smbus_wait_until_done(mmio) < 0)
return -3; /* timeout or error */ return -3; /* timeout or error */
return 0; return 0;

View File

@ -27,8 +27,7 @@
* sending offset for every byte. * sending offset for every byte.
* Reads 128 bytes in 7-8 ms at 400 KHz. * Reads 128 bytes in 7-8 ms at 400 KHz.
*/ */
static int readspd(uint16_t iobase, uint8_t SmbusSlaveAddress, static int readspd(uint8_t SmbusSlaveAddress, char *buffer, size_t count)
char *buffer, size_t count)
{ {
uint8_t dev_addr; uint8_t dev_addr;
size_t index; size_t index;
@ -36,8 +35,8 @@ static int readspd(uint16_t iobase, uint8_t SmbusSlaveAddress,
char *pbuf = buffer; char *pbuf = buffer;
printk(BIOS_SPEW, "-------------READING SPD-----------\n"); printk(BIOS_SPEW, "-------------READING SPD-----------\n");
printk(BIOS_SPEW, "iobase: 0x%08X, SmbusSlave: 0x%08X, count: %d\n", printk(BIOS_SPEW, "SmbusSlave: 0x%08X, count: %zd\n",
iobase, SmbusSlaveAddress, (int)count); SmbusSlaveAddress, count);
/* /*
* Convert received device address to the format accepted by * Convert received device address to the format accepted by
@ -46,7 +45,7 @@ static int readspd(uint16_t iobase, uint8_t SmbusSlaveAddress,
dev_addr = (SmbusSlaveAddress >> 1); dev_addr = (SmbusSlaveAddress >> 1);
/* Read the first SPD byte */ /* Read the first SPD byte */
error = do_smbus_read_byte(iobase, dev_addr, 0); error = do_smbus_read_byte(SMBUS_MMIO_BASE, dev_addr, 0);
if (error < 0) { if (error < 0) {
printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n"); printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n");
return error; return error;
@ -56,7 +55,7 @@ static int readspd(uint16_t iobase, uint8_t SmbusSlaveAddress,
/* Read the remaining SPD bytes using do_smbus_recv_byte for speed */ /* Read the remaining SPD bytes using do_smbus_recv_byte for speed */
for (index = 1 ; index < count ; index++) { for (index = 1 ; index < count ; index++) {
error = do_smbus_recv_byte(iobase, dev_addr); error = do_smbus_recv_byte(SMBUS_MMIO_BASE, dev_addr);
if (error < 0) { if (error < 0) {
printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n"); printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n");
return error; return error;
@ -70,24 +69,7 @@ static int readspd(uint16_t iobase, uint8_t SmbusSlaveAddress,
return 0; return 0;
} }
static void write_pm_reg(int reg, int data)
{
outb(reg, PM_INDEX);
outb(data, PM_DATA);
}
static void setup_fch(uint16_t ioBase)
{
write_pm_reg(SMB_ASF_IO_BASE, ioBase >> 8);
outb(SMB_SPEED_400KHZ, ioBase + SMBTIMING);
/* Clear all SMBUS status bits */
outb(SMBHST_STAT_CLEAR, ioBase + SMBHSTSTAT);
outb(SMBSLV_STAT_CLEAR, ioBase + SMBSLVSTAT);
}
int sb_read_spd(uint8_t spdAddress, char *buf, size_t len) int sb_read_spd(uint8_t spdAddress, char *buf, size_t len)
{ {
uint16_t ioBase = SMB_BASE_ADDR; return readspd(spdAddress, buf, len);
setup_fch(ioBase);
return readspd(ioBase, spdAddress, buf, len);
} }

View File

@ -28,6 +28,7 @@
#include <amdblocks/agesawrapper.h> #include <amdblocks/agesawrapper.h>
#include <amdblocks/reset.h> #include <amdblocks/reset.h>
#include <soc/southbridge.h> #include <soc/southbridge.h>
#include <soc/smbus.h>
#include <soc/smi.h> #include <soc/smi.h>
#include <soc/amd_pci_int_defs.h> #include <soc/amd_pci_int_defs.h>
#include <delay.h> #include <delay.h>
@ -619,6 +620,17 @@ static void setup_misc(int *reboot)
} }
} }
static void fch_smbus_init(void)
{
pm_write8(SMB_ASF_IO_BASE, SMB_BASE_ADDR >> 8);
smbus_write8(SMBUS_MMIO_BASE, SMBTIMING, SMB_SPEED_400KHZ);
/* Clear all SMBUS status bits */
smbus_write8(SMBUS_MMIO_BASE, SMBHSTSTAT, SMBHST_STAT_CLEAR);
smbus_write8(SMBUS_MMIO_BASE, SMBSLVSTAT, SMBSLV_STAT_CLEAR);
smbus_write8(ASF_MMIO_BASE, SMBHSTSTAT, SMBHST_STAT_CLEAR);
smbus_write8(ASF_MMIO_BASE, SMBSLVSTAT, SMBSLV_STAT_CLEAR);
}
/* Before console init */ /* Before console init */
void bootblock_fch_early_init(void) void bootblock_fch_early_init(void)
{ {
@ -631,6 +643,7 @@ void bootblock_fch_early_init(void)
sb_spibase(); sb_spibase();
sb_disable_4dw_burst(); /* Must be disabled on CZ(ST) */ sb_disable_4dw_burst(); /* Must be disabled on CZ(ST) */
sb_acpi_mmio_decode(); sb_acpi_mmio_decode();
fch_smbus_init();
sb_enable_cf9_io(); sb_enable_cf9_io();
setup_spread_spectrum(&reboot); setup_spread_spectrum(&reboot);
setup_misc(&reboot); setup_misc(&reboot);