aboutsummaryrefslogtreecommitdiff
path: root/src/soc/amd/stoneyridge/smbus_spd.c
diff options
context:
space:
mode:
authorRichard Spiegel <richard.spiegel@silverbackltd.com>2017-11-08 14:58:30 -0700
committerAaron Durbin <adurbin@chromium.org>2017-11-10 19:11:12 +0000
commitcd04e31c8beaecb2e4c95ab47934b32b2b5e3b06 (patch)
tree6c429c36fba38a110f5a85bdab3b28ab784d33a1 /src/soc/amd/stoneyridge/smbus_spd.c
parent3f6c400310a930d226e85e77f29c51f03578f0f1 (diff)
soc/amd/stoneyridge: Simplify and fix SMBUS code
Solve issues left from Change-Id Ib88a868e654ad127be70ecc506f6b90b784f8d1b Unify code: smbus.c to have the actual execution code, sm.c and smbus_spd.c call functions within smbus.c. Fix some functions that wrongly use SMBHSTCTRL as the register for the data being transfered. The correct register is SMBHSTDAT0. Include file smbus.h should only be used by sm.c, smbus.c and smbus_spd.c. BUG=b:62200225 Change-Id: Ibd55560c95b6752652a4f255b04198e7a4e77d05 Signed-off-by: Richard Spiegel <richard.spiegel@silverbackltd.com> Reviewed-on: https://review.coreboot.org/21887 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Martin Roth <martinroth@google.com> Reviewed-by: Marc Jones <marc@marcjonesconsulting.com>
Diffstat (limited to 'src/soc/amd/stoneyridge/smbus_spd.c')
-rw-r--r--src/soc/amd/stoneyridge/smbus_spd.c120
1 files changed, 34 insertions, 86 deletions
diff --git a/src/soc/amd/stoneyridge/smbus_spd.c b/src/soc/amd/stoneyridge/smbus_spd.c
index 605f8da78e..a2763357f4 100644
--- a/src/soc/amd/stoneyridge/smbus_spd.c
+++ b/src/soc/amd/stoneyridge/smbus_spd.c
@@ -24,101 +24,49 @@
#include <dimmSpd.h>
/*
- * readSmbusByteData - read a single SPD byte from any offset
- */
-static int readSmbusByteData(int iobase, int address, char *buffer, int offset)
-{
- unsigned int status;
- UINT64 limit;
-
- address |= 1; // set read bit
-
- __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 + SMBHSTSTAT);
- if (__rdtsc() > limit)
- break;
- if ((status & SMBHST_STAT_INTERRUPT) == 0)
- continue; // SMBusInterrupt not set, keep waiting
- if ((status & SMBHST_STAT_BUSY) == SMBHST_STAT_BUSY)
- continue; // HostBusy set, keep waiting
- break;
- }
-
- 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
- */
-static int readSmbusByte(int iobase, int address, char *buffer)
-{
- unsigned int status;
- UINT64 limit;
-
- __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 + SMBHSTSTAT);
- if (__rdtsc() > limit)
- break;
- if ((status & SMBHST_STAT_INTERRUPT) == 0)
- continue; // SMBusInterrupt not set, keep waiting
- if ((status & SMBHST_STAT_BUSY) == SMBHST_STAT_BUSY)
- continue; // HostBusy set, keep waiting
- break;
- }
-
- 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
* sending offset for every byte.
* Reads 128 bytes in 7-8 ms at 400 KHz.
*/
-static int readspd(int iobase, int SmbusSlaveAddress, char *buffer, int count)
+static int readspd(uint16_t iobase, int SmbusSlaveAddress,
+ char *buffer, size_t count)
{
- int index, error;
+ u8 dev_addr;
+ size_t index;
+ int error;
+ char *pbuf = buffer;
printk(BIOS_SPEW, "-------------READING SPD-----------\n");
printk(BIOS_SPEW, "iobase: 0x%08X, SmbusSlave: 0x%08X, count: %d\n",
- iobase, SmbusSlaveAddress, count);
+ iobase, SmbusSlaveAddress, (int)count);
- /* read the first byte using offset zero */
- error = readSmbusByteData(iobase, SmbusSlaveAddress, buffer, 0);
+ /*
+ * Convert received device address to the format accepted by
+ * do_smbus_read_byte and do_smbus_recv_byte.
+ */
+ dev_addr = (SmbusSlaveAddress >> 1);
- if (error) {
+ /* Read the first SPD byte */
+ error = do_smbus_read_byte(iobase, dev_addr, 0);
+ if (error < 0) {
printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n");
return error;
+ } else {
+ *pbuf = (char) error;
+ pbuf++;
}
- /* read the remaining bytes using auto-increment for speed */
- for (index = 1; index < count; index++) {
- error = readSmbusByte(iobase, SmbusSlaveAddress,
- &buffer[index]);
- if (error) {
+ /* Read the remaining SPD bytes using do_smbus_recv_byte for speed */
+ for (index = 1 ; index < count ; index++) {
+ error = do_smbus_recv_byte(iobase, dev_addr);
+ if (error < 0) {
printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n");
return error;
+ } else {
+ *pbuf = (char) error;
+ pbuf++;
}
}
printk(BIOS_SPEW, "\n");
@@ -129,22 +77,22 @@ static int readspd(int iobase, int SmbusSlaveAddress, char *buffer, int count)
static void writePmReg(int reg, int data)
{
- __outbyte(PM_INDEX, reg);
- __outbyte(PM_DATA, data);
+ outb(reg, PM_INDEX);
+ outb(data, PM_DATA);
}
-static void setupFch(int ioBase)
+static void setupFch(uint16_t 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 + SMBTIMING, 66000000 / 400000 / 4);
+ writePmReg(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_readSpd(int spdAddress, char *buf, size_t len)
{
- int ioBase = SMB_BASE_ADDR;
+ uint16_t ioBase = SMB_BASE_ADDR;
setupFch(ioBase);
return readspd(ioBase, spdAddress, buf, len);
}