summaryrefslogtreecommitdiff
path: root/src/southbridge/intel/i3100/smbus.c
diff options
context:
space:
mode:
authorDustin Harrison <dustin.harrison@sutus.com>2011-05-12 18:30:23 +0200
committerNoe Rubinstein <nrubinstein@proformatique.com>2011-06-23 10:38:59 +0200
commit19676f30ac7b838c4e8a7b93f6299f5375848452 (patch)
tree2815ee1485c2b68e60744b00c684d8a82639a49f /src/southbridge/intel/i3100/smbus.c
parent07186a9f5375ec026350a97d9df35391b8120228 (diff)
Convert to CAR and make i3100/{early_smbus.c,smbus.c} compile with host gcc
This patch aims to convert the Truxton dev board to CAR which required the following changes: - Remove unused variables (to satisfy no warnings flag) - Change .c includes to use headers (raminit_ep80579, early_smbus, smbus) - Remove early_mtrr_init because CAR takes care of this - Remove cache_lbmem (raminit_ep80579.c) as CAR takes care of this - Remove debug code (for now, coming soon) One side effect is that the mtarvon and eagleheights (which are already CAR) romstage now use the new headers. These two boards have been build tested. The truxton platform was boot tested and a full memtest was run. Signed-off-by: Dustin Harrison <dustin.harrison@sutus.com> ---
Diffstat (limited to 'src/southbridge/intel/i3100/smbus.c')
-rw-r--r--src/southbridge/intel/i3100/smbus.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/southbridge/intel/i3100/smbus.c b/src/southbridge/intel/i3100/smbus.c
index 23602acb2..06401137f 100644
--- a/src/southbridge/intel/i3100/smbus.c
+++ b/src/southbridge/intel/i3100/smbus.c
@@ -28,6 +28,7 @@
#include "i3100.h"
#include "smbus.h"
+#ifndef __PRE_RAM__
static int lsmbus_read_byte(device_t dev, u8 address)
{
u16 device;
@@ -77,3 +78,79 @@ static const struct pci_driver smbus_driver_ep80579 __pci_driver = {
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_EP80579_SMB,
};
+#endif /* __PRE_RAM__ */
+
+void smbus_delay(void)
+{
+ outb(0x80, 0x80);
+}
+
+int smbus_wait_until_ready(u32 smbus_io_base)
+{
+ u32 loops = SMBUS_TIMEOUT;
+ u8 byte;
+ do {
+ smbus_delay();
+ if (--loops == 0)
+ break;
+ byte = inb(smbus_io_base + SMBHSTSTAT);
+ } while (byte & 1);
+ return loops ? 0 : -1;
+}
+
+int smbus_wait_until_done(u32 smbus_io_base)
+{
+ u32 loops = SMBUS_TIMEOUT;
+ u8 byte;
+ do {
+ smbus_delay();
+ if (--loops == 0)
+ break;
+ byte = inb(smbus_io_base + SMBHSTSTAT);
+ } while ((byte & 1) || (byte & ~((1 << 6)|(1 << 0))) == 0);
+ return loops ? 0 : -1;
+}
+
+int do_smbus_read_byte(u32 smbus_io_base, u16 device, u8 address)
+{
+ u8 global_status_register;
+ u8 byte;
+
+ if (smbus_wait_until_ready(smbus_io_base) < 0) {
+ return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+ }
+ /* setup transaction */
+ /* disable interrupts */
+ outb(inb(smbus_io_base + SMBHSTCTL) & (~1), smbus_io_base + SMBHSTCTL);
+ /* set the device I'm talking too */
+ outb(((device & 0x7f) << 1) | SMBUS_READ, smbus_io_base + SMBXMITADD);
+ /* set the command/address... */
+ outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
+ /* set up for a byte data read */
+ outb((inb(smbus_io_base + SMBHSTCTL) & 0xE3) | (0x2 << 2), smbus_io_base + SMBHSTCTL);
+ /* clear any lingering errors, so the transaction will run */
+ outb(inb(smbus_io_base + SMBHSTSTAT), smbus_io_base + SMBHSTSTAT);
+
+ /* clear the data byte...*/
+ outb(0, smbus_io_base + SMBHSTDAT0);
+
+ /* start the command */
+ outb((inb(smbus_io_base + SMBHSTCTL) | 0x40), smbus_io_base + SMBHSTCTL);
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(smbus_io_base) < 0) {
+ return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
+ }
+
+ global_status_register = inb(smbus_io_base + SMBHSTSTAT);
+
+ /* Ignore the In Use Status... */
+ global_status_register &= ~(3 << 5);
+
+ /* read results of transaction */
+ byte = inb(smbus_io_base + SMBHSTDAT0);
+ if (global_status_register != (1 << 1)) {
+ return SMBUS_ERROR;
+ }
+ return byte;
+}