here I thought it was built as part of checkin.
If I do a clean pull, and try to build the qemu target, I hit a lot of
bad issues with ACPI RESUME being misconfigured. Anyone else seeing
this?
ron
Am 2013-01-24 11:26, schrieb WANG Siyuan:
> Hi, everyone
> My coreboot can boot Windows 7 with VGA driver but cannot boot
> Windows
> 7 with AMD driver. The monitor is black but system is still alive.
> I can connect it by Remote Desktop. There is no dump files generated.
> I try to use WinDbg to debug. Now, I know how to debug a process and
> setup a server-client environment, But how to debug Graphic Driver
> without source code?
In my cases, the problem usually showed by not booting into anything
useful. Since you have remote desktop, consider checking the event log.
I collected some information on how to setup debuggable Windows install
media on http://www.coreboot.org/Debugging#Windows_7_USB - install media
has different characteristics, which might help with tracking down the
issue - or not.
For using WinDbg itself there are various blogs out there detailling
how to use it. Feel free to add links to useful articles to the above
document.
Patrick
Martin Roth (martin.roth(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2190
-gerrit
commit 6bb46f34981a6a874c9ffaba5d9701faf26fdadf
Author: Martin Roth <martin.roth(a)se-eng.com>
Date: Sun Jan 20 10:38:58 2013 -0700
Fam15tn: Move SPD read from mainboards into wrapper
Continuing with the mainboard cleanup for F15tn, move the functions
to read the SPD from the mainboards for Thatcher and Parmer into the
wrapper for the northbridge/amd/agesa/family15tn.
Move the SPD address customization for the mainboard into the
devicetree.cb file.
Unrelated side note - Porting.h has an un-closed #pragma pack(1)
that can cause confusing side-effects. AGESA's structures all
use this, but coreboot's don't. Be sure to include the coreboot
.h files BEFORE Porting.h is included, not after.
I have, of course, actually tested this fix.
Change-Id: I89cdd225be61f60c6b8e7020e6f8b879983bbd96
Signed-off-by: Martin Roth <martin.roth(a)se-eng.com>
---
src/mainboard/amd/parmer/BiosCallOuts.c | 15 +-
src/mainboard/amd/parmer/BiosCallOuts.h | 3 -
src/mainboard/amd/parmer/Makefile.inc | 2 -
src/mainboard/amd/parmer/devicetree.cb | 16 +-
src/mainboard/amd/parmer/dimmSpd.c | 164 --------------------
src/mainboard/amd/parmer/dimmSpd.h | 59 --------
src/mainboard/amd/thatcher/BiosCallOuts.c | 15 +-
src/mainboard/amd/thatcher/BiosCallOuts.h | 3 -
src/mainboard/amd/thatcher/Makefile.inc | 2 -
src/mainboard/amd/thatcher/devicetree.cb | 16 +-
src/mainboard/amd/thatcher/dimmSpd.c | 166 ---------------------
src/mainboard/amd/thatcher/dimmSpd.h | 59 --------
src/northbridge/amd/agesa/family15tn/Makefile.inc | 3 +-
src/northbridge/amd/agesa/family15tn/chip.h | 29 ++++
src/northbridge/amd/agesa/family15tn/dimmSpd.c | 160 ++++++++++++++++++++
src/northbridge/amd/agesa/family15tn/dimmSpd.h | 56 +++++++
.../amd/agesa/family15tn/fam15tn_callouts.c | 8 +
.../amd/agesa/family15tn/fam15tn_callouts.h | 1 +
18 files changed, 278 insertions(+), 499 deletions(-)
diff --git a/src/mainboard/amd/parmer/BiosCallOuts.c b/src/mainboard/amd/parmer/BiosCallOuts.c
index 8bfde14..c3e57c8 100644
--- a/src/mainboard/amd/parmer/BiosCallOuts.c
+++ b/src/mainboard/amd/parmer/BiosCallOuts.c
@@ -19,7 +19,6 @@
#include "agesawrapper.h"
#include "amdlib.h"
-#include "dimmSpd.h"
#include "BiosCallOuts.h"
#include "Ids.h"
#include "OptionsIds.h"
@@ -33,10 +32,10 @@ STATIC CONST BIOS_CALLOUT_STRUCT BiosCallouts[] =
{AGESA_DEALLOCATE_BUFFER, fam15tn_DeallocateBuffer },
{AGESA_DO_RESET, fam15tn_Reset },
{AGESA_LOCATE_BUFFER, fam15tn_LocateBuffer },
- {AGESA_READ_SPD, BiosReadSpd },
+ {AGESA_READ_SPD, fam15tn_ReadSpd },
{AGESA_READ_SPD_RECOVERY, fam15tn_DefaultRet },
- {AGESA_RUNFUNC_ONAP, fam15tn_RunFuncOnAp },
- {AGESA_GET_IDS_INIT_DATA, fam15tn_GetIdsInitData },
+ {AGESA_RUNFUNC_ONAP, fam15tn_RunFuncOnAp },
+ {AGESA_GET_IDS_INIT_DATA, fam15tn_GetIdsInitData },
{AGESA_HOOKBEFORE_DQS_TRAINING, fam15tn_HookBeforeDQSTraining },
{AGESA_HOOKBEFORE_EXIT_SELF_REF, fam15tn_HookBeforeExitSelfRefresh },
{AGESA_FCH_OEM_CALLOUT, Fch_Oem_config },
@@ -63,14 +62,6 @@ AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
return CalloutStatus;
}
-AGESA_STATUS BiosReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
-{
- AGESA_STATUS Status;
- Status = AmdMemoryReadSPD (Func, Data, ConfigPtr);
-
- return Status;
-}
-
/**
* AMD Parmer Platform ALC272 Verb Table
*/
diff --git a/src/mainboard/amd/parmer/BiosCallOuts.h b/src/mainboard/amd/parmer/BiosCallOuts.h
index 66db8cd..d42683e 100644
--- a/src/mainboard/amd/parmer/BiosCallOuts.h
+++ b/src/mainboard/amd/parmer/BiosCallOuts.h
@@ -25,9 +25,6 @@
/* CALLOUT Initialization */
AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
-/* AGESA ADVANCED CALLOUTS - MEMORY */
-AGESA_STATUS BiosReadSpd (UINT32 Func,UINT32 Data,VOID *ConfigPtr);
-
/* FCH OEM Config*/
AGESA_STATUS Fch_Oem_config(UINT32 Func, UINT32 FchData, VOID *ConfigPtr);
diff --git a/src/mainboard/amd/parmer/Makefile.inc b/src/mainboard/amd/parmer/Makefile.inc
index de3163d..a83297a 100644
--- a/src/mainboard/amd/parmer/Makefile.inc
+++ b/src/mainboard/amd/parmer/Makefile.inc
@@ -19,12 +19,10 @@
romstage-y += buildOpts.c
romstage-y += agesawrapper.c
-romstage-y += dimmSpd.c
romstage-y += BiosCallOuts.c
romstage-y += PlatformGnbPcie.c
ramstage-y += buildOpts.c
ramstage-y += agesawrapper.c
-ramstage-y += dimmSpd.c
ramstage-y += BiosCallOuts.c
ramstage-y += PlatformGnbPcie.c
diff --git a/src/mainboard/amd/parmer/devicetree.cb b/src/mainboard/amd/parmer/devicetree.cb
index 3e3e371..9dbdc98 100644
--- a/src/mainboard/amd/parmer/devicetree.cb
+++ b/src/mainboard/amd/parmer/devicetree.cb
@@ -51,16 +51,10 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 13.2 on end # USB
device pci 14.0 on # SMBUS
chip drivers/generic/generic #dimm 0
- device i2c 50 on end
+ device i2c 50 on end # 7-bit SPD address
end
chip drivers/generic/generic #dimm 1
- device i2c 51 on end
- end
- chip drivers/generic/generic #dimm 0-1-0
- device i2c 52 on end
- end
- chip drivers/generic/generic #dimm 0-1-1
- device i2c 53 on end
+ device i2c 51 on end # 7-bit SPD address
end
end # SM
device pci 14.1 on end # IDE 0x439c
@@ -85,6 +79,12 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 18.4 on end
device pci 18.5 on end
+ register "spdAddrLookup" = "
+ {
+ { {0xA0, 0x00}, {0xA2, 0x00}, }, // socket 0 - Channel 0 & 1 - 8-bit SPD addresses
+ { {0x00, 0x00}, {0x00, 0x00}, }, // socket 1 - Channel 0 & 1 - 8-bit SPD addresses
+ }"
+
end #chip northbridge/amd/agesa/family15tn # CPU side of HT root complex
end #pci_domain
end #chip northbridge/amd/agesa/family15tn/root_complex
diff --git a/src/mainboard/amd/parmer/dimmSpd.c b/src/mainboard/amd/parmer/dimmSpd.c
deleted file mode 100644
index 576de7e..0000000
--- a/src/mainboard/amd/parmer/dimmSpd.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "Porting.h"
-#include "AGESA.h"
-#include "amdlib.h"
-#include "dimmSpd.h"
-
-#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
-
-/*#pragma optimize ("", off) // for source level debug
- *---------------------------------------------------------------------------
- *
- * SPD address table - porting required
- */
-
-static const UINT8 spdAddressLookup [2] [2] [4] = // socket, channel, dimm
-{
- // socket 0
- {
- {0xA0, 0x00}, // channel 0 dimms
- {0xA2, 0x00}, // channel 1 dimms
- },
- // socket 1
- {
- {0x00, 0x00}, // channel 0 dimms
- {0x00, 0x00}, // channel 1 dimms
- },
-};
-
-/*-----------------------------------------------------------------------------
- *
- * 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 + 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
-
- // time limit to avoid hanging for unexpected error status (should never happen)
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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 + 0, 0xFF); // clear error status
- __outbyte (iobase + 2, 0x44); // read command
-
- // time limit to avoid hanging for unexpected error status
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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)
-{
- int index, error;
-
- /* read the first byte using offset zero */
- error = readSmbusByteData (iobase, SmbusSlaveAddress, buffer, 0);
- if (error) return error;
-
- /* read the remaining bytes using auto-increment for speed */
- for (index = 1; index < count; index++)
- {
- error = readSmbusByte (iobase, SmbusSlaveAddress, &buffer [index]);
- if (error) return error;
- }
-
- return 0;
-}
-
-static void writePmReg (int reg, int data)
-{
- __outbyte (0xCD6, reg);
- __outbyte (0xCD7, data);
-}
-
-static void setupFch (int ioBase)
-{
- writePmReg (0x2D, ioBase >> 8);
- writePmReg (0x2C, ioBase | 1);
- __outbyte (ioBase + 0x0E, 66000000 / 400000 / 4); // set SMBus clock to 400 KHz
-}
-
-AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
-{
- int spdAddress, ioBase;
-
- if (info->SocketId >= DIMENSION (spdAddressLookup )) return AGESA_ERROR;
- if (info->MemChannelId >= DIMENSION (spdAddressLookup[0] )) return AGESA_ERROR;
- if (info->DimmId >= DIMENSION (spdAddressLookup[0][0])) return AGESA_ERROR;
-
- spdAddress = spdAddressLookup [info->SocketId] [info->MemChannelId] [info->DimmId];
- if (spdAddress == 0) return AGESA_ERROR;
- ioBase = 0xB00;
- setupFch (ioBase);
- return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
-}
diff --git a/src/mainboard/amd/parmer/dimmSpd.h b/src/mainboard/amd/parmer/dimmSpd.h
deleted file mode 100644
index c19cecc..0000000
--- a/src/mainboard/amd/parmer/dimmSpd.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*----------------------------------------------------------------------------------------
- * M O D U L E S U S E D
- *----------------------------------------------------------------------------------------
- */
-
-#ifndef _DIMMSPD_H_
-#define _DIMMSPD_H_
-
-#include "Porting.h"
-#include "AGESA.h"
-
-/*----------------------------------------------------------------------------------------
- * D E F I N I T I O N S A N D M A C R O S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * T Y P E D E F S A N D S T R U C T U R E S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * P R O T O T Y P E S O F L O C A L F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * E X P O R T E D F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-AGESA_STATUS
-AmdMemoryReadSPD (IN UINT32 Func, IN UINT32 Data, IN OUT AGESA_READ_SPD_PARAMS *SpdData);
-
-/*---------------------------------------------------------------------------------------
- * L O C A L F U N C T I O N S
- *---------------------------------------------------------------------------------------
- */
-
-#endif
diff --git a/src/mainboard/amd/thatcher/BiosCallOuts.c b/src/mainboard/amd/thatcher/BiosCallOuts.c
index b82c56b..359ae78 100644
--- a/src/mainboard/amd/thatcher/BiosCallOuts.c
+++ b/src/mainboard/amd/thatcher/BiosCallOuts.c
@@ -19,7 +19,6 @@
#include "agesawrapper.h"
#include "amdlib.h"
-#include "dimmSpd.h"
#include "BiosCallOuts.h"
#include "Ids.h"
#include "OptionsIds.h"
@@ -33,10 +32,10 @@ STATIC CONST BIOS_CALLOUT_STRUCT BiosCallouts[] =
{AGESA_DEALLOCATE_BUFFER, fam15tn_DeallocateBuffer },
{AGESA_DO_RESET, fam15tn_Reset },
{AGESA_LOCATE_BUFFER, fam15tn_LocateBuffer },
- {AGESA_READ_SPD, BiosReadSpd },
+ {AGESA_READ_SPD, fam15tn_ReadSpd },
{AGESA_READ_SPD_RECOVERY, fam15tn_DefaultRet },
- {AGESA_RUNFUNC_ONAP, fam15tn_RunFuncOnAp },
- {AGESA_GET_IDS_INIT_DATA, fam15tn_GetIdsInitData },
+ {AGESA_RUNFUNC_ONAP, fam15tn_RunFuncOnAp },
+ {AGESA_GET_IDS_INIT_DATA, fam15tn_GetIdsInitData },
{AGESA_HOOKBEFORE_DQS_TRAINING, fam15tn_HookBeforeDQSTraining },
{AGESA_HOOKBEFORE_EXIT_SELF_REF, fam15tn_HookBeforeExitSelfRefresh },
{AGESA_FCH_OEM_CALLOUT, Fch_Oem_config },
@@ -63,14 +62,6 @@ AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
return CalloutStatus;
}
-AGESA_STATUS BiosReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
-{
- AGESA_STATUS Status;
- Status = AmdMemoryReadSPD (Func, Data, ConfigPtr);
-
- return Status;
-}
-
/**
* AMD Thatcher Platform ALC272 Verb Table
*/
diff --git a/src/mainboard/amd/thatcher/BiosCallOuts.h b/src/mainboard/amd/thatcher/BiosCallOuts.h
index 66db8cd..d42683e 100644
--- a/src/mainboard/amd/thatcher/BiosCallOuts.h
+++ b/src/mainboard/amd/thatcher/BiosCallOuts.h
@@ -25,9 +25,6 @@
/* CALLOUT Initialization */
AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
-/* AGESA ADVANCED CALLOUTS - MEMORY */
-AGESA_STATUS BiosReadSpd (UINT32 Func,UINT32 Data,VOID *ConfigPtr);
-
/* FCH OEM Config*/
AGESA_STATUS Fch_Oem_config(UINT32 Func, UINT32 FchData, VOID *ConfigPtr);
diff --git a/src/mainboard/amd/thatcher/Makefile.inc b/src/mainboard/amd/thatcher/Makefile.inc
index de3163d..a83297a 100644
--- a/src/mainboard/amd/thatcher/Makefile.inc
+++ b/src/mainboard/amd/thatcher/Makefile.inc
@@ -19,12 +19,10 @@
romstage-y += buildOpts.c
romstage-y += agesawrapper.c
-romstage-y += dimmSpd.c
romstage-y += BiosCallOuts.c
romstage-y += PlatformGnbPcie.c
ramstage-y += buildOpts.c
ramstage-y += agesawrapper.c
-ramstage-y += dimmSpd.c
ramstage-y += BiosCallOuts.c
ramstage-y += PlatformGnbPcie.c
diff --git a/src/mainboard/amd/thatcher/devicetree.cb b/src/mainboard/amd/thatcher/devicetree.cb
index f6459c1..ccb8b58 100644
--- a/src/mainboard/amd/thatcher/devicetree.cb
+++ b/src/mainboard/amd/thatcher/devicetree.cb
@@ -51,16 +51,10 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 13.2 on end # USB
device pci 14.0 on # SMBUS
chip drivers/generic/generic #dimm 0
- device i2c 50 on end
+ device i2c 50 on end # 7-bit SPD address
end
chip drivers/generic/generic #dimm 1
- device i2c 51 on end
- end
- chip drivers/generic/generic #dimm 0-1-0
- device i2c 52 on end
- end
- chip drivers/generic/generic #dimm 0-1-1
- device i2c 53 on end
+ device i2c 51 on end # 7-bit SPD address
end
end # SM
device pci 14.1 on end # IDE 0x439c
@@ -100,6 +94,12 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 18.4 on end
device pci 18.5 on end
+ register "spdAddrLookup" = "
+ {
+ { {0xA0, 0x00}, {0xA2, 0x00}, }, // socket 0 - Channel 0 & 1 - 8-bit SPD addresses
+ { {0x00, 0x00}, {0x00, 0x00}, }, // socket 1 - Channel 0 & 1 - 8-bit SPD addresses
+ }"
+
end #chip northbridge/amd/agesa/family15tn # CPU side of HT root complex
end #pci_domain
end #chip northbridge/amd/agesa/family15tn/root_complex
diff --git a/src/mainboard/amd/thatcher/dimmSpd.c b/src/mainboard/amd/thatcher/dimmSpd.c
deleted file mode 100644
index 29d6a29..0000000
--- a/src/mainboard/amd/thatcher/dimmSpd.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "Porting.h"
-#include "AGESA.h"
-#include "amdlib.h"
-#include "dimmSpd.h"
-
-#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
-
-/*#pragma optimize ("", off) // for source level debug
- *---------------------------------------------------------------------------
- *
- * SPD address table - porting required
- */
-
-static const UINT8 spdAddressLookup [2] [2] [4] = // socket, channel, dimm
-{
- // socket 0
- {
- {0xA0, 0x00}, // channel 0 dimms
- {0xA2, 0x00}, // channel 1 dimms
- },
- // socket 1
- {
- {0x00, 0x00}, // channel 0 dimms
- {0x00, 0x00}, // channel 1 dimms
- },
-};
-
-/*-----------------------------------------------------------------------------
- *
- * 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 + 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
-
- // time limit to avoid hanging for unexpected error status (should never happen)
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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 + 0, 0xFF); // clear error status
- __outbyte (iobase + 2, 0x44); // read command
-
- // time limit to avoid hanging for unexpected error status
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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)
-{
- int index, error;
-
- /* read the first byte using offset zero */
- error = readSmbusByteData (iobase, SmbusSlaveAddress, buffer, 0);
- if (error) return error;
-
- /* read the remaining bytes using auto-increment for speed */
- for (index = 1; index < count; index++)
- {
- error = readSmbusByte (iobase, SmbusSlaveAddress, &buffer [index]);
- if (error) return error;
- }
-
- return 0;
-}
-
-static void writePmReg (int reg, int data)
-{
- __outbyte (0xCD6, reg);
- __outbyte (0xCD7, data);
-}
-
-static void setupFch (int ioBase)
-{
- writePmReg (0x2D, ioBase >> 8);
- writePmReg (0x2C, ioBase | 1);
- //writePmReg (0x29, 0x80);
- //writePmReg (0x28, 0x61);
- __outbyte (ioBase + 0x0E, 66000000 / 400000 / 4); // set SMBus clock to 400 KHz
-}
-
-AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
-{
- int spdAddress, ioBase;
-
- if (info->SocketId >= DIMENSION (spdAddressLookup )) return AGESA_ERROR;
- if (info->MemChannelId >= DIMENSION (spdAddressLookup[0] )) return AGESA_ERROR;
- if (info->DimmId >= DIMENSION (spdAddressLookup[0][0])) return AGESA_ERROR;
-
- spdAddress = spdAddressLookup [info->SocketId] [info->MemChannelId] [info->DimmId];
- if (spdAddress == 0) return AGESA_ERROR;
- ioBase = 0xB00;
- setupFch (ioBase);
- return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
-}
diff --git a/src/mainboard/amd/thatcher/dimmSpd.h b/src/mainboard/amd/thatcher/dimmSpd.h
deleted file mode 100644
index c19cecc..0000000
--- a/src/mainboard/amd/thatcher/dimmSpd.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*----------------------------------------------------------------------------------------
- * M O D U L E S U S E D
- *----------------------------------------------------------------------------------------
- */
-
-#ifndef _DIMMSPD_H_
-#define _DIMMSPD_H_
-
-#include "Porting.h"
-#include "AGESA.h"
-
-/*----------------------------------------------------------------------------------------
- * D E F I N I T I O N S A N D M A C R O S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * T Y P E D E F S A N D S T R U C T U R E S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * P R O T O T Y P E S O F L O C A L F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * E X P O R T E D F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-AGESA_STATUS
-AmdMemoryReadSPD (IN UINT32 Func, IN UINT32 Data, IN OUT AGESA_READ_SPD_PARAMS *SpdData);
-
-/*---------------------------------------------------------------------------------------
- * L O C A L F U N C T I O N S
- *---------------------------------------------------------------------------------------
- */
-
-#endif
diff --git a/src/northbridge/amd/agesa/family15tn/Makefile.inc b/src/northbridge/amd/agesa/family15tn/Makefile.inc
index b0cf7ff..5bc7f6c 100644
--- a/src/northbridge/amd/agesa/family15tn/Makefile.inc
+++ b/src/northbridge/amd/agesa/family15tn/Makefile.inc
@@ -18,7 +18,8 @@
#
romstage-y += fam15tn_callouts.c
+romstage-y += dimmSpd.c
ramstage-y += northbridge.c
ramstage-y += fam15tn_callouts.c
-
+ramstage-y += dimmSpd.c
diff --git a/src/northbridge/amd/agesa/family15tn/chip.h b/src/northbridge/amd/agesa/family15tn/chip.h
new file mode 100644
index 0000000..56c3776
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15tn/chip.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _AGESA_FAM15TN_CHIP_H_
+#define _AGESA_FAM15TN_CHIP_H_
+
+struct northbridge_amd_agesa_family15tn_config
+{
+ u8 spdAddrLookup[2][2][4];
+
+};
+
+#endif
\ No newline at end of file
diff --git a/src/northbridge/amd/agesa/family15tn/dimmSpd.c b/src/northbridge/amd/agesa/family15tn/dimmSpd.c
new file mode 100644
index 0000000..8b62a39
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15tn/dimmSpd.c
@@ -0,0 +1,160 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <device/pci_def.h>
+#include <device/device.h>
+
+/* warning: Porting.h includes an open #pragma pack(1) */
+#include "Porting.h"
+#include "AGESA.h"
+#include "amdlib.h"
+#include "dimmSpd.h"
+#include "chip.h"
+
+
+#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
+
+/*-----------------------------------------------------------------------------
+ *
+ * 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 + 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
+
+ // time limit to avoid hanging for unexpected error status (should never happen)
+ limit = __rdtsc () + 2000000000 / 10;
+ for (;;)
+ {
+ status = __inbyte (iobase);
+ if (__rdtsc () > limit) break;
+ if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
+ if ((status & 1) == 1) continue; // HostBusy set, keep waiting
+ break;
+ }
+
+ buffer [0] = __inbyte (iobase + 5);
+ if (status == 2) status = 0; // check for 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 + 0, 0xFF); // clear error status
+ __outbyte (iobase + 2, 0x44); // read command
+
+ // time limit to avoid hanging for unexpected error status
+ limit = __rdtsc () + 2000000000 / 10;
+ for (;;)
+ {
+ status = __inbyte (iobase);
+ if (__rdtsc () > limit) break;
+ if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
+ if ((status & 1) == 1) continue; // HostBusy set, keep waiting
+ break;
+ }
+
+ buffer [0] = __inbyte (iobase + 5);
+ if (status == 2) status = 0; // check for 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)
+{
+ int index, error;
+
+ /* read the first byte using offset zero */
+ error = readSmbusByteData (iobase, SmbusSlaveAddress, buffer, 0);
+ if (error) return error;
+
+ /* read the remaining bytes using auto-increment for speed */
+ for (index = 1; index < count; index++)
+ {
+ error = readSmbusByte (iobase, SmbusSlaveAddress, &buffer [index]);
+ if (error) return error;
+ }
+
+ return 0;
+}
+
+static void writePmReg (int reg, int data)
+{
+ __outbyte (0xCD6, reg);
+ __outbyte (0xCD7, data);
+}
+
+static void setupFch (int ioBase)
+{
+ writePmReg (0x2D, ioBase >> 8);
+ writePmReg (0x2C, ioBase | 1);
+ __outbyte (ioBase + 0x0E, 66000000 / 400000 / 4); // set SMBus clock to 400 KHz
+}
+
+AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
+{
+ int spdAddress, ioBase;
+ ROMSTAGE_CONST struct device *dev = dev_find_slot(0, PCI_DEVFN(0x18, 2));
+ ROMSTAGE_CONST struct northbridge_amd_agesa_family15tn_config *config = dev->chip_info;
+
+ if ((dev == 0) || (config == 0))
+ return AGESA_ERROR;
+
+ if (info->SocketId >= DIMENSION(config->spdAddrLookup ))
+ return AGESA_ERROR;
+ if (info->MemChannelId >= DIMENSION(config->spdAddrLookup[0] ))
+ return AGESA_ERROR;
+ if (info->DimmId >= DIMENSION(config->spdAddrLookup[0][0]))
+ return AGESA_ERROR;
+
+ spdAddress = config->spdAddrLookup
+ [info->SocketId] [info->MemChannelId] [info->DimmId];
+
+ if (spdAddress == 0) return AGESA_ERROR;
+ ioBase = 0xB00;
+ setupFch (ioBase);
+ return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
+}
diff --git a/src/northbridge/amd/agesa/family15tn/dimmSpd.h b/src/northbridge/amd/agesa/family15tn/dimmSpd.h
new file mode 100644
index 0000000..116eeb0
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15tn/dimmSpd.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+
+#ifndef _DIMMSPD_H_
+#define _DIMMSPD_H_
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+AGESA_STATUS
+AmdMemoryReadSPD (IN UINT32 Func, IN UINT32 Data, IN OUT AGESA_READ_SPD_PARAMS *SpdData);
+
+/*---------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *---------------------------------------------------------------------------------------
+ */
+
+#endif
diff --git a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
index 7c3b0ac..35aae91 100644
--- a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
+++ b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
@@ -24,6 +24,7 @@
#include "heapManager.h"
#include "FchPlatform.h"
#include "cbfs.h"
+#include "dimmSpd.h"
#include "fam15tn_callouts.h"
AGESA_STATUS fam15tn_AllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
@@ -403,3 +404,10 @@ AGESA_STATUS fam15tn_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *Con
return pVbiosImageInfo->ImagePtr == NULL ? AGESA_WARNING : AGESA_SUCCESS;
}
+AGESA_STATUS fam15tn_ReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+ AGESA_STATUS Status;
+ Status = AmdMemoryReadSPD (Func, Data, ConfigPtr);
+
+ return Status;
+}
diff --git a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h
index 74c7bf3..eb80a63 100644
--- a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h
+++ b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h
@@ -49,5 +49,6 @@ AGESA_STATUS fam15tn_HookBeforeDQSTraining (UINT32 Func, UINT32 Data, VOID *Conf
AGESA_STATUS fam15tn_HookBeforeExitSelfRefresh (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
AGESA_STATUS fam15tn_DefaultRet (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
AGESA_STATUS fam15tn_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt);
+AGESA_STATUS fam15tn_ReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
#endif /* CALLOUTS_AMD_AGESA_FAM15TN_H */
Martin Roth (martin.roth(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2190
-gerrit
commit 0c381b1e55039bffd0a21ee4e07aa22e6d454d4b
Author: Martin Roth <martin.roth(a)se-eng.com>
Date: Sun Jan 20 10:38:58 2013 -0700
Fam15tn: Move SPD read from mainboards into wrapper
Continuing with the mainboard cleanup for F15tn, move the functions
to read the SPD from the mainboards for thatcher and parmerinto the
wrapper for the northbridge/amd/agesa/family15tn.
Move the SPD address customization for the mainboard into the
devicetree.cb file.
Unrelated side note - Porting.h has an un-closed #pragma pack(1)
that can cause confusing side-effects. AGESA's structures all
use this, but coreboot's don't. Be sure to include the coreboot
.h files BEFORE Porting.h is included, not after.
Change-Id: I89cdd225be61f60c6b8e7020e6f8b879983bbd96
Signed-off-by: Martin Roth <martin.roth(a)se-eng.com>
---
src/mainboard/amd/parmer/BiosCallOuts.c | 11 +-
src/mainboard/amd/parmer/BiosCallOuts.h | 3 -
src/mainboard/amd/parmer/Makefile.inc | 2 -
src/mainboard/amd/parmer/devicetree.cb | 16 +-
src/mainboard/amd/parmer/dimmSpd.c | 164 --------------------
src/mainboard/amd/parmer/dimmSpd.h | 59 --------
src/mainboard/amd/thatcher/BiosCallOuts.c | 11 +-
src/mainboard/amd/thatcher/BiosCallOuts.h | 3 -
src/mainboard/amd/thatcher/Makefile.inc | 2 -
src/mainboard/amd/thatcher/devicetree.cb | 16 +-
src/mainboard/amd/thatcher/dimmSpd.c | 166 ---------------------
src/mainboard/amd/thatcher/dimmSpd.h | 59 --------
src/northbridge/amd/agesa/family15tn/Makefile.inc | 3 +-
src/northbridge/amd/agesa/family15tn/chip.h | 29 ++++
src/northbridge/amd/agesa/family15tn/dimmSpd.c | 161 ++++++++++++++++++++
src/northbridge/amd/agesa/family15tn/dimmSpd.h | 56 +++++++
.../amd/agesa/family15tn/fam15tn_callouts.c | 8 +
.../amd/agesa/family15tn/fam15tn_callouts.h | 1 +
18 files changed, 275 insertions(+), 495 deletions(-)
diff --git a/src/mainboard/amd/parmer/BiosCallOuts.c b/src/mainboard/amd/parmer/BiosCallOuts.c
index 8bfde14..7d79881 100644
--- a/src/mainboard/amd/parmer/BiosCallOuts.c
+++ b/src/mainboard/amd/parmer/BiosCallOuts.c
@@ -19,7 +19,6 @@
#include "agesawrapper.h"
#include "amdlib.h"
-#include "dimmSpd.h"
#include "BiosCallOuts.h"
#include "Ids.h"
#include "OptionsIds.h"
@@ -33,7 +32,7 @@ STATIC CONST BIOS_CALLOUT_STRUCT BiosCallouts[] =
{AGESA_DEALLOCATE_BUFFER, fam15tn_DeallocateBuffer },
{AGESA_DO_RESET, fam15tn_Reset },
{AGESA_LOCATE_BUFFER, fam15tn_LocateBuffer },
- {AGESA_READ_SPD, BiosReadSpd },
+ {AGESA_READ_SPD, fam15tn_ReadSpd },
{AGESA_READ_SPD_RECOVERY, fam15tn_DefaultRet },
{AGESA_RUNFUNC_ONAP, fam15tn_RunFuncOnAp },
{AGESA_GET_IDS_INIT_DATA, fam15tn_GetIdsInitData },
@@ -63,14 +62,6 @@ AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
return CalloutStatus;
}
-AGESA_STATUS BiosReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
-{
- AGESA_STATUS Status;
- Status = AmdMemoryReadSPD (Func, Data, ConfigPtr);
-
- return Status;
-}
-
/**
* AMD Parmer Platform ALC272 Verb Table
*/
diff --git a/src/mainboard/amd/parmer/BiosCallOuts.h b/src/mainboard/amd/parmer/BiosCallOuts.h
index 66db8cd..d42683e 100644
--- a/src/mainboard/amd/parmer/BiosCallOuts.h
+++ b/src/mainboard/amd/parmer/BiosCallOuts.h
@@ -25,9 +25,6 @@
/* CALLOUT Initialization */
AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
-/* AGESA ADVANCED CALLOUTS - MEMORY */
-AGESA_STATUS BiosReadSpd (UINT32 Func,UINT32 Data,VOID *ConfigPtr);
-
/* FCH OEM Config*/
AGESA_STATUS Fch_Oem_config(UINT32 Func, UINT32 FchData, VOID *ConfigPtr);
diff --git a/src/mainboard/amd/parmer/Makefile.inc b/src/mainboard/amd/parmer/Makefile.inc
index de3163d..a83297a 100644
--- a/src/mainboard/amd/parmer/Makefile.inc
+++ b/src/mainboard/amd/parmer/Makefile.inc
@@ -19,12 +19,10 @@
romstage-y += buildOpts.c
romstage-y += agesawrapper.c
-romstage-y += dimmSpd.c
romstage-y += BiosCallOuts.c
romstage-y += PlatformGnbPcie.c
ramstage-y += buildOpts.c
ramstage-y += agesawrapper.c
-ramstage-y += dimmSpd.c
ramstage-y += BiosCallOuts.c
ramstage-y += PlatformGnbPcie.c
diff --git a/src/mainboard/amd/parmer/devicetree.cb b/src/mainboard/amd/parmer/devicetree.cb
index 3e3e371..9dbdc98 100644
--- a/src/mainboard/amd/parmer/devicetree.cb
+++ b/src/mainboard/amd/parmer/devicetree.cb
@@ -51,16 +51,10 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 13.2 on end # USB
device pci 14.0 on # SMBUS
chip drivers/generic/generic #dimm 0
- device i2c 50 on end
+ device i2c 50 on end # 7-bit SPD address
end
chip drivers/generic/generic #dimm 1
- device i2c 51 on end
- end
- chip drivers/generic/generic #dimm 0-1-0
- device i2c 52 on end
- end
- chip drivers/generic/generic #dimm 0-1-1
- device i2c 53 on end
+ device i2c 51 on end # 7-bit SPD address
end
end # SM
device pci 14.1 on end # IDE 0x439c
@@ -85,6 +79,12 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 18.4 on end
device pci 18.5 on end
+ register "spdAddrLookup" = "
+ {
+ { {0xA0, 0x00}, {0xA2, 0x00}, }, // socket 0 - Channel 0 & 1 - 8-bit SPD addresses
+ { {0x00, 0x00}, {0x00, 0x00}, }, // socket 1 - Channel 0 & 1 - 8-bit SPD addresses
+ }"
+
end #chip northbridge/amd/agesa/family15tn # CPU side of HT root complex
end #pci_domain
end #chip northbridge/amd/agesa/family15tn/root_complex
diff --git a/src/mainboard/amd/parmer/dimmSpd.c b/src/mainboard/amd/parmer/dimmSpd.c
deleted file mode 100644
index 576de7e..0000000
--- a/src/mainboard/amd/parmer/dimmSpd.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "Porting.h"
-#include "AGESA.h"
-#include "amdlib.h"
-#include "dimmSpd.h"
-
-#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
-
-/*#pragma optimize ("", off) // for source level debug
- *---------------------------------------------------------------------------
- *
- * SPD address table - porting required
- */
-
-static const UINT8 spdAddressLookup [2] [2] [4] = // socket, channel, dimm
-{
- // socket 0
- {
- {0xA0, 0x00}, // channel 0 dimms
- {0xA2, 0x00}, // channel 1 dimms
- },
- // socket 1
- {
- {0x00, 0x00}, // channel 0 dimms
- {0x00, 0x00}, // channel 1 dimms
- },
-};
-
-/*-----------------------------------------------------------------------------
- *
- * 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 + 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
-
- // time limit to avoid hanging for unexpected error status (should never happen)
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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 + 0, 0xFF); // clear error status
- __outbyte (iobase + 2, 0x44); // read command
-
- // time limit to avoid hanging for unexpected error status
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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)
-{
- int index, error;
-
- /* read the first byte using offset zero */
- error = readSmbusByteData (iobase, SmbusSlaveAddress, buffer, 0);
- if (error) return error;
-
- /* read the remaining bytes using auto-increment for speed */
- for (index = 1; index < count; index++)
- {
- error = readSmbusByte (iobase, SmbusSlaveAddress, &buffer [index]);
- if (error) return error;
- }
-
- return 0;
-}
-
-static void writePmReg (int reg, int data)
-{
- __outbyte (0xCD6, reg);
- __outbyte (0xCD7, data);
-}
-
-static void setupFch (int ioBase)
-{
- writePmReg (0x2D, ioBase >> 8);
- writePmReg (0x2C, ioBase | 1);
- __outbyte (ioBase + 0x0E, 66000000 / 400000 / 4); // set SMBus clock to 400 KHz
-}
-
-AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
-{
- int spdAddress, ioBase;
-
- if (info->SocketId >= DIMENSION (spdAddressLookup )) return AGESA_ERROR;
- if (info->MemChannelId >= DIMENSION (spdAddressLookup[0] )) return AGESA_ERROR;
- if (info->DimmId >= DIMENSION (spdAddressLookup[0][0])) return AGESA_ERROR;
-
- spdAddress = spdAddressLookup [info->SocketId] [info->MemChannelId] [info->DimmId];
- if (spdAddress == 0) return AGESA_ERROR;
- ioBase = 0xB00;
- setupFch (ioBase);
- return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
-}
diff --git a/src/mainboard/amd/parmer/dimmSpd.h b/src/mainboard/amd/parmer/dimmSpd.h
deleted file mode 100644
index c19cecc..0000000
--- a/src/mainboard/amd/parmer/dimmSpd.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*----------------------------------------------------------------------------------------
- * M O D U L E S U S E D
- *----------------------------------------------------------------------------------------
- */
-
-#ifndef _DIMMSPD_H_
-#define _DIMMSPD_H_
-
-#include "Porting.h"
-#include "AGESA.h"
-
-/*----------------------------------------------------------------------------------------
- * D E F I N I T I O N S A N D M A C R O S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * T Y P E D E F S A N D S T R U C T U R E S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * P R O T O T Y P E S O F L O C A L F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * E X P O R T E D F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-AGESA_STATUS
-AmdMemoryReadSPD (IN UINT32 Func, IN UINT32 Data, IN OUT AGESA_READ_SPD_PARAMS *SpdData);
-
-/*---------------------------------------------------------------------------------------
- * L O C A L F U N C T I O N S
- *---------------------------------------------------------------------------------------
- */
-
-#endif
diff --git a/src/mainboard/amd/thatcher/BiosCallOuts.c b/src/mainboard/amd/thatcher/BiosCallOuts.c
index b82c56b..2d735af 100644
--- a/src/mainboard/amd/thatcher/BiosCallOuts.c
+++ b/src/mainboard/amd/thatcher/BiosCallOuts.c
@@ -19,7 +19,6 @@
#include "agesawrapper.h"
#include "amdlib.h"
-#include "dimmSpd.h"
#include "BiosCallOuts.h"
#include "Ids.h"
#include "OptionsIds.h"
@@ -33,7 +32,7 @@ STATIC CONST BIOS_CALLOUT_STRUCT BiosCallouts[] =
{AGESA_DEALLOCATE_BUFFER, fam15tn_DeallocateBuffer },
{AGESA_DO_RESET, fam15tn_Reset },
{AGESA_LOCATE_BUFFER, fam15tn_LocateBuffer },
- {AGESA_READ_SPD, BiosReadSpd },
+ {AGESA_READ_SPD, fam15tn_ReadSpd },
{AGESA_READ_SPD_RECOVERY, fam15tn_DefaultRet },
{AGESA_RUNFUNC_ONAP, fam15tn_RunFuncOnAp },
{AGESA_GET_IDS_INIT_DATA, fam15tn_GetIdsInitData },
@@ -63,14 +62,6 @@ AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
return CalloutStatus;
}
-AGESA_STATUS BiosReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
-{
- AGESA_STATUS Status;
- Status = AmdMemoryReadSPD (Func, Data, ConfigPtr);
-
- return Status;
-}
-
/**
* AMD Thatcher Platform ALC272 Verb Table
*/
diff --git a/src/mainboard/amd/thatcher/BiosCallOuts.h b/src/mainboard/amd/thatcher/BiosCallOuts.h
index 66db8cd..d42683e 100644
--- a/src/mainboard/amd/thatcher/BiosCallOuts.h
+++ b/src/mainboard/amd/thatcher/BiosCallOuts.h
@@ -25,9 +25,6 @@
/* CALLOUT Initialization */
AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
-/* AGESA ADVANCED CALLOUTS - MEMORY */
-AGESA_STATUS BiosReadSpd (UINT32 Func,UINT32 Data,VOID *ConfigPtr);
-
/* FCH OEM Config*/
AGESA_STATUS Fch_Oem_config(UINT32 Func, UINT32 FchData, VOID *ConfigPtr);
diff --git a/src/mainboard/amd/thatcher/Makefile.inc b/src/mainboard/amd/thatcher/Makefile.inc
index de3163d..a83297a 100644
--- a/src/mainboard/amd/thatcher/Makefile.inc
+++ b/src/mainboard/amd/thatcher/Makefile.inc
@@ -19,12 +19,10 @@
romstage-y += buildOpts.c
romstage-y += agesawrapper.c
-romstage-y += dimmSpd.c
romstage-y += BiosCallOuts.c
romstage-y += PlatformGnbPcie.c
ramstage-y += buildOpts.c
ramstage-y += agesawrapper.c
-ramstage-y += dimmSpd.c
ramstage-y += BiosCallOuts.c
ramstage-y += PlatformGnbPcie.c
diff --git a/src/mainboard/amd/thatcher/devicetree.cb b/src/mainboard/amd/thatcher/devicetree.cb
index f6459c1..ccb8b58 100644
--- a/src/mainboard/amd/thatcher/devicetree.cb
+++ b/src/mainboard/amd/thatcher/devicetree.cb
@@ -51,16 +51,10 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 13.2 on end # USB
device pci 14.0 on # SMBUS
chip drivers/generic/generic #dimm 0
- device i2c 50 on end
+ device i2c 50 on end # 7-bit SPD address
end
chip drivers/generic/generic #dimm 1
- device i2c 51 on end
- end
- chip drivers/generic/generic #dimm 0-1-0
- device i2c 52 on end
- end
- chip drivers/generic/generic #dimm 0-1-1
- device i2c 53 on end
+ device i2c 51 on end # 7-bit SPD address
end
end # SM
device pci 14.1 on end # IDE 0x439c
@@ -100,6 +94,12 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 18.4 on end
device pci 18.5 on end
+ register "spdAddrLookup" = "
+ {
+ { {0xA0, 0x00}, {0xA2, 0x00}, }, // socket 0 - Channel 0 & 1 - 8-bit SPD addresses
+ { {0x00, 0x00}, {0x00, 0x00}, }, // socket 1 - Channel 0 & 1 - 8-bit SPD addresses
+ }"
+
end #chip northbridge/amd/agesa/family15tn # CPU side of HT root complex
end #pci_domain
end #chip northbridge/amd/agesa/family15tn/root_complex
diff --git a/src/mainboard/amd/thatcher/dimmSpd.c b/src/mainboard/amd/thatcher/dimmSpd.c
deleted file mode 100644
index 29d6a29..0000000
--- a/src/mainboard/amd/thatcher/dimmSpd.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "Porting.h"
-#include "AGESA.h"
-#include "amdlib.h"
-#include "dimmSpd.h"
-
-#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
-
-/*#pragma optimize ("", off) // for source level debug
- *---------------------------------------------------------------------------
- *
- * SPD address table - porting required
- */
-
-static const UINT8 spdAddressLookup [2] [2] [4] = // socket, channel, dimm
-{
- // socket 0
- {
- {0xA0, 0x00}, // channel 0 dimms
- {0xA2, 0x00}, // channel 1 dimms
- },
- // socket 1
- {
- {0x00, 0x00}, // channel 0 dimms
- {0x00, 0x00}, // channel 1 dimms
- },
-};
-
-/*-----------------------------------------------------------------------------
- *
- * 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 + 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
-
- // time limit to avoid hanging for unexpected error status (should never happen)
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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 + 0, 0xFF); // clear error status
- __outbyte (iobase + 2, 0x44); // read command
-
- // time limit to avoid hanging for unexpected error status
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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)
-{
- int index, error;
-
- /* read the first byte using offset zero */
- error = readSmbusByteData (iobase, SmbusSlaveAddress, buffer, 0);
- if (error) return error;
-
- /* read the remaining bytes using auto-increment for speed */
- for (index = 1; index < count; index++)
- {
- error = readSmbusByte (iobase, SmbusSlaveAddress, &buffer [index]);
- if (error) return error;
- }
-
- return 0;
-}
-
-static void writePmReg (int reg, int data)
-{
- __outbyte (0xCD6, reg);
- __outbyte (0xCD7, data);
-}
-
-static void setupFch (int ioBase)
-{
- writePmReg (0x2D, ioBase >> 8);
- writePmReg (0x2C, ioBase | 1);
- //writePmReg (0x29, 0x80);
- //writePmReg (0x28, 0x61);
- __outbyte (ioBase + 0x0E, 66000000 / 400000 / 4); // set SMBus clock to 400 KHz
-}
-
-AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
-{
- int spdAddress, ioBase;
-
- if (info->SocketId >= DIMENSION (spdAddressLookup )) return AGESA_ERROR;
- if (info->MemChannelId >= DIMENSION (spdAddressLookup[0] )) return AGESA_ERROR;
- if (info->DimmId >= DIMENSION (spdAddressLookup[0][0])) return AGESA_ERROR;
-
- spdAddress = spdAddressLookup [info->SocketId] [info->MemChannelId] [info->DimmId];
- if (spdAddress == 0) return AGESA_ERROR;
- ioBase = 0xB00;
- setupFch (ioBase);
- return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
-}
diff --git a/src/mainboard/amd/thatcher/dimmSpd.h b/src/mainboard/amd/thatcher/dimmSpd.h
deleted file mode 100644
index c19cecc..0000000
--- a/src/mainboard/amd/thatcher/dimmSpd.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*----------------------------------------------------------------------------------------
- * M O D U L E S U S E D
- *----------------------------------------------------------------------------------------
- */
-
-#ifndef _DIMMSPD_H_
-#define _DIMMSPD_H_
-
-#include "Porting.h"
-#include "AGESA.h"
-
-/*----------------------------------------------------------------------------------------
- * D E F I N I T I O N S A N D M A C R O S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * T Y P E D E F S A N D S T R U C T U R E S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * P R O T O T Y P E S O F L O C A L F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * E X P O R T E D F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-AGESA_STATUS
-AmdMemoryReadSPD (IN UINT32 Func, IN UINT32 Data, IN OUT AGESA_READ_SPD_PARAMS *SpdData);
-
-/*---------------------------------------------------------------------------------------
- * L O C A L F U N C T I O N S
- *---------------------------------------------------------------------------------------
- */
-
-#endif
diff --git a/src/northbridge/amd/agesa/family15tn/Makefile.inc b/src/northbridge/amd/agesa/family15tn/Makefile.inc
index b0cf7ff..5bc7f6c 100644
--- a/src/northbridge/amd/agesa/family15tn/Makefile.inc
+++ b/src/northbridge/amd/agesa/family15tn/Makefile.inc
@@ -18,7 +18,8 @@
#
romstage-y += fam15tn_callouts.c
+romstage-y += dimmSpd.c
ramstage-y += northbridge.c
ramstage-y += fam15tn_callouts.c
-
+ramstage-y += dimmSpd.c
diff --git a/src/northbridge/amd/agesa/family15tn/chip.h b/src/northbridge/amd/agesa/family15tn/chip.h
new file mode 100644
index 0000000..56c3776
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15tn/chip.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _AGESA_FAM15TN_CHIP_H_
+#define _AGESA_FAM15TN_CHIP_H_
+
+struct northbridge_amd_agesa_family15tn_config
+{
+ u8 spdAddrLookup[2][2][4];
+
+};
+
+#endif
\ No newline at end of file
diff --git a/src/northbridge/amd/agesa/family15tn/dimmSpd.c b/src/northbridge/amd/agesa/family15tn/dimmSpd.c
new file mode 100644
index 0000000..73f287e
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15tn/dimmSpd.c
@@ -0,0 +1,161 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <device/pci_def.h>
+#include <device/device.h>
+
+/* warning: Porting.h includes an open #pragma pack(1) */
+#include "Porting.h"
+#include "AGESA.h"
+#include "amdlib.h"
+#include "dimmSpd.h"
+#include "chip.h"
+
+
+#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
+
+/*-----------------------------------------------------------------------------
+ *
+ * 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 + 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
+
+ // time limit to avoid hanging for unexpected error status (should never happen)
+ limit = __rdtsc () + 2000000000 / 10;
+ for (;;)
+ {
+ status = __inbyte (iobase);
+ if (__rdtsc () > limit) break;
+ if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
+ if ((status & 1) == 1) continue; // HostBusy set, keep waiting
+ break;
+ }
+
+ buffer [0] = __inbyte (iobase + 5);
+ if (status == 2) status = 0; // check for 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 + 0, 0xFF); // clear error status
+ __outbyte (iobase + 2, 0x44); // read command
+
+ // time limit to avoid hanging for unexpected error status
+ limit = __rdtsc () + 2000000000 / 10;
+ for (;;)
+ {
+ status = __inbyte (iobase);
+ if (__rdtsc () > limit) break;
+ if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
+ if ((status & 1) == 1) continue; // HostBusy set, keep waiting
+ break;
+ }
+
+ buffer [0] = __inbyte (iobase + 5);
+ if (status == 2) status = 0; // check for 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)
+{
+ int index, error;
+
+ /* read the first byte using offset zero */
+ error = readSmbusByteData (iobase, SmbusSlaveAddress, buffer, 0);
+ if (error) return error;
+
+ /* read the remaining bytes using auto-increment for speed */
+ for (index = 1; index < count; index++)
+ {
+ error = readSmbusByte (iobase, SmbusSlaveAddress, &buffer [index]);
+ if (error) return error;
+ }
+
+ return 0;
+}
+
+static void writePmReg (int reg, int data)
+{
+ __outbyte (0xCD6, reg);
+ __outbyte (0xCD7, data);
+}
+
+static void setupFch (int ioBase)
+{
+ writePmReg (0x2D, ioBase >> 8);
+ writePmReg (0x2C, ioBase | 1);
+ __outbyte (ioBase + 0x0E, 66000000 / 400000 / 4); // set SMBus clock to 400 KHz
+}
+
+AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
+{
+ int spdAddress, ioBase;
+ ROMSTAGE_CONST struct device *dev = dev_find_slot(0, PCI_DEVFN(0x18, 2));
+ ROMSTAGE_CONST struct northbridge_amd_agesa_family15tn_config *config = dev->chip_info;
+
+ if ((dev == 0) || (config == 0)) {
+ return AGESA_ERROR;
+ }
+
+ if (info->SocketId >= DIMENSION(config->spdAddrLookup ))
+ return AGESA_ERROR;
+ if (info->MemChannelId >= DIMENSION(config->spdAddrLookup[0] ))
+ return AGESA_ERROR;
+ if (info->DimmId >= DIMENSION(config->spdAddrLookup[0][0]))
+ return AGESA_ERROR;
+
+ spdAddress = config->spdAddrLookup
+ [info->SocketId] [info->MemChannelId] [info->DimmId];
+
+ if (spdAddress == 0) return AGESA_ERROR;
+ ioBase = 0xB00;
+ setupFch (ioBase);
+ return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
+}
diff --git a/src/northbridge/amd/agesa/family15tn/dimmSpd.h b/src/northbridge/amd/agesa/family15tn/dimmSpd.h
new file mode 100644
index 0000000..116eeb0
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15tn/dimmSpd.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+
+#ifndef _DIMMSPD_H_
+#define _DIMMSPD_H_
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+AGESA_STATUS
+AmdMemoryReadSPD (IN UINT32 Func, IN UINT32 Data, IN OUT AGESA_READ_SPD_PARAMS *SpdData);
+
+/*---------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *---------------------------------------------------------------------------------------
+ */
+
+#endif
diff --git a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
index 7c3b0ac..35aae91 100644
--- a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
+++ b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
@@ -24,6 +24,7 @@
#include "heapManager.h"
#include "FchPlatform.h"
#include "cbfs.h"
+#include "dimmSpd.h"
#include "fam15tn_callouts.h"
AGESA_STATUS fam15tn_AllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
@@ -403,3 +404,10 @@ AGESA_STATUS fam15tn_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *Con
return pVbiosImageInfo->ImagePtr == NULL ? AGESA_WARNING : AGESA_SUCCESS;
}
+AGESA_STATUS fam15tn_ReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+ AGESA_STATUS Status;
+ Status = AmdMemoryReadSPD (Func, Data, ConfigPtr);
+
+ return Status;
+}
diff --git a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h
index 74c7bf3..eb80a63 100644
--- a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h
+++ b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h
@@ -49,5 +49,6 @@ AGESA_STATUS fam15tn_HookBeforeDQSTraining (UINT32 Func, UINT32 Data, VOID *Conf
AGESA_STATUS fam15tn_HookBeforeExitSelfRefresh (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
AGESA_STATUS fam15tn_DefaultRet (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
AGESA_STATUS fam15tn_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt);
+AGESA_STATUS fam15tn_ReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
#endif /* CALLOUTS_AMD_AGESA_FAM15TN_H */
Martin Roth (martin.roth(a)se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2190
-gerrit
commit 986b86bc9bd20984c049f7d63dbdc9d5b811599c
Author: Martin Roth <martin.roth(a)se-eng.com>
Date: Sun Jan 20 10:38:58 2013 -0700
Fam15tn: Move SPD read from mainboards into wrapper
Continuing with the mainboard cleanup for F15tn, move the functions
to read the SPD from the mainboards for thatcher and parmerinto the
wrapper for the northbridge/amd/agesa/family15tn.
Move the SPD address customization for the mainboard into the
devicetree.cb file.
Unrelated side note - Porting.h has an un-closed #pragma pack(1)
that can cause confusing side-effects. AGESA's structures all
use this, but coreboot's don't. Be sure to include the coreboot
.h files BEFORE Porting.h is included, not after.
Change-Id: I89cdd225be61f60c6b8e7020e6f8b879983bbd96
Signed-off-by: Martin Roth <martin.roth(a)se-eng.com>
---
src/mainboard/amd/parmer/BiosCallOuts.c | 11 +-
src/mainboard/amd/parmer/BiosCallOuts.h | 3 -
src/mainboard/amd/parmer/Makefile.inc | 2 -
src/mainboard/amd/parmer/devicetree.cb | 16 +-
src/mainboard/amd/parmer/dimmSpd.c | 164 ------------------
src/mainboard/amd/parmer/dimmSpd.h | 59 -------
src/mainboard/amd/thatcher/BiosCallOuts.c | 11 +-
src/mainboard/amd/thatcher/BiosCallOuts.h | 3 -
src/mainboard/amd/thatcher/Makefile.inc | 2 -
src/mainboard/amd/thatcher/devicetree.cb | 16 +-
src/mainboard/amd/thatcher/dimmSpd.c | 166 ------------------
src/mainboard/amd/thatcher/dimmSpd.h | 59 -------
src/northbridge/amd/agesa/family15tn/Makefile.inc | 3 +-
src/northbridge/amd/agesa/family15tn/chip.h | 29 ++++
src/northbridge/amd/agesa/family15tn/dimmSpd.c | 161 ++++++++++++++++++
.../amd/agesa/family15tn/dimmSpd.c.orig | 188 +++++++++++++++++++++
src/northbridge/amd/agesa/family15tn/dimmSpd.h | 56 ++++++
.../amd/agesa/family15tn/fam15tn_callouts.c | 8 +
.../amd/agesa/family15tn/fam15tn_callouts.h | 1 +
19 files changed, 463 insertions(+), 495 deletions(-)
diff --git a/src/mainboard/amd/parmer/BiosCallOuts.c b/src/mainboard/amd/parmer/BiosCallOuts.c
index 8bfde14..7d79881 100644
--- a/src/mainboard/amd/parmer/BiosCallOuts.c
+++ b/src/mainboard/amd/parmer/BiosCallOuts.c
@@ -19,7 +19,6 @@
#include "agesawrapper.h"
#include "amdlib.h"
-#include "dimmSpd.h"
#include "BiosCallOuts.h"
#include "Ids.h"
#include "OptionsIds.h"
@@ -33,7 +32,7 @@ STATIC CONST BIOS_CALLOUT_STRUCT BiosCallouts[] =
{AGESA_DEALLOCATE_BUFFER, fam15tn_DeallocateBuffer },
{AGESA_DO_RESET, fam15tn_Reset },
{AGESA_LOCATE_BUFFER, fam15tn_LocateBuffer },
- {AGESA_READ_SPD, BiosReadSpd },
+ {AGESA_READ_SPD, fam15tn_ReadSpd },
{AGESA_READ_SPD_RECOVERY, fam15tn_DefaultRet },
{AGESA_RUNFUNC_ONAP, fam15tn_RunFuncOnAp },
{AGESA_GET_IDS_INIT_DATA, fam15tn_GetIdsInitData },
@@ -63,14 +62,6 @@ AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
return CalloutStatus;
}
-AGESA_STATUS BiosReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
-{
- AGESA_STATUS Status;
- Status = AmdMemoryReadSPD (Func, Data, ConfigPtr);
-
- return Status;
-}
-
/**
* AMD Parmer Platform ALC272 Verb Table
*/
diff --git a/src/mainboard/amd/parmer/BiosCallOuts.h b/src/mainboard/amd/parmer/BiosCallOuts.h
index 66db8cd..d42683e 100644
--- a/src/mainboard/amd/parmer/BiosCallOuts.h
+++ b/src/mainboard/amd/parmer/BiosCallOuts.h
@@ -25,9 +25,6 @@
/* CALLOUT Initialization */
AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
-/* AGESA ADVANCED CALLOUTS - MEMORY */
-AGESA_STATUS BiosReadSpd (UINT32 Func,UINT32 Data,VOID *ConfigPtr);
-
/* FCH OEM Config*/
AGESA_STATUS Fch_Oem_config(UINT32 Func, UINT32 FchData, VOID *ConfigPtr);
diff --git a/src/mainboard/amd/parmer/Makefile.inc b/src/mainboard/amd/parmer/Makefile.inc
index de3163d..a83297a 100644
--- a/src/mainboard/amd/parmer/Makefile.inc
+++ b/src/mainboard/amd/parmer/Makefile.inc
@@ -19,12 +19,10 @@
romstage-y += buildOpts.c
romstage-y += agesawrapper.c
-romstage-y += dimmSpd.c
romstage-y += BiosCallOuts.c
romstage-y += PlatformGnbPcie.c
ramstage-y += buildOpts.c
ramstage-y += agesawrapper.c
-ramstage-y += dimmSpd.c
ramstage-y += BiosCallOuts.c
ramstage-y += PlatformGnbPcie.c
diff --git a/src/mainboard/amd/parmer/devicetree.cb b/src/mainboard/amd/parmer/devicetree.cb
index 3e3e371..9dbdc98 100644
--- a/src/mainboard/amd/parmer/devicetree.cb
+++ b/src/mainboard/amd/parmer/devicetree.cb
@@ -51,16 +51,10 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 13.2 on end # USB
device pci 14.0 on # SMBUS
chip drivers/generic/generic #dimm 0
- device i2c 50 on end
+ device i2c 50 on end # 7-bit SPD address
end
chip drivers/generic/generic #dimm 1
- device i2c 51 on end
- end
- chip drivers/generic/generic #dimm 0-1-0
- device i2c 52 on end
- end
- chip drivers/generic/generic #dimm 0-1-1
- device i2c 53 on end
+ device i2c 51 on end # 7-bit SPD address
end
end # SM
device pci 14.1 on end # IDE 0x439c
@@ -85,6 +79,12 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 18.4 on end
device pci 18.5 on end
+ register "spdAddrLookup" = "
+ {
+ { {0xA0, 0x00}, {0xA2, 0x00}, }, // socket 0 - Channel 0 & 1 - 8-bit SPD addresses
+ { {0x00, 0x00}, {0x00, 0x00}, }, // socket 1 - Channel 0 & 1 - 8-bit SPD addresses
+ }"
+
end #chip northbridge/amd/agesa/family15tn # CPU side of HT root complex
end #pci_domain
end #chip northbridge/amd/agesa/family15tn/root_complex
diff --git a/src/mainboard/amd/parmer/dimmSpd.c b/src/mainboard/amd/parmer/dimmSpd.c
deleted file mode 100644
index 576de7e..0000000
--- a/src/mainboard/amd/parmer/dimmSpd.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "Porting.h"
-#include "AGESA.h"
-#include "amdlib.h"
-#include "dimmSpd.h"
-
-#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
-
-/*#pragma optimize ("", off) // for source level debug
- *---------------------------------------------------------------------------
- *
- * SPD address table - porting required
- */
-
-static const UINT8 spdAddressLookup [2] [2] [4] = // socket, channel, dimm
-{
- // socket 0
- {
- {0xA0, 0x00}, // channel 0 dimms
- {0xA2, 0x00}, // channel 1 dimms
- },
- // socket 1
- {
- {0x00, 0x00}, // channel 0 dimms
- {0x00, 0x00}, // channel 1 dimms
- },
-};
-
-/*-----------------------------------------------------------------------------
- *
- * 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 + 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
-
- // time limit to avoid hanging for unexpected error status (should never happen)
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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 + 0, 0xFF); // clear error status
- __outbyte (iobase + 2, 0x44); // read command
-
- // time limit to avoid hanging for unexpected error status
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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)
-{
- int index, error;
-
- /* read the first byte using offset zero */
- error = readSmbusByteData (iobase, SmbusSlaveAddress, buffer, 0);
- if (error) return error;
-
- /* read the remaining bytes using auto-increment for speed */
- for (index = 1; index < count; index++)
- {
- error = readSmbusByte (iobase, SmbusSlaveAddress, &buffer [index]);
- if (error) return error;
- }
-
- return 0;
-}
-
-static void writePmReg (int reg, int data)
-{
- __outbyte (0xCD6, reg);
- __outbyte (0xCD7, data);
-}
-
-static void setupFch (int ioBase)
-{
- writePmReg (0x2D, ioBase >> 8);
- writePmReg (0x2C, ioBase | 1);
- __outbyte (ioBase + 0x0E, 66000000 / 400000 / 4); // set SMBus clock to 400 KHz
-}
-
-AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
-{
- int spdAddress, ioBase;
-
- if (info->SocketId >= DIMENSION (spdAddressLookup )) return AGESA_ERROR;
- if (info->MemChannelId >= DIMENSION (spdAddressLookup[0] )) return AGESA_ERROR;
- if (info->DimmId >= DIMENSION (spdAddressLookup[0][0])) return AGESA_ERROR;
-
- spdAddress = spdAddressLookup [info->SocketId] [info->MemChannelId] [info->DimmId];
- if (spdAddress == 0) return AGESA_ERROR;
- ioBase = 0xB00;
- setupFch (ioBase);
- return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
-}
diff --git a/src/mainboard/amd/parmer/dimmSpd.h b/src/mainboard/amd/parmer/dimmSpd.h
deleted file mode 100644
index c19cecc..0000000
--- a/src/mainboard/amd/parmer/dimmSpd.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*----------------------------------------------------------------------------------------
- * M O D U L E S U S E D
- *----------------------------------------------------------------------------------------
- */
-
-#ifndef _DIMMSPD_H_
-#define _DIMMSPD_H_
-
-#include "Porting.h"
-#include "AGESA.h"
-
-/*----------------------------------------------------------------------------------------
- * D E F I N I T I O N S A N D M A C R O S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * T Y P E D E F S A N D S T R U C T U R E S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * P R O T O T Y P E S O F L O C A L F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * E X P O R T E D F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-AGESA_STATUS
-AmdMemoryReadSPD (IN UINT32 Func, IN UINT32 Data, IN OUT AGESA_READ_SPD_PARAMS *SpdData);
-
-/*---------------------------------------------------------------------------------------
- * L O C A L F U N C T I O N S
- *---------------------------------------------------------------------------------------
- */
-
-#endif
diff --git a/src/mainboard/amd/thatcher/BiosCallOuts.c b/src/mainboard/amd/thatcher/BiosCallOuts.c
index b82c56b..2d735af 100644
--- a/src/mainboard/amd/thatcher/BiosCallOuts.c
+++ b/src/mainboard/amd/thatcher/BiosCallOuts.c
@@ -19,7 +19,6 @@
#include "agesawrapper.h"
#include "amdlib.h"
-#include "dimmSpd.h"
#include "BiosCallOuts.h"
#include "Ids.h"
#include "OptionsIds.h"
@@ -33,7 +32,7 @@ STATIC CONST BIOS_CALLOUT_STRUCT BiosCallouts[] =
{AGESA_DEALLOCATE_BUFFER, fam15tn_DeallocateBuffer },
{AGESA_DO_RESET, fam15tn_Reset },
{AGESA_LOCATE_BUFFER, fam15tn_LocateBuffer },
- {AGESA_READ_SPD, BiosReadSpd },
+ {AGESA_READ_SPD, fam15tn_ReadSpd },
{AGESA_READ_SPD_RECOVERY, fam15tn_DefaultRet },
{AGESA_RUNFUNC_ONAP, fam15tn_RunFuncOnAp },
{AGESA_GET_IDS_INIT_DATA, fam15tn_GetIdsInitData },
@@ -63,14 +62,6 @@ AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
return CalloutStatus;
}
-AGESA_STATUS BiosReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
-{
- AGESA_STATUS Status;
- Status = AmdMemoryReadSPD (Func, Data, ConfigPtr);
-
- return Status;
-}
-
/**
* AMD Thatcher Platform ALC272 Verb Table
*/
diff --git a/src/mainboard/amd/thatcher/BiosCallOuts.h b/src/mainboard/amd/thatcher/BiosCallOuts.h
index 66db8cd..d42683e 100644
--- a/src/mainboard/amd/thatcher/BiosCallOuts.h
+++ b/src/mainboard/amd/thatcher/BiosCallOuts.h
@@ -25,9 +25,6 @@
/* CALLOUT Initialization */
AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
-/* AGESA ADVANCED CALLOUTS - MEMORY */
-AGESA_STATUS BiosReadSpd (UINT32 Func,UINT32 Data,VOID *ConfigPtr);
-
/* FCH OEM Config*/
AGESA_STATUS Fch_Oem_config(UINT32 Func, UINT32 FchData, VOID *ConfigPtr);
diff --git a/src/mainboard/amd/thatcher/Makefile.inc b/src/mainboard/amd/thatcher/Makefile.inc
index de3163d..a83297a 100644
--- a/src/mainboard/amd/thatcher/Makefile.inc
+++ b/src/mainboard/amd/thatcher/Makefile.inc
@@ -19,12 +19,10 @@
romstage-y += buildOpts.c
romstage-y += agesawrapper.c
-romstage-y += dimmSpd.c
romstage-y += BiosCallOuts.c
romstage-y += PlatformGnbPcie.c
ramstage-y += buildOpts.c
ramstage-y += agesawrapper.c
-ramstage-y += dimmSpd.c
ramstage-y += BiosCallOuts.c
ramstage-y += PlatformGnbPcie.c
diff --git a/src/mainboard/amd/thatcher/devicetree.cb b/src/mainboard/amd/thatcher/devicetree.cb
index f6459c1..ccb8b58 100644
--- a/src/mainboard/amd/thatcher/devicetree.cb
+++ b/src/mainboard/amd/thatcher/devicetree.cb
@@ -51,16 +51,10 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 13.2 on end # USB
device pci 14.0 on # SMBUS
chip drivers/generic/generic #dimm 0
- device i2c 50 on end
+ device i2c 50 on end # 7-bit SPD address
end
chip drivers/generic/generic #dimm 1
- device i2c 51 on end
- end
- chip drivers/generic/generic #dimm 0-1-0
- device i2c 52 on end
- end
- chip drivers/generic/generic #dimm 0-1-1
- device i2c 53 on end
+ device i2c 51 on end # 7-bit SPD address
end
end # SM
device pci 14.1 on end # IDE 0x439c
@@ -100,6 +94,12 @@ chip northbridge/amd/agesa/family15tn/root_complex
device pci 18.4 on end
device pci 18.5 on end
+ register "spdAddrLookup" = "
+ {
+ { {0xA0, 0x00}, {0xA2, 0x00}, }, // socket 0 - Channel 0 & 1 - 8-bit SPD addresses
+ { {0x00, 0x00}, {0x00, 0x00}, }, // socket 1 - Channel 0 & 1 - 8-bit SPD addresses
+ }"
+
end #chip northbridge/amd/agesa/family15tn # CPU side of HT root complex
end #pci_domain
end #chip northbridge/amd/agesa/family15tn/root_complex
diff --git a/src/mainboard/amd/thatcher/dimmSpd.c b/src/mainboard/amd/thatcher/dimmSpd.c
deleted file mode 100644
index 29d6a29..0000000
--- a/src/mainboard/amd/thatcher/dimmSpd.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "Porting.h"
-#include "AGESA.h"
-#include "amdlib.h"
-#include "dimmSpd.h"
-
-#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
-
-/*#pragma optimize ("", off) // for source level debug
- *---------------------------------------------------------------------------
- *
- * SPD address table - porting required
- */
-
-static const UINT8 spdAddressLookup [2] [2] [4] = // socket, channel, dimm
-{
- // socket 0
- {
- {0xA0, 0x00}, // channel 0 dimms
- {0xA2, 0x00}, // channel 1 dimms
- },
- // socket 1
- {
- {0x00, 0x00}, // channel 0 dimms
- {0x00, 0x00}, // channel 1 dimms
- },
-};
-
-/*-----------------------------------------------------------------------------
- *
- * 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 + 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
-
- // time limit to avoid hanging for unexpected error status (should never happen)
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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 + 0, 0xFF); // clear error status
- __outbyte (iobase + 2, 0x44); // read command
-
- // time limit to avoid hanging for unexpected error status
- limit = __rdtsc () + 2000000000 / 10;
- for (;;)
- {
- status = __inbyte (iobase);
- if (__rdtsc () > limit) break;
- if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
- if ((status & 1) == 1) continue; // HostBusy set, keep waiting
- break;
- }
-
- buffer [0] = __inbyte (iobase + 5);
- if (status == 2) status = 0; // check for 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)
-{
- int index, error;
-
- /* read the first byte using offset zero */
- error = readSmbusByteData (iobase, SmbusSlaveAddress, buffer, 0);
- if (error) return error;
-
- /* read the remaining bytes using auto-increment for speed */
- for (index = 1; index < count; index++)
- {
- error = readSmbusByte (iobase, SmbusSlaveAddress, &buffer [index]);
- if (error) return error;
- }
-
- return 0;
-}
-
-static void writePmReg (int reg, int data)
-{
- __outbyte (0xCD6, reg);
- __outbyte (0xCD7, data);
-}
-
-static void setupFch (int ioBase)
-{
- writePmReg (0x2D, ioBase >> 8);
- writePmReg (0x2C, ioBase | 1);
- //writePmReg (0x29, 0x80);
- //writePmReg (0x28, 0x61);
- __outbyte (ioBase + 0x0E, 66000000 / 400000 / 4); // set SMBus clock to 400 KHz
-}
-
-AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
-{
- int spdAddress, ioBase;
-
- if (info->SocketId >= DIMENSION (spdAddressLookup )) return AGESA_ERROR;
- if (info->MemChannelId >= DIMENSION (spdAddressLookup[0] )) return AGESA_ERROR;
- if (info->DimmId >= DIMENSION (spdAddressLookup[0][0])) return AGESA_ERROR;
-
- spdAddress = spdAddressLookup [info->SocketId] [info->MemChannelId] [info->DimmId];
- if (spdAddress == 0) return AGESA_ERROR;
- ioBase = 0xB00;
- setupFch (ioBase);
- return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
-}
diff --git a/src/mainboard/amd/thatcher/dimmSpd.h b/src/mainboard/amd/thatcher/dimmSpd.h
deleted file mode 100644
index c19cecc..0000000
--- a/src/mainboard/amd/thatcher/dimmSpd.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2012 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*----------------------------------------------------------------------------------------
- * M O D U L E S U S E D
- *----------------------------------------------------------------------------------------
- */
-
-#ifndef _DIMMSPD_H_
-#define _DIMMSPD_H_
-
-#include "Porting.h"
-#include "AGESA.h"
-
-/*----------------------------------------------------------------------------------------
- * D E F I N I T I O N S A N D M A C R O S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * T Y P E D E F S A N D S T R U C T U R E S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * P R O T O T Y P E S O F L O C A L F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------------------
- * E X P O R T E D F U N C T I O N S
- *----------------------------------------------------------------------------------------
- */
-
-AGESA_STATUS
-AmdMemoryReadSPD (IN UINT32 Func, IN UINT32 Data, IN OUT AGESA_READ_SPD_PARAMS *SpdData);
-
-/*---------------------------------------------------------------------------------------
- * L O C A L F U N C T I O N S
- *---------------------------------------------------------------------------------------
- */
-
-#endif
diff --git a/src/northbridge/amd/agesa/family15tn/Makefile.inc b/src/northbridge/amd/agesa/family15tn/Makefile.inc
index b0cf7ff..5bc7f6c 100644
--- a/src/northbridge/amd/agesa/family15tn/Makefile.inc
+++ b/src/northbridge/amd/agesa/family15tn/Makefile.inc
@@ -18,7 +18,8 @@
#
romstage-y += fam15tn_callouts.c
+romstage-y += dimmSpd.c
ramstage-y += northbridge.c
ramstage-y += fam15tn_callouts.c
-
+ramstage-y += dimmSpd.c
diff --git a/src/northbridge/amd/agesa/family15tn/chip.h b/src/northbridge/amd/agesa/family15tn/chip.h
new file mode 100644
index 0000000..56c3776
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15tn/chip.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _AGESA_FAM15TN_CHIP_H_
+#define _AGESA_FAM15TN_CHIP_H_
+
+struct northbridge_amd_agesa_family15tn_config
+{
+ u8 spdAddrLookup[2][2][4];
+
+};
+
+#endif
\ No newline at end of file
diff --git a/src/northbridge/amd/agesa/family15tn/dimmSpd.c b/src/northbridge/amd/agesa/family15tn/dimmSpd.c
new file mode 100644
index 0000000..73f287e
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15tn/dimmSpd.c
@@ -0,0 +1,161 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <device/pci_def.h>
+#include <device/device.h>
+
+/* warning: Porting.h includes an open #pragma pack(1) */
+#include "Porting.h"
+#include "AGESA.h"
+#include "amdlib.h"
+#include "dimmSpd.h"
+#include "chip.h"
+
+
+#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
+
+/*-----------------------------------------------------------------------------
+ *
+ * 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 + 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
+
+ // time limit to avoid hanging for unexpected error status (should never happen)
+ limit = __rdtsc () + 2000000000 / 10;
+ for (;;)
+ {
+ status = __inbyte (iobase);
+ if (__rdtsc () > limit) break;
+ if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
+ if ((status & 1) == 1) continue; // HostBusy set, keep waiting
+ break;
+ }
+
+ buffer [0] = __inbyte (iobase + 5);
+ if (status == 2) status = 0; // check for 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 + 0, 0xFF); // clear error status
+ __outbyte (iobase + 2, 0x44); // read command
+
+ // time limit to avoid hanging for unexpected error status
+ limit = __rdtsc () + 2000000000 / 10;
+ for (;;)
+ {
+ status = __inbyte (iobase);
+ if (__rdtsc () > limit) break;
+ if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
+ if ((status & 1) == 1) continue; // HostBusy set, keep waiting
+ break;
+ }
+
+ buffer [0] = __inbyte (iobase + 5);
+ if (status == 2) status = 0; // check for 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)
+{
+ int index, error;
+
+ /* read the first byte using offset zero */
+ error = readSmbusByteData (iobase, SmbusSlaveAddress, buffer, 0);
+ if (error) return error;
+
+ /* read the remaining bytes using auto-increment for speed */
+ for (index = 1; index < count; index++)
+ {
+ error = readSmbusByte (iobase, SmbusSlaveAddress, &buffer [index]);
+ if (error) return error;
+ }
+
+ return 0;
+}
+
+static void writePmReg (int reg, int data)
+{
+ __outbyte (0xCD6, reg);
+ __outbyte (0xCD7, data);
+}
+
+static void setupFch (int ioBase)
+{
+ writePmReg (0x2D, ioBase >> 8);
+ writePmReg (0x2C, ioBase | 1);
+ __outbyte (ioBase + 0x0E, 66000000 / 400000 / 4); // set SMBus clock to 400 KHz
+}
+
+AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
+{
+ int spdAddress, ioBase;
+ ROMSTAGE_CONST struct device *dev = dev_find_slot(0, PCI_DEVFN(0x18, 2));
+ ROMSTAGE_CONST struct northbridge_amd_agesa_family15tn_config *config = dev->chip_info;
+
+ if ((dev == 0) || (config == 0)) {
+ return AGESA_ERROR;
+ }
+
+ if (info->SocketId >= DIMENSION(config->spdAddrLookup ))
+ return AGESA_ERROR;
+ if (info->MemChannelId >= DIMENSION(config->spdAddrLookup[0] ))
+ return AGESA_ERROR;
+ if (info->DimmId >= DIMENSION(config->spdAddrLookup[0][0]))
+ return AGESA_ERROR;
+
+ spdAddress = config->spdAddrLookup
+ [info->SocketId] [info->MemChannelId] [info->DimmId];
+
+ if (spdAddress == 0) return AGESA_ERROR;
+ ioBase = 0xB00;
+ setupFch (ioBase);
+ return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
+}
diff --git a/src/northbridge/amd/agesa/family15tn/dimmSpd.c.orig b/src/northbridge/amd/agesa/family15tn/dimmSpd.c.orig
new file mode 100644
index 0000000..b3bba1d
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15tn/dimmSpd.c.orig
@@ -0,0 +1,188 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "Porting.h"
+#include "AGESA.h"
+#include "amdlib.h"
+#include "dimmSpd.h"
+#include "chip.h"
+<<<<<<< Updated upstream:src/northbridge/amd/agesa/family15tn/dimmSpd.c
+
+#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
+
+extern ROMSTAGE_CONST struct northbridge_amd_agesa_family15tn_config ROMSTAGE_CONST northbridge_amd_agesa_family15tn_info_6;
+=======
+#include <device/pci_def.h>
+#include <device/device.h>
+#include <console/console.h>
+#include <console/loglevel.h>
+
+
+#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
+>>>>>>> Stashed changes:src/mainboard/amd/parmer/dimmSpd.c
+
+/*-----------------------------------------------------------------------------
+ *
+ * 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 + 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
+
+ // time limit to avoid hanging for unexpected error status (should never happen)
+ limit = __rdtsc () + 2000000000 / 10;
+ for (;;)
+ {
+ status = __inbyte (iobase);
+ if (__rdtsc () > limit) break;
+ if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
+ if ((status & 1) == 1) continue; // HostBusy set, keep waiting
+ break;
+ }
+
+ buffer [0] = __inbyte (iobase + 5);
+ if (status == 2) status = 0; // check for 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 + 0, 0xFF); // clear error status
+ __outbyte (iobase + 2, 0x44); // read command
+
+ // time limit to avoid hanging for unexpected error status
+ limit = __rdtsc () + 2000000000 / 10;
+ for (;;)
+ {
+ status = __inbyte (iobase);
+ if (__rdtsc () > limit) break;
+ if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
+ if ((status & 1) == 1) continue; // HostBusy set, keep waiting
+ break;
+ }
+
+ buffer [0] = __inbyte (iobase + 5);
+ if (status == 2) status = 0; // check for 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)
+{
+ int index, error;
+
+ /* read the first byte using offset zero */
+ error = readSmbusByteData (iobase, SmbusSlaveAddress, buffer, 0);
+ if (error) return error;
+
+ /* read the remaining bytes using auto-increment for speed */
+ for (index = 1; index < count; index++)
+ {
+ error = readSmbusByte (iobase, SmbusSlaveAddress, &buffer [index]);
+ if (error) return error;
+ }
+
+ return 0;
+}
+
+static void writePmReg (int reg, int data)
+{
+ __outbyte (0xCD6, reg);
+ __outbyte (0xCD7, data);
+}
+
+static void setupFch (int ioBase)
+{
+ writePmReg (0x2D, ioBase >> 8);
+ writePmReg (0x2C, ioBase | 1);
+ __outbyte (ioBase + 0x0E, 66000000 / 400000 / 4); // set SMBus clock to 400 KHz
+}
+
+AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
+{
+ int spdAddress, ioBase;
+ ROMSTAGE_CONST struct device *dev = dev_find_slot(0, PCI_DEVFN(0x18, 2));
+ ROMSTAGE_CONST struct northbridge_amd_agesa_family15tn_config *config = dev->chip_info;
+
+ if ((dev == 0) || (config == 0)) {
+ return AGESA_ERROR;
+ }
+ printk(BIOS_DEBUG, "SPD ADDR 0: %02x \n", config->spdAddrLookup[0][0][0]);
+
+
+ if (info->SocketId >= DIMENSION(config->spdAddrLookup ))
+ return AGESA_ERROR;
+ if (info->MemChannelId >= DIMENSION(config->spdAddrLookup[0] ))
+ return AGESA_ERROR;
+ if (info->DimmId >= DIMENSION(config->spdAddrLookup[0][0]))
+ return AGESA_ERROR;
+
+<<<<<<< Updated upstream:src/northbridge/amd/agesa/family15tn/dimmSpd.c
+ if (info->SocketId >= DIMENSION
+ (northbridge_amd_agesa_family15tn_info_6.spdAddrLookup ))
+ return AGESA_ERROR;
+ if (info->MemChannelId >= DIMENSION
+ (northbridge_amd_agesa_family15tn_info_6.spdAddrLookup[0] ))
+ return AGESA_ERROR;
+ if (info->DimmId >= DIMENSION
+ (northbridge_amd_agesa_family15tn_info_6.spdAddrLookup[0][0]))
+ return AGESA_ERROR;
+
+ spdAddress = northbridge_amd_agesa_family15tn_info_6.spdAddrLookup
+ [info->SocketId] [info->MemChannelId] [info->DimmId];
+=======
+ spdAddress = config->spdAddrLookup
+ [info->SocketId] [info->MemChannelId] [info->DimmId];
+ printk(BIOS_DEBUG, "SPD ADDR [%02x][%02x][%02x]: %02x \n",
+ info->SocketId, info->MemChannelId, info->DimmId,
+ config->spdAddrLookup[info->SocketId][info->MemChannelId][info->DimmId]);
+
+>>>>>>> Stashed changes:src/mainboard/amd/parmer/dimmSpd.c
+ if (spdAddress == 0) return AGESA_ERROR;
+ ioBase = 0xB00;
+ setupFch (ioBase);
+ return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
+}
diff --git a/src/northbridge/amd/agesa/family15tn/dimmSpd.h b/src/northbridge/amd/agesa/family15tn/dimmSpd.h
new file mode 100644
index 0000000..116eeb0
--- /dev/null
+++ b/src/northbridge/amd/agesa/family15tn/dimmSpd.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+
+#ifndef _DIMMSPD_H_
+#define _DIMMSPD_H_
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+AGESA_STATUS
+AmdMemoryReadSPD (IN UINT32 Func, IN UINT32 Data, IN OUT AGESA_READ_SPD_PARAMS *SpdData);
+
+/*---------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *---------------------------------------------------------------------------------------
+ */
+
+#endif
diff --git a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
index 7c3b0ac..35aae91 100644
--- a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
+++ b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
@@ -24,6 +24,7 @@
#include "heapManager.h"
#include "FchPlatform.h"
#include "cbfs.h"
+#include "dimmSpd.h"
#include "fam15tn_callouts.h"
AGESA_STATUS fam15tn_AllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
@@ -403,3 +404,10 @@ AGESA_STATUS fam15tn_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *Con
return pVbiosImageInfo->ImagePtr == NULL ? AGESA_WARNING : AGESA_SUCCESS;
}
+AGESA_STATUS fam15tn_ReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
+{
+ AGESA_STATUS Status;
+ Status = AmdMemoryReadSPD (Func, Data, ConfigPtr);
+
+ return Status;
+}
diff --git a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h
index 74c7bf3..eb80a63 100644
--- a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h
+++ b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.h
@@ -49,5 +49,6 @@ AGESA_STATUS fam15tn_HookBeforeDQSTraining (UINT32 Func, UINT32 Data, VOID *Conf
AGESA_STATUS fam15tn_HookBeforeExitSelfRefresh (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
AGESA_STATUS fam15tn_DefaultRet (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
AGESA_STATUS fam15tn_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt);
+AGESA_STATUS fam15tn_ReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
#endif /* CALLOUTS_AMD_AGESA_FAM15TN_H */