summaryrefslogtreecommitdiff
path: root/src/southbridge
diff options
context:
space:
mode:
authorArthur Heymans <arthur@aheymans.xyz>2017-04-12 17:01:31 +0200
committerMartin Roth <martinroth@google.com>2017-08-06 23:26:15 +0000
commit16fe79048f5254661ff2342aa481cbb44657b7ff (patch)
tree5ad72bc5c5a97ca9a7a47f5ab24bbe622f12e9e9 /src/southbridge
parent12d010306b3892b01350e96d83275206215d9f31 (diff)
sb/intel/*: Use common SMBus functions
All Intel southbridges implement the same SMBus functions. This patch replaces all these similar and mostly identical implementations with a common file. This also makes i2c block read available to all those southbridges. If the northbridge has to read a lot of SPD bytes sequentially, using this function can reduce the time being spent to read SPD five-fold. Change-Id: I93bb186e04e8c32dff04fc1abe4b5ecbc4c9c962 Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/19258 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Diffstat (limited to 'src/southbridge')
-rw-r--r--src/southbridge/intel/bd82x6x/Kconfig1
-rw-r--r--src/southbridge/intel/bd82x6x/early_smbus.c2
-rw-r--r--src/southbridge/intel/bd82x6x/pch.h16
-rw-r--r--src/southbridge/intel/bd82x6x/smbus.c45
-rw-r--r--src/southbridge/intel/bd82x6x/smbus.h95
-rw-r--r--src/southbridge/intel/common/Kconfig2
-rw-r--r--src/southbridge/intel/common/Makefile.inc4
-rw-r--r--src/southbridge/intel/common/smbus.c365
-rw-r--r--src/southbridge/intel/common/smbus.h46
-rw-r--r--src/southbridge/intel/fsp_bd82x6x/Kconfig2
-rw-r--r--src/southbridge/intel/fsp_i89xx/Kconfig2
-rw-r--r--src/southbridge/intel/fsp_i89xx/early_smbus.c2
-rw-r--r--src/southbridge/intel/fsp_i89xx/pch.h16
-rw-r--r--src/southbridge/intel/fsp_i89xx/smbus.h91
-rw-r--r--src/southbridge/intel/fsp_rangeley/Kconfig2
-rw-r--r--src/southbridge/intel/fsp_rangeley/early_smbus.c2
-rw-r--r--src/southbridge/intel/fsp_rangeley/smbus.c2
-rw-r--r--src/southbridge/intel/fsp_rangeley/smbus.h95
-rw-r--r--src/southbridge/intel/fsp_rangeley/soc.h15
-rw-r--r--src/southbridge/intel/i3100/Kconfig2
-rw-r--r--src/southbridge/intel/i3100/early_smbus.c2
-rw-r--r--src/southbridge/intel/i3100/smbus.c2
-rw-r--r--src/southbridge/intel/i3100/smbus.h151
-rw-r--r--src/southbridge/intel/i82371eb/Kconfig2
-rw-r--r--src/southbridge/intel/i82371eb/early_smbus.c4
-rw-r--r--src/southbridge/intel/i82371eb/smbus.c2
-rw-r--r--src/southbridge/intel/i82371eb/smbus.h112
-rw-r--r--src/southbridge/intel/i82801ax/Kconfig2
-rw-r--r--src/southbridge/intel/i82801ax/early_smbus.c2
-rw-r--r--src/southbridge/intel/i82801ax/i82801ax.h11
-rw-r--r--src/southbridge/intel/i82801ax/smbus.c2
-rw-r--r--src/southbridge/intel/i82801ax/smbus.h97
-rw-r--r--src/southbridge/intel/i82801bx/Kconfig2
-rw-r--r--src/southbridge/intel/i82801bx/early_smbus.c2
-rw-r--r--src/southbridge/intel/i82801bx/i82801bx.h15
-rw-r--r--src/southbridge/intel/i82801bx/smbus.c2
-rw-r--r--src/southbridge/intel/i82801bx/smbus.h94
-rw-r--r--src/southbridge/intel/i82801dx/Kconfig2
-rw-r--r--src/southbridge/intel/i82801dx/early_smbus.c141
-rw-r--r--src/southbridge/intel/i82801dx/i82801dx.h17
-rw-r--r--src/southbridge/intel/i82801dx/smbus.c101
-rw-r--r--src/southbridge/intel/i82801gx/Kconfig1
-rw-r--r--src/southbridge/intel/i82801gx/early_smbus.c51
-rw-r--r--src/southbridge/intel/i82801gx/i82801gx.h16
-rw-r--r--src/southbridge/intel/i82801gx/smbus.c148
-rw-r--r--src/southbridge/intel/i82801gx/smbus.h92
-rw-r--r--src/southbridge/intel/i82801ix/Kconfig1
-rw-r--r--src/southbridge/intel/i82801ix/early_smbus.c2
-rw-r--r--src/southbridge/intel/i82801ix/i82801ix.h16
-rw-r--r--src/southbridge/intel/i82801ix/smbus.c3
-rw-r--r--src/southbridge/intel/i82801ix/smbus.h140
-rw-r--r--src/southbridge/intel/i82801jx/Kconfig1
-rw-r--r--src/southbridge/intel/i82801jx/early_smbus.c2
-rw-r--r--src/southbridge/intel/i82801jx/i82801jx.h16
-rw-r--r--src/southbridge/intel/i82801jx/smbus.c3
-rw-r--r--src/southbridge/intel/i82801jx/smbus.h140
-rw-r--r--src/southbridge/intel/ibexpeak/Kconfig1
-rw-r--r--src/southbridge/intel/ibexpeak/early_smbus.c2
-rw-r--r--src/southbridge/intel/ibexpeak/pch.h16
-rw-r--r--src/southbridge/intel/ibexpeak/smbus.c2
-rw-r--r--src/southbridge/intel/ibexpeak/smbus.h241
-rw-r--r--src/southbridge/intel/lynxpoint/Kconfig1
-rw-r--r--src/southbridge/intel/lynxpoint/early_smbus.c2
-rw-r--r--src/southbridge/intel/lynxpoint/pch.h16
-rw-r--r--src/southbridge/intel/lynxpoint/smbus.c50
-rw-r--r--src/southbridge/intel/lynxpoint/smbus.h95
66 files changed, 469 insertions, 2161 deletions
diff --git a/src/southbridge/intel/bd82x6x/Kconfig b/src/southbridge/intel/bd82x6x/Kconfig
index 6522cce848..c24c71c30f 100644
--- a/src/southbridge/intel/bd82x6x/Kconfig
+++ b/src/southbridge/intel/bd82x6x/Kconfig
@@ -25,6 +25,7 @@ config SOUTH_BRIDGE_OPTIONS # dummy
def_bool y
select ACPI_INTEL_HARDWARE_SLEEP_VALUES
select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
select IOAPIC
select HAVE_HARD_RESET
select HAVE_USBDEBUG_OPTIONS
diff --git a/src/southbridge/intel/bd82x6x/early_smbus.c b/src/southbridge/intel/bd82x6x/early_smbus.c
index 9f74fdd45f..4c67aea29c 100644
--- a/src/southbridge/intel/bd82x6x/early_smbus.c
+++ b/src/southbridge/intel/bd82x6x/early_smbus.c
@@ -18,8 +18,8 @@
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
+#include <southbridge/intel/common/smbus.h>
#include "pch.h"
-#include "smbus.h"
void enable_smbus(void)
{
diff --git a/src/southbridge/intel/bd82x6x/pch.h b/src/southbridge/intel/bd82x6x/pch.h
index 0ae9826989..dcd7b2e130 100644
--- a/src/southbridge/intel/bd82x6x/pch.h
+++ b/src/southbridge/intel/bd82x6x/pch.h
@@ -265,22 +265,6 @@ early_usb_init (const struct southbridge_usb_port *portmap);
#define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0)
-/* SMBus I/O bits. */
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-#define SMBTRNSADD 0x9
-#define SMBSLVDATA 0xa
-#define SMLINK_PIN_CTL 0xe
-#define SMBUS_PIN_CTL 0xf
-
-#define SMBUS_TIMEOUT (10 * 1000 * 100)
-
-
/* Southbridge IO BARs */
#define GPIOBASE 0x48
diff --git a/src/southbridge/intel/bd82x6x/smbus.c b/src/southbridge/intel/bd82x6x/smbus.c
index c450d9b555..6cbdef987e 100644
--- a/src/southbridge/intel/bd82x6x/smbus.c
+++ b/src/southbridge/intel/bd82x6x/smbus.c
@@ -22,8 +22,8 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
+#include <southbridge/intel/common/smbus.h>
#include "pch.h"
-#include "smbus.h"
static void pch_smbus_init(device_t dev)
{
@@ -54,49 +54,6 @@ static int lsmbus_read_byte(device_t dev, u8 address)
return do_smbus_read_byte(res->base, device, address);
}
-static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data)
-{
- unsigned char global_status_register;
-
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(data, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- if (global_status_register != (1 << 1))
- return SMBUS_ERROR;
-
- return 0;
-}
-
static int lsmbus_write_byte(device_t dev, u8 address, u8 val)
{
u16 device;
diff --git a/src/southbridge/intel/bd82x6x/smbus.h b/src/southbridge/intel/bd82x6x/smbus.h
deleted file mode 100644
index 0978963723..0000000000
--- a/src/southbridge/intel/bd82x6x/smbus.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
- * Copyright (C) 2009 coresystems GmbH
- *
- * 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.
- */
-
-#include <device/smbus_def.h>
-#include "pch.h"
-
-static void smbus_delay(void)
-{
- inb(0x80);
-}
-
-static int smbus_wait_until_ready(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while (byte & 1);
- return loops ? 0 : -1;
-}
-
-static int smbus_wait_until_done(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
- return loops ? 0 : -1;
-}
-
-static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address)
-{
- unsigned char global_status_register;
- unsigned char byte;
-
- if (smbus_wait_until_ready(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
- }
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(0, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
- }
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- byte = inb(smbus_base + SMBHSTDAT0);
- if (global_status_register != (1 << 1)) {
- return SMBUS_ERROR;
- }
- return byte;
-}
diff --git a/src/southbridge/intel/common/Kconfig b/src/southbridge/intel/common/Kconfig
index 7bc686defa..23fb8cea5b 100644
--- a/src/southbridge/intel/common/Kconfig
+++ b/src/southbridge/intel/common/Kconfig
@@ -2,3 +2,5 @@ config SOUTHBRIDGE_INTEL_COMMON
def_bool n
config SOUTHBRIDGE_INTEL_COMMON_GPIO
def_bool n
+config SOUTHBRIDGE_INTEL_COMMON_SMBUS
+ def_bool n
diff --git a/src/southbridge/intel/common/Makefile.inc b/src/southbridge/intel/common/Makefile.inc
index 56ba56fc01..5810394bcb 100644
--- a/src/southbridge/intel/common/Makefile.inc
+++ b/src/southbridge/intel/common/Makefile.inc
@@ -24,4 +24,8 @@ ramstage-$(CONFIG_USBDEBUG) += usb_debug.c
romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c
ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c
smm-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c
+
+romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SMBUS) += smbus.c
+ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SMBUS) += smbus.c
+
endif
diff --git a/src/southbridge/intel/common/smbus.c b/src/southbridge/intel/common/smbus.c
new file mode 100644
index 0000000000..cac9ba7943
--- /dev/null
+++ b/src/southbridge/intel/common/smbus.c
@@ -0,0 +1,365 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
+ * Copyright (C) 2009 coresystems GmbH
+ * Copyright (C) 2013 Vladimir Serbinenko
+ *
+ * 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.
+ */
+
+#include <arch/io.h>
+#include <device/smbus_def.h>
+#include "smbus.h"
+
+
+/* I801 command constants */
+#define I801_QUICK (0 << 2)
+#define I801_BYTE (1 << 2)
+#define I801_BYTE_DATA (2 << 2)
+#define I801_WORD_DATA (3 << 2)
+#define I801_BLOCK_DATA (5 << 2)
+#define I801_I2C_BLOCK_DATA (6 << 2) /* ICH5 and later */
+
+/* I801 Host Control register bits */
+#define SMBHSTCNT_INTREN (1 << 0)
+#define SMBHSTCNT_KILL (1 << 1)
+#define SMBHSTCNT_LAST_BYTE (1 << 5)
+#define SMBHSTCNT_START (1 << 6)
+#define SMBHSTCNT_PEC_EN (1 << 7) /* ICH3 and later */
+
+/* I801 Hosts Status register bits */
+#define SMBHSTSTS_BYTE_DONE (1 << 7)
+#define SMBHSTSTS_INUSE_STS (1 << 6)
+#define SMBHSTSTS_SMBALERT_STS (1 << 5)
+#define SMBHSTSTS_FAILED (1 << 4)
+#define SMBHSTSTS_BUS_ERR (1 << 3)
+#define SMBHSTSTS_DEV_ERR (1 << 2)
+#define SMBHSTSTS_INTR (1 << 1)
+#define SMBHSTSTS_HOST_BUSY (1 << 0)
+
+#define SMBUS_TIMEOUT (10 * 1000 * 100)
+
+static void smbus_delay(void)
+{
+ inb(0x80);
+}
+
+static int smbus_wait_until_ready(u16 smbus_base)
+{
+ unsigned int loops = SMBUS_TIMEOUT;
+ unsigned char byte;
+ do {
+ smbus_delay();
+ if (--loops == 0)
+ break;
+ byte = inb(smbus_base + SMBHSTSTAT);
+ } while (byte & SMBHSTSTS_HOST_BUSY);
+ return loops ? 0 : -1;
+}
+
+static int smbus_wait_until_done(u16 smbus_base)
+{
+ unsigned int loops = SMBUS_TIMEOUT;
+ unsigned char byte;
+ do {
+ smbus_delay();
+ if (--loops == 0)
+ break;
+ byte = inb(smbus_base + SMBHSTSTAT);
+ } while ((byte & SMBHSTSTS_HOST_BUSY)
+ || (byte & ~(SMBHSTSTS_INUSE_STS | SMBHSTSTS_HOST_BUSY)) == 0);
+ return loops ? 0 : -1;
+}
+
+static int smbus_wait_until_active(u16 smbus_base)
+{
+ unsigned long loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ unsigned char val;
+ smbus_delay();
+ val = inb(smbus_base + SMBHSTSTAT);
+ if ((val & SMBHSTSTS_HOST_BUSY)) {
+ break;
+ }
+ } while (--loops);
+ return loops ? 0 : -1;
+}
+
+int do_smbus_read_byte(unsigned int smbus_base, u8 device,
+ unsigned int address)
+{
+ unsigned char status;
+ unsigned char byte;
+
+ if (smbus_wait_until_ready(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+ /* Set up transaction */
+ /* Disable interrupts */
+ outb(inb(smbus_base + SMBHSTCTL) & ~SMBHSTCNT_INTREN,
+ smbus_base + SMBHSTCTL);
+ /* Set the device I'm talking too */
+ outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
+ /* Set the command/address... */
+ outb(address & 0xff, smbus_base + SMBHSTCMD);
+ /* Set up for a byte data read */
+ outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | I801_BYTE_DATA,
+ (smbus_base + SMBHSTCTL));
+ /* Clear any lingering errors, so the transaction will run */
+ outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
+
+ /* Clear the data byte... */
+ outb(0, smbus_base + SMBHSTDAT0);
+
+ /* Start the command */
+ outb((inb(smbus_base + SMBHSTCTL) | SMBHSTCNT_START),
+ smbus_base + SMBHSTCTL);
+
+ /* poll for it to start */
+ if (smbus_wait_until_active(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT;
+
+ /* Poll for transaction completion */
+ if (smbus_wait_until_done(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
+
+ status = inb(smbus_base + SMBHSTSTAT);
+
+ /* Ignore the "In Use" status... */
+ status &= ~(SMBHSTSTS_SMBALERT_STS | SMBHSTSTS_INUSE_STS);
+
+ /* Read results of transaction */
+ byte = inb(smbus_base + SMBHSTDAT0);
+ if (status != SMBHSTSTS_INTR)
+ return SMBUS_ERROR;
+ return byte;
+}
+
+int do_smbus_write_byte(unsigned int smbus_base, u8 device,
+ unsigned int address, unsigned int data)
+{
+ unsigned char status;
+
+ if (smbus_wait_until_ready(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+
+ /* Set up transaction */
+ /* Disable interrupts */
+ outb(inb(smbus_base + SMBHSTCTL) & ~SMBHSTCNT_INTREN,
+ smbus_base + SMBHSTCTL);
+ /* Set the device I'm talking too */
+ outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
+ /* Set the command/address... */
+ outb(address & 0xff, smbus_base + SMBHSTCMD);
+ /* Set up for a byte data read */
+ outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | I801_BYTE_DATA,
+ (smbus_base + SMBHSTCTL));
+ /* Clear any lingering errors, so the transaction will run */
+ outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
+
+ /* Clear the data byte... */
+ outb(data, smbus_base + SMBHSTDAT0);
+
+ /* Start the command */
+ outb((inb(smbus_base + SMBHSTCTL) | SMBHSTCNT_START),
+ smbus_base + SMBHSTCTL);
+
+ /* poll for it to start */
+ if (smbus_wait_until_active(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT;
+
+ /* Poll for transaction completion */
+ if (smbus_wait_until_done(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
+
+ status = inb(smbus_base + SMBHSTSTAT);
+
+ /* Ignore the "In Use" status... */
+ status &= ~(SMBHSTSTS_SMBALERT_STS | SMBHSTSTS_INUSE_STS);
+
+ /* Read results of transaction */
+ if (status != SMBHSTSTS_INTR)
+ return SMBUS_ERROR;
+
+ return 0;
+}
+
+int do_smbus_block_read(unsigned int smbus_base, u8 device, u8 cmd,
+ unsigned int bytes, u8 *buf)
+{
+ u8 status;
+ int bytes_read = 0;
+ unsigned int loops = SMBUS_TIMEOUT;
+ if (smbus_wait_until_ready(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+
+ /* Set up transaction */
+ /* Disable interrupts */
+ outb(inb(smbus_base + SMBHSTCTL) & ~SMBHSTCNT_INTREN,
+ smbus_base + SMBHSTCTL);
+ /* Set the device I'm talking too */
+ outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
+ /* Set the command/address... */
+ outb(cmd & 0xff, smbus_base + SMBHSTCMD);
+ /* Set up for a block data read */
+ outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | I801_BLOCK_DATA,
+ (smbus_base + SMBHSTCTL));
+ /* Clear any lingering errors, so the transaction will run */
+ outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
+
+ /* Start the command */
+ outb((inb(smbus_base + SMBHSTCTL) | SMBHSTCNT_START),
+ smbus_base + SMBHSTCTL);
+
+ /* poll for it to start */
+ if (smbus_wait_until_active(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT;
+
+ /* Poll for transaction completion */
+ do {
+ loops--;
+ status = inb(smbus_base + SMBHSTSTAT);
+ if (status & (SMBHSTSTS_FAILED | /* FAILED */
+ SMBHSTSTS_BUS_ERR | /* BUS ERR */
+ SMBHSTSTS_DEV_ERR)) /* DEV ERR */
+ return SMBUS_ERROR;
+
+ if (status & SMBHSTSTS_BYTE_DONE) { /* Byte done */
+ *buf = inb(smbus_base + SMBBLKDAT);
+ buf++;
+ bytes_read++;
+ if (--bytes == 1) {
+ /* indicate that next byte is the last one */
+ outb(inb(smbus_base + SMBHSTCTL)
+ | SMBHSTCNT_LAST_BYTE,
+ smbus_base + SMBHSTCTL);
+ }
+ outb(status, smbus_base + SMBHSTSTAT);
+ }
+ } while ((status & SMBHSTSTS_HOST_BUSY) && loops);
+
+ return bytes_read;
+}
+
+int do_smbus_block_write(unsigned int smbus_base, u8 device, u8 cmd,
+ unsigned int bytes, const u8 *buf)
+{
+ u8 status;
+ unsigned int loops = SMBUS_TIMEOUT;
+
+ if (smbus_wait_until_ready(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+
+ /* Set up transaction */
+ /* Disable interrupts */
+ outb(inb(smbus_base + SMBHSTCTL) & ~SMBHSTCNT_INTREN,
+ smbus_base + SMBHSTCTL);
+ /* Set the device I'm talking too */
+ outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
+ /* Set the command/address... */
+ outb(cmd & 0xff, smbus_base + SMBHSTCMD);
+ /* Set up for a block data write */
+ outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | I801_BLOCK_DATA,
+ (smbus_base + SMBHSTCTL));
+ /* Clear any lingering errors, so the transaction will run */
+ outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
+
+ /* set number of bytes to transfer */
+ outb(bytes, smbus_base + SMBHSTDAT0);
+
+ outb(*buf++, smbus_base + SMBBLKDAT);
+ bytes--;
+
+ /* Start the command */
+ outb((inb(smbus_base + SMBHSTCTL) | SMBHSTCNT_START),
+ smbus_base + SMBHSTCTL);
+
+ /* poll for it to start */
+ if (smbus_wait_until_active(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT;
+
+ /* Poll for transaction completion */
+ do {
+ loops--;
+ status = inb(smbus_base + SMBHSTSTAT);
+ if (status & (SMBHSTSTS_FAILED | /* FAILED */
+ SMBHSTSTS_BUS_ERR | /* BUS ERR */
+ SMBHSTSTS_DEV_ERR)) /* DEV ERR */
+ return SMBUS_ERROR;
+
+ if (status & SMBHSTSTS_BYTE_DONE) {
+ outb(*buf++, smbus_base + SMBBLKDAT);
+ outb(status, smbus_base + SMBHSTSTAT);
+ }
+ } while ((status & SMBHSTSTS_HOST_BUSY) && loops);
+
+ return 0;
+}
+
+/* Only since ICH5 */
+int do_i2c_block_read(unsigned int smbus_base, u8 device,
+ unsigned int offset, u32 bytes, u8 *buf)
+{
+ u8 status;
+ int bytes_read = 0;
+ unsigned int loops = SMBUS_TIMEOUT;
+ if (smbus_wait_until_ready(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+
+ /* Set upp transaction */
+ /* Disable interrupts */
+ outb(inb(smbus_base + SMBHSTCTL) & SMBHSTCNT_INTREN,
+ smbus_base + SMBHSTCTL);
+ /* Set the device I'm talking to */
+ outb((device & 0x7f) << 1, smbus_base + SMBXMITADD);
+
+ /* device offset */
+ outb(offset, smbus_base + SMBHSTDAT1);
+
+ /* Set up for a i2c block data read */
+ outb((inb(smbus_base + SMBHSTCTL) & 0xc3) | I801_I2C_BLOCK_DATA,
+ (smbus_base + SMBHSTCTL));
+
+ /* Clear any lingering errors, so the transaction will run */
+ outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
+ /* Start the command */
+ outb((inb(smbus_base + SMBHSTCTL) | SMBHSTCNT_START),
+ smbus_base + SMBHSTCTL);
+
+ /* poll for it to start */
+ if (smbus_wait_until_active(smbus_base) < 0)
+ return SMBUS_WAIT_UNTIL_ACTIVE_TIMEOUT;
+
+ /* Poll for transaction completion */
+ do {
+ loops--;
+ status = inb(smbus_base + SMBHSTSTAT);
+ if (status & (SMBHSTSTS_FAILED | /* FAILED */
+ SMBHSTSTS_BUS_ERR | /* BUS ERR */
+ SMBHSTSTS_DEV_ERR)) /* DEV ERR */
+ return SMBUS_ERROR;
+
+ if (status & SMBHSTSTS_BYTE_DONE) {
+ *buf = inb(smbus_base + SMBBLKDAT);
+ buf++;
+ bytes_read++;
+ if (--bytes == 1) {
+ /* indicate that next byte is the last one */
+ outb(inb(smbus_base + SMBHSTCTL)
+ | SMBHSTCNT_LAST_BYTE,
+ smbus_base + SMBHSTCTL);
+ }
+ outb(status, smbus_base + SMBHSTSTAT);
+ }
+ } while ((status & SMBHSTSTS_HOST_BUSY) && loops);
+
+ return bytes_read;
+}
diff --git a/src/southbridge/intel/common/smbus.h b/src/southbridge/intel/common/smbus.h
new file mode 100644
index 0000000000..f2e903c82b
--- /dev/null
+++ b/src/southbridge/intel/common/smbus.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
+ * Copyright (C) 2009 coresystems GmbH
+ * Copyright (C) 2013 Vladimir Serbinenko
+ *
+ * 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.
+ */
+
+#ifndef INTEL_COMMON_SMBUS_H
+#define INTEL_COMMON_SMBUS_H
+
+/* SMBus register offsets. */
+#define SMBHSTSTAT 0x0
+#define SMBHSTCTL 0x2
+#define SMBHSTCMD 0x3
+#define SMBXMITADD 0x4
+#define SMBHSTDAT0 0x5
+#define SMBHSTDAT1 0x6
+#define SMBBLKDAT 0x7
+#define SMBTRNSADD 0x9
+#define SMBSLVDATA 0xa
+#define SMLINK_PIN_CTL 0xe
+#define SMBUS_PIN_CTL 0xf
+#define SMBSLVCMD 0x11
+
+int do_smbus_read_byte(unsigned int smbus_base, u8 device,
+ unsigned int address);
+int do_smbus_write_byte(unsigned int smbus_base, u8 device,
+ unsigned int address, unsigned int data);
+int do_smbus_block_read(unsigned int smbus_base, u8 device,
+ u8 cmd, unsigned int bytes, u8 *buf);
+int do_smbus_block_write(unsigned int smbus_base, u8 device,
+ u8 cmd, unsigned int bytes, const u8 *buf);
+/* Only since ICH5 */
+int do_i2c_block_read(unsigned int smbus_base, u8 device,
+ unsigned int offset, u32 bytes, u8 *buf);
+#endif
diff --git a/src/southbridge/intel/fsp_bd82x6x/Kconfig b/src/southbridge/intel/fsp_bd82x6x/Kconfig
index 516362c773..cebd96d69a 100644
--- a/src/southbridge/intel/fsp_bd82x6x/Kconfig
+++ b/src/southbridge/intel/fsp_bd82x6x/Kconfig
@@ -31,6 +31,8 @@ config SOUTH_BRIDGE_OPTIONS # dummy
select SPI_FLASH
select COMMON_FADT
select HAVE_INTEL_FIRMWARE
+ select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
config EHCI_BAR
hex
diff --git a/src/southbridge/intel/fsp_i89xx/Kconfig b/src/southbridge/intel/fsp_i89xx/Kconfig
index 9dfbbf7169..67c2665e66 100644
--- a/src/southbridge/intel/fsp_i89xx/Kconfig
+++ b/src/southbridge/intel/fsp_i89xx/Kconfig
@@ -32,6 +32,8 @@ config SOUTH_BRIDGE_OPTIONS # dummy
select COMMON_FADT
select HAVE_INTEL_FIRMWARE
select NO_EARLY_BOOTBLOCK_POSTCODES
+ select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
config EHCI_BAR
hex
diff --git a/src/southbridge/intel/fsp_i89xx/early_smbus.c b/src/southbridge/intel/fsp_i89xx/early_smbus.c
index 0d41d5eaf2..1451179915 100644
--- a/src/southbridge/intel/fsp_i89xx/early_smbus.c
+++ b/src/southbridge/intel/fsp_i89xx/early_smbus.c
@@ -19,8 +19,8 @@
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
+#include <southbridge/intel/common/smbus.h>
#include "pch.h"
-#include "smbus.h"
void enable_smbus(void)
{
diff --git a/src/southbridge/intel/fsp_i89xx/pch.h b/src/southbridge/intel/fsp_i89xx/pch.h
index 9ae9467a7a..447178865c 100644
--- a/src/southbridge/intel/fsp_i89xx/pch.h
+++ b/src/southbridge/intel/fsp_i89xx/pch.h
@@ -174,22 +174,6 @@ void early_pch_init(void);
#define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0)
-/* SMBus I/O bits. */
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-#define SMBTRNSADD 0x9
-#define SMBSLVDATA 0xa
-#define SMLINK_PIN_CTL 0xe
-#define SMBUS_PIN_CTL 0xf
-
-#define SMBUS_TIMEOUT (10 * 1000 * 100)
-
-
/* Southbridge IO BARs */
#define GPIOBASE 0x48
diff --git a/src/southbridge/intel/fsp_i89xx/smbus.h b/src/southbridge/intel/fsp_i89xx/smbus.h
deleted file mode 100644
index 92b05b78c2..0000000000
--- a/src/southbridge/intel/fsp_i89xx/smbus.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
- * Copyright (C) 2009 coresystems GmbH
- *
- * 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.
- */
-
-#include <device/smbus_def.h>
-#include "pch.h"
-#include <delay.h>
-
-static int smbus_wait_until_ready(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- udelay(1);
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while (byte & 1);
- return loops ? 0 : -1;
-}
-
-static int smbus_wait_until_done(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- udelay(1);
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
- return loops ? 0 : -1;
-}
-
-static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address)
-{
- unsigned char global_status_register;
- unsigned char byte;
-
- if (smbus_wait_until_ready(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
- }
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(0, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
- }
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- byte = inb(smbus_base + SMBHSTDAT0);
- if (global_status_register != (1 << 1)) {
- return SMBUS_ERROR;
- }
- return byte;
-}
diff --git a/src/southbridge/intel/fsp_rangeley/Kconfig b/src/southbridge/intel/fsp_rangeley/Kconfig
index 092cf1dd63..4d2e89f316 100644
--- a/src/southbridge/intel/fsp_rangeley/Kconfig
+++ b/src/southbridge/intel/fsp_rangeley/Kconfig
@@ -30,6 +30,8 @@ config SOUTH_BRIDGE_OPTIONS # dummy
select PCIEXP_COMMON_CLOCK
select SPI_FLASH
select HAVE_INTEL_FIRMWARE
+ select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
config EHCI_BAR
hex
diff --git a/src/southbridge/intel/fsp_rangeley/early_smbus.c b/src/southbridge/intel/fsp_rangeley/early_smbus.c
index f27fa87d38..84b750e228 100644
--- a/src/southbridge/intel/fsp_rangeley/early_smbus.c
+++ b/src/southbridge/intel/fsp_rangeley/early_smbus.c
@@ -18,8 +18,8 @@
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
+#include <southbridge/intel/common/smbus.h>
#include "soc.h"
-#include "smbus.h"
void enable_smbus(void)
{
diff --git a/src/southbridge/intel/fsp_rangeley/smbus.c b/src/southbridge/intel/fsp_rangeley/smbus.c
index 9a4d86708c..9ea8126222 100644
--- a/src/southbridge/intel/fsp_rangeley/smbus.c
+++ b/src/southbridge/intel/fsp_rangeley/smbus.c
@@ -22,8 +22,8 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
+#include <southbridge/intel/common/smbus.h>
#include "soc.h"
-#include "smbus.h"
static int lsmbus_read_byte(device_t dev, u8 address)
{
diff --git a/src/southbridge/intel/fsp_rangeley/smbus.h b/src/southbridge/intel/fsp_rangeley/smbus.h
deleted file mode 100644
index 39ba6dce16..0000000000
--- a/src/southbridge/intel/fsp_rangeley/smbus.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
- * Copyright (C) 2009 coresystems GmbH
- *
- * 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.
- */
-
-#include <device/smbus_def.h>
-#include "soc.h"
-
-static void smbus_delay(void)
-{
- inb(0x80);
-}
-
-static int smbus_wait_until_ready(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while (byte & 1);
- return loops ? 0 : -1;
-}
-
-static int smbus_wait_until_done(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
- return loops ? 0 : -1;
-}
-
-static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address)
-{
- unsigned char global_status_register;
- unsigned char byte;
-
- if (smbus_wait_until_ready(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
- }
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(0, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
- }
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- byte = inb(smbus_base + SMBHSTDAT0);
- if (global_status_register != (1 << 1)) {
- return SMBUS_ERROR;
- }
- return byte;
-}
diff --git a/src/southbridge/intel/fsp_rangeley/soc.h b/src/southbridge/intel/fsp_rangeley/soc.h
index 4409f1e5f2..764bf97ca4 100644
--- a/src/southbridge/intel/fsp_rangeley/soc.h
+++ b/src/southbridge/intel/fsp_rangeley/soc.h
@@ -176,21 +176,6 @@ void rangeley_sb_early_initialization(void);
#define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0)
-/* SMBus I/O bits. */
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-#define SMBTRNSADD 0x9
-#define SMBSLVDATA 0xa
-#define SMLINK_PIN_CTL 0xe
-#define SMBUS_PIN_CTL 0xf
-
-#define SMBUS_TIMEOUT (10 * 1000 * 100)
-
/* Root Complex Register Block */
#define RCBA 0xf0
#define RCBA_ENABLE 0x01
diff --git a/src/southbridge/intel/i3100/Kconfig b/src/southbridge/intel/i3100/Kconfig
index 1dd0931779..20990ba289 100644
--- a/src/southbridge/intel/i3100/Kconfig
+++ b/src/southbridge/intel/i3100/Kconfig
@@ -2,6 +2,8 @@ config SOUTHBRIDGE_INTEL_I3100
bool
select IOAPIC
select HAVE_HARD_RESET
+ select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
if SOUTHBRIDGE_INTEL_I3100
diff --git a/src/southbridge/intel/i3100/early_smbus.c b/src/southbridge/intel/i3100/early_smbus.c
index 35c32a41c1..35fe614d8e 100644
--- a/src/southbridge/intel/i3100/early_smbus.c
+++ b/src/southbridge/intel/i3100/early_smbus.c
@@ -14,7 +14,7 @@
*
*/
-#include "smbus.h"
+#include <southbridge/intel/common/smbus.h>
#define SMBUS_IO_BASE 0x0f00
diff --git a/src/southbridge/intel/i3100/smbus.c b/src/southbridge/intel/i3100/smbus.c
index 32cf709b0c..850982adc5 100644
--- a/src/southbridge/intel/i3100/smbus.c
+++ b/src/southbridge/intel/i3100/smbus.c
@@ -21,8 +21,8 @@
#include <device/pci_ops.h>
#include <device/smbus.h>
#include <arch/io.h>
+#include <southbridge/intel/common/smbus.h>
#include "i3100.h"
-#include "smbus.h"
static int lsmbus_read_byte(device_t dev, u8 address)
{
diff --git a/src/southbridge/intel/i3100/smbus.h b/src/southbridge/intel/i3100/smbus.h
deleted file mode 100644
index 0b2f0601f1..0000000000
--- a/src/southbridge/intel/i3100/smbus.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2008 Arastra, 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.
- */
-
-/* This code is based on src/southbridge/intel/esb6300/esb6300_smbus.h */
-
-#include <device/smbus_def.h>
-
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-#define SMBTRNSADD 0x9
-#define SMBSLVDATA 0xa
-#define SMLINK_PIN_CTL 0xe
-#define SMBUS_PIN_CTL 0xf
-#define SMBSLVCMD 0x11
-
-#define SMBUS_TIMEOUT (100*1000*10)
-
-static void smbus_delay(void)
-{
- outb(0x80, 0x80);
-}
-
-static 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;
-}
-
-static 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;
-}
-
-static 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) | 1, 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;
-}
-
-static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data)
-{
- unsigned char global_status_register;
-
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(data, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- if (global_status_register != (1 << 1))
- return SMBUS_ERROR;
-
- return 0;
-}
diff --git a/src/southbridge/intel/i82371eb/Kconfig b/src/southbridge/intel/i82371eb/Kconfig
index 5466b12d50..f22c6e90fc 100644
--- a/src/southbridge/intel/i82371eb/Kconfig
+++ b/src/southbridge/intel/i82371eb/Kconfig
@@ -1,4 +1,6 @@
config SOUTHBRIDGE_INTEL_I82371EB
+ select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
bool
config BOOTBLOCK_SOUTHBRIDGE_INIT
diff --git a/src/southbridge/intel/i82371eb/early_smbus.c b/src/southbridge/intel/i82371eb/early_smbus.c
index af6b14b643..89ed9c8e57 100644
--- a/src/southbridge/intel/i82371eb/early_smbus.c
+++ b/src/southbridge/intel/i82371eb/early_smbus.c
@@ -19,8 +19,8 @@
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
+#include <southbridge/intel/common/smbus.h>
#include "i82371eb.h"
-#include "smbus.h"
void enable_smbus(void)
{
@@ -46,7 +46,7 @@ void enable_smbus(void)
pci_write_config16(dev, PCI_COMMAND, reg16);
/* Clear any lingering errors, so the transaction will run. */
- outb(inb(SMBUS_IO_BASE + SMBHST_STATUS), SMBUS_IO_BASE + SMBHST_STATUS);
+ outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
}
int smbus_read_byte(u8 device, u8 address)
diff --git a/src/southbridge/intel/i82371eb/smbus.c b/src/southbridge/intel/i82371eb/smbus.c
index 9231402cd0..3477c52c32 100644
--- a/src/southbridge/intel/i82371eb/smbus.c
+++ b/src/southbridge/intel/i82371eb/smbus.c
@@ -24,8 +24,8 @@
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/smbus.h>
+#include <southbridge/intel/common/smbus.h>
#include "i82371eb.h"
-#include "smbus.h"
static void pwrmgt_enable(struct device *dev)
{
diff --git a/src/southbridge/intel/i82371eb/smbus.h b/src/southbridge/intel/i82371eb/smbus.h
deleted file mode 100644
index de34504aff..0000000000
--- a/src/southbridge/intel/i82371eb/smbus.h
+++ /dev/null
@@ -1,112 +0,0 @@
-#include <device/smbus_def.h>
-#include "i82371eb.h"
-
-#define SMBHST_STATUS 0x0
-#define SMBHST_CTL 0x2
-#define SMBHST_CMD 0x3
-#define SMBHST_ADDR 0x4
-#define SMBHST_DAT 0x5
-
-#define SMBUS_TIMEOUT (100*1000*10)
-#define SMBUS_STATUS_MASK 0x1e
-#define SMBUS_ERROR_FLAG (1<<2)
-
-int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address);
-
-static inline void smbus_delay(void)
-{
- outb(0x80, 0x80);
- outb(0x80, 0x80);
- outb(0x80, 0x80);
- outb(0x80, 0x80);
- outb(0x80, 0x80);
- outb(0x80, 0x80);
-}
-
-static int smbus_wait_until_ready(unsigned smbus_io_base)
-{
- unsigned long loops;
- loops = SMBUS_TIMEOUT;
- do {
- unsigned char val;
- smbus_delay();
- val = inb(smbus_io_base + SMBHST_STATUS);
- if ((val & 0x1) == 0) {
- break;
- }
-#if 0
- if (loops == (SMBUS_TIMEOUT / 2)) {
- outw(inw(smbus_io_base + SMBHST_STATUS),
- smbus_io_base + SMBHST_STATUS);
- }
-#endif
- } while (--loops);
- return loops?0:SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-}
-
-static int smbus_wait_until_done(unsigned smbus_io_base)
-{
- unsigned long loops;
- loops = SMBUS_TIMEOUT;
- do {
- unsigned short val;
- smbus_delay();
-
- val = inb(smbus_io_base + SMBHST_STATUS);
- // Make sure the command is done
- if ((val & 0x1) != 0) {
- continue;
- }
- // Don't break out until one of the interrupt
- // flags is set.
- if (val & 0xfe) {
- break;
- }
- } while (--loops);
- return loops?0:SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
-}
-
-int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
-{
- unsigned status_register;
- unsigned byte;
-
- if (smbus_wait_until_ready(smbus_io_base) < 0) {
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
- }
-
- /* setup transaction */
-
- /* clear any lingering errors, so the transaction will run */
- outb(0x1e, smbus_io_base + SMBHST_STATUS);
-
- /* set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHST_ADDR);
-
- /* set the command/address... */
- outb(address & 0xff, smbus_io_base + SMBHST_CMD);
-
- /* clear the data word...*/
- outb(0, smbus_io_base + SMBHST_DAT);
-
- /* start a byte read with interrupts disabled */
- outb( (0x02 << 2)|(1<<6), smbus_io_base + SMBHST_CTL);
-
- /* poll for transaction completion */
- if (smbus_wait_until_done(smbus_io_base) < 0) {
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
- }
-
- status_register = inw(smbus_io_base + SMBHST_STATUS);
-
- /* read results of transaction */
- byte = inw(smbus_io_base + SMBHST_DAT) & 0xff;
-
- if (status_register & 0x04) {
-#if 0
- printk(BIOS_DEBUG, "Read fail %04x\n", status_register);
-#endif
- return SMBUS_ERROR;
- }
- return byte;
-}
diff --git a/src/southbridge/intel/i82801ax/Kconfig b/src/southbridge/intel/i82801ax/Kconfig
index 740c69dd00..cade3f5f82 100644
--- a/src/southbridge/intel/i82801ax/Kconfig
+++ b/src/southbridge/intel/i82801ax/Kconfig
@@ -18,3 +18,5 @@ config SOUTHBRIDGE_INTEL_I82801AX
select IOAPIC
select HAVE_HARD_RESET
select USE_WATCHDOG_ON_BOOT
+ select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
diff --git a/src/southbridge/intel/i82801ax/early_smbus.c b/src/southbridge/intel/i82801ax/early_smbus.c
index 2a224bffd6..836721b6a8 100644
--- a/src/southbridge/intel/i82801ax/early_smbus.c
+++ b/src/southbridge/intel/i82801ax/early_smbus.c
@@ -20,8 +20,8 @@
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
+#include <southbridge/intel/common/smbus.h>
#include "i82801ax.h"
-#include "smbus.h"
void enable_smbus(void)
{
diff --git a/src/southbridge/intel/i82801ax/i82801ax.h b/src/southbridge/intel/i82801ax/i82801ax.h
index c6e505d25b..879c25a835 100644
--- a/src/southbridge/intel/i82801ax/i82801ax.h
+++ b/src/southbridge/intel/i82801ax/i82801ax.h
@@ -90,15 +90,4 @@ int smbus_read_byte(u8 device, u8 address);
#define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0)
-/* SMBus I/O registers. */
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-
-#define SMBUS_TIMEOUT (10 * 1000 * 100)
-
#endif
diff --git a/src/southbridge/intel/i82801ax/smbus.c b/src/southbridge/intel/i82801ax/smbus.c
index 54fa34f5a2..1e71a984a8 100644
--- a/src/southbridge/intel/i82801ax/smbus.c
+++ b/src/southbridge/intel/i82801ax/smbus.c
@@ -19,8 +19,8 @@
#include <device/pci.h>
#include <device/pci_ids.h>
#include <arch/io.h>
+#include <southbridge/intel/common/smbus.h>
#include "i82801ax.h"
-#include "smbus.h"
static int lsmbus_read_byte(device_t dev, u8 address)
{
diff --git a/src/southbridge/intel/i82801ax/smbus.h b/src/southbridge/intel/i82801ax/smbus.h
deleted file mode 100644
index 0ca7d8e282..0000000000
--- a/src/southbridge/intel/i82801ax/smbus.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- */
-
-#include <device/smbus_def.h>
-#include "i82801ax.h"
-
-int do_smbus_read_byte(u16 smbus_io_base, u8 device, u8 address);
-
-static void smbus_delay(void)
-{
- inb(0x80);
-}
-
-static int smbus_wait_until_ready(u16 smbus_io_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_io_base + SMBHSTSTAT);
- } while (byte & 1);
- return loops ? 0 : -1;
-}
-
-static int smbus_wait_until_done(u16 smbus_io_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char 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(u16 smbus_io_base, u8 device, u8 address)
-{
- unsigned char global_status_register;
- unsigned char 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) | 1, 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;
-}
diff --git a/src/southbridge/intel/i82801bx/Kconfig b/src/southbridge/intel/i82801bx/Kconfig
index f1423001b9..9d25cbf5da 100644
--- a/src/southbridge/intel/i82801bx/Kconfig
+++ b/src/southbridge/intel/i82801bx/Kconfig
@@ -18,3 +18,5 @@ config SOUTHBRIDGE_INTEL_I82801BX
select IOAPIC
select HAVE_HARD_RESET
select USE_WATCHDOG_ON_BOOT
+ select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
diff --git a/src/southbridge/intel/i82801bx/early_smbus.c b/src/southbridge/intel/i82801bx/early_smbus.c
index c038e0aba8..103e1a35d4 100644
--- a/src/southbridge/intel/i82801bx/early_smbus.c
+++ b/src/southbridge/intel/i82801bx/early_smbus.c
@@ -20,8 +20,8 @@
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
+#include <southbridge/intel/common/smbus.h>
#include "i82801bx.h"
-#include "smbus.h"
void enable_smbus(void)
{
diff --git a/src/southbridge/intel/i82801bx/i82801bx.h b/src/southbridge/intel/i82801bx/i82801bx.h
index 27888b881f..3ecfe72947 100644
--- a/src/southbridge/intel/i82801bx/i82801bx.h
+++ b/src/southbridge/intel/i82801bx/i82801bx.h
@@ -99,19 +99,4 @@ int smbus_read_byte(u8 device, u8 address);
#define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0)
-/* SMBus I/O registers. */
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-#define SMBTRNSADD 0x9
-#define SMBSLVDATA 0xa
-#define SMLINK_PIN_CTL 0xe
-#define SMBUS_PIN_CTL 0xf
-
-#define SMBUS_TIMEOUT (10 * 1000 * 100)
-
#endif /* SOUTHBRIDGE_INTEL_I82801BX_I82801BX_H */
diff --git a/src/southbridge/intel/i82801bx/smbus.c b/src/southbridge/intel/i82801bx/smbus.c
index 6cc05ca5c4..01e8c373e6 100644
--- a/src/southbridge/intel/i82801bx/smbus.c
+++ b/src/southbridge/intel/i82801bx/smbus.c
@@ -19,8 +19,8 @@
#include <device/pci.h>
#include <device/pci_ids.h>
#include <arch/io.h>
+#include <southbridge/intel/common/smbus.h>
#include "i82801bx.h"
-#include "smbus.h"
static int lsmbus_read_byte(device_t dev, u8 address)
{
diff --git a/src/southbridge/intel/i82801bx/smbus.h b/src/southbridge/intel/i82801bx/smbus.h
deleted file mode 100644
index ffb983ea04..0000000000
--- a/src/southbridge/intel/i82801bx/smbus.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
- *
- * 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; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- */
-
-#include <device/smbus_def.h>
-
-static void smbus_delay(void)
-{
- inb(0x80);
-}
-
-static int smbus_wait_until_ready(u16 smbus_io_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_io_base + SMBHSTSTAT);
- } while (byte & 1);
- return loops ? 0 : -1;
-}
-
-static int smbus_wait_until_done(u16 smbus_io_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char 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;
-}
-
-static int do_smbus_read_byte(u16 smbus_io_base, u8 device, u8 address)
-{
- unsigned char global_status_register;
- unsigned char 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) | 1, 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;
-}
diff --git a/src/southbridge/intel/i82801dx/Kconfig b/src/southbridge/intel/i82801dx/Kconfig
index 82db1c3752..35e597acbf 100644
--- a/src/southbridge/intel/i82801dx/Kconfig
+++ b/src/southbridge/intel/i82801dx/Kconfig
@@ -22,6 +22,8 @@ config SOUTHBRIDGE_INTEL_I82801DX
select HAVE_HARD_RESET
select HAVE_SMI_HANDLER
select HAVE_USBDEBUG
+ select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
if SOUTHBRIDGE_INTEL_I82801DX
diff --git a/src/southbridge/intel/i82801dx/early_smbus.c b/src/southbridge/intel/i82801dx/early_smbus.c
index 5bf87d8e91..fabb58b55b 100644
--- a/src/southbridge/intel/i82801dx/early_smbus.c
+++ b/src/southbridge/intel/i82801dx/early_smbus.c
@@ -17,6 +17,7 @@
#include <arch/io.h>
#include <device/pci_def.h>
#include <console/console.h>
+#include <southbridge/intel/common/smbus.h>
#include "i82801dx.h"
@@ -37,143 +38,7 @@ void enable_smbus(void)
outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
}
-static inline void smbus_delay(void)
+int smbus_read_byte(unsigned int device, unsigned int address)
{
- outb(0x80, 0x80);
+ return do_smbus_read_byte(SMBUS_IO_BASE, device, address);
}
-
-static int smbus_wait_until_active(void)
-{
- unsigned long loops;
- loops = SMBUS_TIMEOUT;
- do {
- unsigned char val;
- smbus_delay();
- val = inb(SMBUS_IO_BASE + SMBHSTSTAT);
- if ((val & 1)) {
- break;
- }
- } while (--loops);
- return loops ? 0 : -4;
-}
-
-static int smbus_wait_until_ready(void)
-{
- unsigned long loops;
- loops = SMBUS_TIMEOUT;
- do {
- unsigned char val;
- smbus_delay();
- val = inb(SMBUS_IO_BASE + SMBHSTSTAT);
- if ((val & 1) == 0) {
- break;
- }
- if (loops == (SMBUS_TIMEOUT / 2)) {
- outb(inb(SMBUS_IO_BASE + SMBHSTSTAT),
- SMBUS_IO_BASE + SMBHSTSTAT);
- }
- } while (--loops);
- return loops ? 0 : -2;
-}
-
-static int smbus_wait_until_done(void)
-{
- unsigned long loops;
- loops = SMBUS_TIMEOUT;
- do {
- unsigned char val;
- smbus_delay();
-
- val = inb(SMBUS_IO_BASE + SMBHSTSTAT);
- if ((val & 1) == 0) {
- break;
- }
- if ((val & ~((1 << 6) | (1 << 0))) != 0) {
- break;
- }
- } while (--loops);
- return loops ? 0 : -3;
-}
-
-int smbus_read_byte(unsigned device, unsigned address)
-{
- unsigned char global_status_register;
- unsigned char byte;
-
- /* printk(BIOS_ERR, "smbus_read_byte\n"); */
- if (smbus_wait_until_ready() < 0) {
- printk(BIOS_ERR, "SMBUS not ready (-2)\n");
- return -2;
- }
-
- /* setup transaction */
- /* disable interrupts */
- outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xfe, SMBUS_IO_BASE + SMBHSTCTL);
- /* set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, 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 a byte read, with interrupts disabled */
- outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40),
- SMBUS_IO_BASE + SMBHSTCTL);
- /* poll for it to start */
- if (smbus_wait_until_active() < 0) {
- printk(BIOS_ERR, "SMBUS not active (-4)\n");
- return -4;
- }
-
- /* poll for transaction completion */
- if (smbus_wait_until_done() < 0) {
- printk(BIOS_ERR, "SMBUS not completed (-3)\n");
- return -3;
- }
-
- global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT) & ~(1 << 6); /* Ignore the In Use Status... */
-
- /* read results of transaction */
- byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
-
- if (global_status_register != 2) {
- //printk(BIOS_SPEW, "%s: no device (%02x, %02x)\n", __func__, device, address);
- return -1;
- }
- //printk(BIOS_DEBUG, "%s: %02x@%02x = %02x\n", __func__, device, address, byte);
- return byte;
-}
-
-#if 0
-static void smbus_write_byte(unsigned device, unsigned address,
- unsigned char val)
-{
- if (smbus_wait_until_ready() < 0) {
- return;
- }
-
- /* by LYH */
- outb(0x37, SMBUS_IO_BASE + SMBHSTSTAT);
- /* set the device I'm talking too */
- outw(((device & 0x7f) << 1) | 0, SMBUS_IO_BASE + SMBHSTADDR);
-
- /* data to send */
- outb(val, SMBUS_IO_BASE + SMBHSTDAT);
-
- outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
-
- /* start the command */
- outb(0xa, SMBUS_IO_BASE + SMBHSTCTL);
-
- /* poll for transaction completion */
- smbus_wait_until_done();
- return;
-}
-#endif
diff --git a/src/southbridge/intel/i82801dx/i82801dx.h b/src/southbridge/intel/i82801dx/i82801dx.h
index 3ab0fda8b2..14ca28f9aa 100644
--- a/src/southbridge/intel/i82801dx/i82801dx.h
+++ b/src/southbridge/intel/i82801dx/i82801dx.h
@@ -116,23 +116,6 @@ int smbus_read_byte(unsigned device, unsigned address);
#define SMBUS_IO_BASE 0x1000
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-#define SMBTRNSADD 0x9
-#define SMBSLVDATA 0xa
-#define SMLINK_PIN_CTL 0xe
-#define SMBUS_PIN_CTL 0xf
-
-/* Between 1-10 seconds, We should never timeout normally
- * Longer than this is just painful when a timeout condition occurs.
- */
-#define SMBUS_TIMEOUT (100*1000)
-
#define PM1_STS 0x00
#define WAK_STS (1 << 15)
#define PCIEXPWAK_STS (1 << 14)
diff --git a/src/southbridge/intel/i82801dx/smbus.c b/src/southbridge/intel/i82801dx/smbus.c
deleted file mode 100644
index 441b45a98d..0000000000
--- a/src/southbridge/intel/i82801dx/smbus.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2004 Ronald G. Minnich
- *
- * 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.
- */
-
-#include "i82801dx.h"
-#include <smbus.h>
-#include <pci.h>
-#include <arch/io.h>
-
-#define PM_BUS 0
-#define PM_DEVFN PCI_DEVFN(0x1f,3)
-
-void smbus_enable(void)
-{
- unsigned char byte;
- /* iobase addr */
- pcibios_write_config_dword(PM_BUS, PM_DEVFN, 0x20, SMBUS_IO_BASE | 1);
- /* smbus enable */
- pcibios_write_config_byte(PM_BUS, PM_DEVFN, 0x40, 1);
- /* iospace enable */
- pcibios_write_config_word(PM_BUS, PM_DEVFN, 0x4, 1);
-
- /* Disable interrupt generation */
- outb(0, SMBUS_IO_BASE + SMBHSTCTL);
-
-}
-
-void smbus_setup(void)
-{
- outb(0, SMBUS_IO_BASE + SMBHSTSTAT);
-}
-
-static void smbus_wait_until_ready(void)
-{
- while ((inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1) == 1) {
- /* nop */
- }
-}
-
-static void smbus_wait_until_done(void)
-{
- unsigned char byte;
- do {
- byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
- }
- while ((byte & 1) == 1);
- while ((byte & ~1) == 0) {
- byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
- }
-}
-
-int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
-{
- unsigned char host_status_register;
- unsigned char byte;
-
- smbus_wait_until_ready();
-
- /* 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) | 1, SMBUS_IO_BASE + SMBHSTADD);
- /* 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 */
- smbus_wait_until_done();
-
- host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
-
- /* read results of transaction */
- byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
-
- *result = byte;
- return host_status_register != 0x02;
-}
diff --git a/src/southbridge/intel/i82801gx/Kconfig b/src/southbridge/intel/i82801gx/Kconfig
index b2265c4902..68c236299e 100644
--- a/src/southbridge/intel/i82801gx/Kconfig
+++ b/src/southbridge/intel/i82801gx/Kconfig
@@ -24,6 +24,7 @@ config SOUTHBRIDGE_INTEL_I82801GX
select HAVE_SMI_HANDLER
select COMMON_FADT
select SOUTHBRIDGE_INTEL_COMMON_GPIO
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
if SOUTHBRIDGE_INTEL_I82801GX
diff --git a/src/southbridge/intel/i82801gx/early_smbus.c b/src/southbridge/intel/i82801gx/early_smbus.c
index b8852e91ab..5d204e9527 100644
--- a/src/southbridge/intel/i82801gx/early_smbus.c
+++ b/src/southbridge/intel/i82801gx/early_smbus.c
@@ -18,8 +18,8 @@
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
+#include <southbridge/intel/common/smbus.h>
#include "i82801gx.h"
-#include "smbus.h"
void enable_smbus(void)
{
@@ -57,52 +57,5 @@ int smbus_read_byte(unsigned int device, unsigned int address)
int i2c_block_read(unsigned int device, unsigned int offset, u32 bytes, u8 *buf)
{
- u8 status;
- int bytes_read = 0;
- 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 to */
- outb((device & 0x7f) << 1, SMBUS_IO_BASE + SMBXMITADD);
-
- /* SPD offset */
- outb(offset, SMBUS_IO_BASE + SMBHSTDAT1);
-
- /* Set up for a i2c block data read */
- outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xc3) | (0x6 << 2),
- (SMBUS_IO_BASE + SMBHSTCTL));
-
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
- /* Start the command */
- outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40),
- SMBUS_IO_BASE + SMBHSTCTL);
-
- while (!(inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1))
- ;
- /* Poll for transaction completion */
- do {
- status = inb(SMBUS_IO_BASE + SMBHSTSTAT);
- if (status & ((1 << 4) | /* FAILED */
- (1 << 3) | /* BUS ERR */
- (1 << 2))) /* DEV ERR */
- return SMBUS_ERROR;
-
- if (status & 0x80) { /* Byte done */
- *buf = inb(SMBUS_IO_BASE + SMBBLKDAT);
- buf++;
- bytes_read++;
- if (--bytes == 1) {
- /* indicate that next byte is the last one */
- outb(inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x20,
- SMBUS_IO_BASE + SMBHSTCTL);
- }
- outb(status, SMBUS_IO_BASE + SMBHSTSTAT);
- }
- } while (status & 0x01);
-
- return bytes_read;
+ return do_i2c_block_read(SMBUS_IO_BASE, device, offset, bytes, buf);
}
diff --git a/src/southbridge/intel/i82801gx/i82801gx.h b/src/southbridge/intel/i82801gx/i82801gx.h
index 0dc4c0b9fd..d1c861ddeb 100644
--- a/src/southbridge/intel/i82801gx/i82801gx.h
+++ b/src/southbridge/intel/i82801gx/i82801gx.h
@@ -177,22 +177,6 @@ int southbridge_detect_s3_resume(void);
#define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0)
-/* SMBus I/O bits. */
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-#define SMBTRNSADD 0x9
-#define SMBSLVDATA 0xa
-#define SMLINK_PIN_CTL 0xe
-#define SMBUS_PIN_CTL 0xf
-
-#define SMBUS_TIMEOUT (10 * 1000 * 100)
-
-
/* Southbridge IO BARs */
#define GPIOBASE 0x48
diff --git a/src/southbridge/intel/i82801gx/smbus.c b/src/southbridge/intel/i82801gx/smbus.c
index d028f73367..fdf76a03e5 100644
--- a/src/southbridge/intel/i82801gx/smbus.c
+++ b/src/southbridge/intel/i82801gx/smbus.c
@@ -22,8 +22,8 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
+#include <southbridge/intel/common/smbus.h>
#include "i82801gx.h"
-#include "smbus.h"
static int lsmbus_read_byte(device_t dev, u8 address)
{
@@ -38,49 +38,6 @@ static int lsmbus_read_byte(device_t dev, u8 address)
return do_smbus_read_byte(res->base, device, address);
}
-static int do_smbus_write_byte(unsigned int smbus_base, unsigned int device,
- unsigned int address, unsigned int data)
-{
- unsigned char global_status_register;
-
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(data, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- if (global_status_register != (1 << 1))
- return SMBUS_ERROR;
- return 0;
-}
-
static int lsmbus_write_byte(device_t dev, u8 address, u8 data)
{
u16 device;
@@ -93,58 +50,6 @@ static int lsmbus_write_byte(device_t dev, u8 address, u8 data)
return do_smbus_write_byte(res->base, device, address, data);
}
-static int do_smbus_block_write(unsigned int smbus_base, unsigned int device,
- unsigned int cmd, unsigned int bytes, const u8 *buf)
-{
- u8 status;
-
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(cmd & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a block data write */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x5 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* set number of bytes to transfer */
- outb(bytes, smbus_base + SMBHSTDAT0);
-
- outb(*buf++, smbus_base + SMBBLKDAT);
- bytes--;
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- while (!(inb(smbus_base + SMBHSTSTAT) & 1))
- ;
- /* Poll for transaction completion */
- do {
- status = inb(smbus_base + SMBHSTSTAT);
- if (status & ((1 << 4) | /* FAILED */
- (1 << 3) | /* BUS ERR */
- (1 << 2))) /* DEV ERR */
- return SMBUS_ERROR;
-
- if (status & 0x80) { /* Byte done */
- outb(*buf++, smbus_base + SMBBLKDAT);
- outb(status, smbus_base + SMBHSTSTAT);
- }
- } while (status & 0x01);
-
- return 0;
-}
-
-
-
static int lsmbus_block_write(device_t dev, u8 cmd, u8 bytes, const u8 *buf)
{
u16 device;
@@ -157,57 +62,6 @@ static int lsmbus_block_write(device_t dev, u8 cmd, u8 bytes, const u8 *buf)
return do_smbus_block_write(res->base, device, cmd, bytes, buf);
}
-static int do_smbus_block_read(unsigned int smbus_base, unsigned int device,
- unsigned int cmd, unsigned int bytes, u8 *buf)
-{
- u8 status;
- int bytes_read = 0;
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(cmd & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a block data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x5 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- while (!(inb(smbus_base + SMBHSTSTAT) & 1))
- ;
- /* Poll for transaction completion */
- do {
- status = inb(smbus_base + SMBHSTSTAT);
- if (status & ((1 << 4) | /* FAILED */
- (1 << 3) | /* BUS ERR */
- (1 << 2))) /* DEV ERR */
- return SMBUS_ERROR;
-
- if (status & 0x80) { /* Byte done */
- *buf = inb(smbus_base + SMBBLKDAT);
- buf++;
- bytes_read++;
- outb(status, smbus_base + SMBHSTSTAT);
- if (--bytes == 1) {
- /* indicate that next byte is the last one */
- outb(inb(smbus_base + SMBHSTCTL) | 0x20,
- smbus_base + SMBHSTCTL);
- }
- }
- } while (status & 0x01);
-
- return bytes_read;
-}
-
static int lsmbus_block_read(device_t dev, u8 cmd, u8 bytes, u8 *buf)
{
u16 device;
diff --git a/src/southbridge/intel/i82801gx/smbus.h b/src/southbridge/intel/i82801gx/smbus.h
deleted file mode 100644
index ff8e1fb112..0000000000
--- a/src/southbridge/intel/i82801gx/smbus.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
- * Copyright (C) 2009 coresystems GmbH
- *
- * 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.
- */
-
-#include <device/smbus_def.h>
-#include "i82801gx.h"
-
-static void smbus_delay(void)
-{
- inb(0x80);
-}
-
-static int smbus_wait_until_ready(u16 smbus_base)
-{
- unsigned int loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while (byte & 1);
- return loops ? 0 : -1;
-}
-
-static int smbus_wait_until_done(u16 smbus_base)
-{
- unsigned int loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
- return loops ? 0 : -1;
-}
-
-static int do_smbus_read_byte(unsigned int smbus_base, unsigned int device, unsigned int address)
-{
- unsigned char global_status_register;
- unsigned char byte;
-
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(0, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- byte = inb(smbus_base + SMBHSTDAT0);
- if (global_status_register != (1 << 1))
- return SMBUS_ERROR;
- return byte;
-}
diff --git a/src/southbridge/intel/i82801ix/Kconfig b/src/southbridge/intel/i82801ix/Kconfig
index e4d1f916f1..6879bce803 100644
--- a/src/southbridge/intel/i82801ix/Kconfig
+++ b/src/southbridge/intel/i82801ix/Kconfig
@@ -17,6 +17,7 @@
config SOUTHBRIDGE_INTEL_I82801IX
bool
select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
select IOAPIC
select HAVE_USBDEBUG
select HAVE_HARD_RESET
diff --git a/src/southbridge/intel/i82801ix/early_smbus.c b/src/southbridge/intel/i82801ix/early_smbus.c
index 31b33e92d9..0e4195c198 100644
--- a/src/southbridge/intel/i82801ix/early_smbus.c
+++ b/src/southbridge/intel/i82801ix/early_smbus.c
@@ -19,8 +19,8 @@
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
+#include <southbridge/intel/common/smbus.h>
#include "i82801ix.h"
-#include "smbus.h"
void enable_smbus(void)
{
diff --git a/src/southbridge/intel/i82801ix/i82801ix.h b/src/southbridge/intel/i82801ix/i82801ix.h
index af4efcdb30..38dfa385ad 100644
--- a/src/southbridge/intel/i82801ix/i82801ix.h
+++ b/src/southbridge/intel/i82801ix/i82801ix.h
@@ -154,22 +154,6 @@
#define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0)
-/* SMBus I/O bits. */
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-#define SMBTRNSADD 0x9
-#define SMBSLVDATA 0xa
-#define SMLINK_PIN_CTL 0xe
-#define SMBUS_PIN_CTL 0xf
-
-#define SMBUS_TIMEOUT (10 * 1000 * 100)
-
-
#define RCBA8(x) *((volatile u8 *)(DEFAULT_RCBA + x))
#define RCBA16(x) *((volatile u16 *)(DEFAULT_RCBA + x))
#define RCBA32(x) *((volatile u32 *)(DEFAULT_RCBA + x))
diff --git a/src/southbridge/intel/i82801ix/smbus.c b/src/southbridge/intel/i82801ix/smbus.c
index 211372237f..ccfcddbec2 100644
--- a/src/southbridge/intel/i82801ix/smbus.c
+++ b/src/southbridge/intel/i82801ix/smbus.c
@@ -22,7 +22,8 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
-#include "smbus.h"
+#include <southbridge/intel/common/smbus.h>
+#include "i82801ix.h"
static void pch_smbus_init(device_t dev)
{
diff --git a/src/southbridge/intel/i82801ix/smbus.h b/src/southbridge/intel/i82801ix/smbus.h
deleted file mode 100644
index bcc758700d..0000000000
--- a/src/southbridge/intel/i82801ix/smbus.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
- * Copyright (C) 2009 coresystems GmbH
- *
- * 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.
- */
-
-#include <device/smbus_def.h>
-#include "i82801ix.h"
-
-static void smbus_delay(void)
-{
- inb(0x80);
-}
-
-static int smbus_wait_until_ready(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while (byte & 1);
- return loops ? 0 : -1;
-}
-
-static int smbus_wait_until_done(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
- return loops ? 0 : -1;
-}
-
-static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address)
-{
- unsigned char global_status_register;
- unsigned char byte;
-
- if (smbus_wait_until_ready(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
- }
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(0, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
- }
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- byte = inb(smbus_base + SMBHSTDAT0);
- if (global_status_register != (1 << 1)) {
- return SMBUS_ERROR;
- }
- return byte;
-}
-
-#ifndef __PRE_RAM__
-static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data)
-{
- unsigned char global_status_register;
-
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(data, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- if (global_status_register != (1 << 1))
- return SMBUS_ERROR;
-
- return 0;
-}
-#endif
diff --git a/src/southbridge/intel/i82801jx/Kconfig b/src/southbridge/intel/i82801jx/Kconfig
index 3f0e5692a0..5edaf1a3ce 100644
--- a/src/southbridge/intel/i82801jx/Kconfig
+++ b/src/southbridge/intel/i82801jx/Kconfig
@@ -17,6 +17,7 @@
config SOUTHBRIDGE_INTEL_I82801JX
bool
select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
select IOAPIC
select HAVE_USBDEBUG
select HAVE_HARD_RESET
diff --git a/src/southbridge/intel/i82801jx/early_smbus.c b/src/southbridge/intel/i82801jx/early_smbus.c
index fb6c252d39..a95099298f 100644
--- a/src/southbridge/intel/i82801jx/early_smbus.c
+++ b/src/southbridge/intel/i82801jx/early_smbus.c
@@ -19,8 +19,8 @@
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
+#include <southbridge/intel/common/smbus.h>
#include "i82801jx.h"
-#include "smbus.h"
void enable_smbus(void)
{
diff --git a/src/southbridge/intel/i82801jx/i82801jx.h b/src/southbridge/intel/i82801jx/i82801jx.h
index be92a8b58e..fd74d2a02f 100644
--- a/src/southbridge/intel/i82801jx/i82801jx.h
+++ b/src/southbridge/intel/i82801jx/i82801jx.h
@@ -147,22 +147,6 @@
#define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0)
-/* SMBus I/O bits. */
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-#define SMBTRNSADD 0x9
-#define SMBSLVDATA 0xa
-#define SMLINK_PIN_CTL 0xe
-#define SMBUS_PIN_CTL 0xf
-
-#define SMBUS_TIMEOUT (10 * 1000 * 100)
-
-
#define RCBA8(x) *((volatile u8 *)(DEFAULT_RCBA + x))
#define RCBA16(x) *((volatile u16 *)(DEFAULT_RCBA + x))
#define RCBA32(x) *((volatile u32 *)(DEFAULT_RCBA + x))
diff --git a/src/southbridge/intel/i82801jx/smbus.c b/src/southbridge/intel/i82801jx/smbus.c
index 00894cf82a..bc735a35b2 100644
--- a/src/southbridge/intel/i82801jx/smbus.c
+++ b/src/southbridge/intel/i82801jx/smbus.c
@@ -22,7 +22,8 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
-#include "smbus.h"
+#include <southbridge/intel/common/smbus.h>
+#include "i82801jx.h"
static void pch_smbus_init(device_t dev)
{
diff --git a/src/southbridge/intel/i82801jx/smbus.h b/src/southbridge/intel/i82801jx/smbus.h
deleted file mode 100644
index 61402f77b2..0000000000
--- a/src/southbridge/intel/i82801jx/smbus.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
- * Copyright (C) 2009 coresystems GmbH
- *
- * 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.
- */
-
-#include <device/smbus_def.h>
-#include "i82801jx.h"
-
-static void smbus_delay(void)
-{
- inb(0x80);
-}
-
-static int smbus_wait_until_ready(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while (byte & 1);
- return loops ? 0 : -1;
-}
-
-static int smbus_wait_until_done(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
- return loops ? 0 : -1;
-}
-
-static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address)
-{
- unsigned char global_status_register;
- unsigned char byte;
-
- if (smbus_wait_until_ready(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
- }
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(0, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
- }
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- byte = inb(smbus_base + SMBHSTDAT0);
- if (global_status_register != (1 << 1)) {
- return SMBUS_ERROR;
- }
- return byte;
-}
-
-#ifndef __PRE_RAM__
-static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data)
-{
- unsigned char global_status_register;
-
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(data, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- if (global_status_register != (1 << 1))
- return SMBUS_ERROR;
-
- return 0;
-}
-#endif
diff --git a/src/southbridge/intel/ibexpeak/Kconfig b/src/southbridge/intel/ibexpeak/Kconfig
index ad32a9bde0..41ace46f7f 100644
--- a/src/southbridge/intel/ibexpeak/Kconfig
+++ b/src/southbridge/intel/ibexpeak/Kconfig
@@ -30,6 +30,7 @@ config SOUTH_BRIDGE_OPTIONS # dummy
select PCIEXP_COMMON_CLOCK
select SPI_FLASH
select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
select HAVE_USBDEBUG_OPTIONS
select COMMON_FADT
select ACPI_SATA_GENERATOR
diff --git a/src/southbridge/intel/ibexpeak/early_smbus.c b/src/southbridge/intel/ibexpeak/early_smbus.c
index f3dab8d00f..b7823ebf59 100644
--- a/src/southbridge/intel/ibexpeak/early_smbus.c
+++ b/src/southbridge/intel/ibexpeak/early_smbus.c
@@ -18,8 +18,8 @@
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
+#include <southbridge/intel/common/smbus.h>
#include "pch.h"
-#include "smbus.h"
void enable_smbus(void)
{
diff --git a/src/southbridge/intel/ibexpeak/pch.h b/src/southbridge/intel/ibexpeak/pch.h
index 63307d9368..1898ae3dba 100644
--- a/src/southbridge/intel/ibexpeak/pch.h
+++ b/src/southbridge/intel/ibexpeak/pch.h
@@ -233,22 +233,6 @@ void southbridge_configure_default_intmap(void);
#define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0)
-/* SMBus I/O bits. */
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-#define SMBTRNSADD 0x9
-#define SMBSLVDATA 0xa
-#define SMLINK_PIN_CTL 0xe
-#define SMBUS_PIN_CTL 0xf
-
-#define SMBUS_TIMEOUT (10 * 1000 * 100)
-
-
/* Southbridge IO BARs */
#define GPIOBASE 0x48
diff --git a/src/southbridge/intel/ibexpeak/smbus.c b/src/southbridge/intel/ibexpeak/smbus.c
index 3b2f18c08e..aea52de7b5 100644
--- a/src/southbridge/intel/ibexpeak/smbus.c
+++ b/src/southbridge/intel/ibexpeak/smbus.c
@@ -22,8 +22,8 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
+#include <southbridge/intel/common/smbus.h>
#include "pch.h"
-#include "smbus.h"
static void pch_smbus_init(device_t dev)
{
diff --git a/src/southbridge/intel/ibexpeak/smbus.h b/src/southbridge/intel/ibexpeak/smbus.h
deleted file mode 100644
index 0815bf4f14..0000000000
--- a/src/southbridge/intel/ibexpeak/smbus.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
- * Copyright (C) 2009 coresystems GmbH
- * Copyright (C) 2013 Vladimir Serbinenko
- *
- * 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.
- */
-
-#include <device/smbus_def.h>
-#include "pch.h"
-
-static void smbus_delay(void)
-{
- inb(0x80);
-}
-
-static int smbus_wait_until_ready(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while (byte & 1);
- return loops ? 0 : -1;
-}
-
-static int smbus_wait_until_done(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
- return loops ? 0 : -1;
-}
-
-static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address)
-{
- unsigned char global_status_register;
- unsigned char byte;
-
- if (smbus_wait_until_ready(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
- }
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(0, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
- }
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- byte = inb(smbus_base + SMBHSTDAT0);
- if (global_status_register != (1 << 1)) {
- return SMBUS_ERROR;
- }
- return byte;
-}
-
-static int do_smbus_write_byte(unsigned smbus_base, unsigned device, unsigned address, unsigned data)
-{
- unsigned char global_status_register;
-
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(data, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- if (global_status_register != (1 << 1))
- return SMBUS_ERROR;
-
- return 0;
-}
-
-#ifdef __PRE_RAM__
-
-static int do_smbus_block_write(unsigned smbus_base, unsigned device,
- unsigned cmd, unsigned bytes, const u8 *buf)
-{
- u8 status;
-
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(cmd & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a block data write */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x5 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* set number of bytes to transfer */
- outb(bytes, smbus_base + SMBHSTDAT0);
-
- outb(*buf++, smbus_base + SMBBLKDAT);
- bytes--;
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- while (!(inb(smbus_base + SMBHSTSTAT) & 1));
- /* Poll for transaction completion */
- do {
- status = inb(smbus_base + SMBHSTSTAT);
- if (status & ((1 << 4) | /* FAILED */
- (1 << 3) | /* BUS ERR */
- (1 << 2))) /* DEV ERR */
- return SMBUS_ERROR;
-
- if (status & 0x80) { /* Byte done */
- outb(*buf++, smbus_base + SMBBLKDAT);
- outb(status, smbus_base + SMBHSTSTAT);
- }
- } while (status & 0x01);
-
- return 0;
-}
-
-static int do_smbus_block_read(unsigned smbus_base, unsigned device,
- unsigned cmd, unsigned bytes, u8 *buf)
-{
- u8 status;
- int bytes_read = 0;
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(cmd & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a block data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x5 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- while (!(inb(smbus_base + SMBHSTSTAT) & 1));
- /* Poll for transaction completion */
- do {
- status = inb(smbus_base + SMBHSTSTAT);
- if (status & ((1 << 4) | /* FAILED */
- (1 << 3) | /* BUS ERR */
- (1 << 2))) /* DEV ERR */
- return SMBUS_ERROR;
-
- if (status & 0x80) { /* Byte done */
- *buf = inb(smbus_base + SMBBLKDAT);
- buf++;
- bytes_read++;
- outb(status, smbus_base + SMBHSTSTAT);
- if (--bytes == 1) {
- /* indicate that next byte is the last one */
- outb(inb(smbus_base + SMBHSTCTL) | 0x20,
- smbus_base + SMBHSTCTL);
- }
- }
- } while (status & 0x01);
-
- return bytes_read;
-}
-#endif
diff --git a/src/southbridge/intel/lynxpoint/Kconfig b/src/southbridge/intel/lynxpoint/Kconfig
index 742f95cbd2..c65e5d7c32 100644
--- a/src/southbridge/intel/lynxpoint/Kconfig
+++ b/src/southbridge/intel/lynxpoint/Kconfig
@@ -22,6 +22,7 @@ config SOUTH_BRIDGE_OPTIONS # dummy
def_bool y
select ACPI_INTEL_HARDWARE_SLEEP_VALUES
select SOUTHBRIDGE_INTEL_COMMON
+ select SOUTHBRIDGE_INTEL_COMMON_SMBUS
select IOAPIC
select HAVE_HARD_RESET
select HAVE_USBDEBUG_OPTIONS
diff --git a/src/southbridge/intel/lynxpoint/early_smbus.c b/src/southbridge/intel/lynxpoint/early_smbus.c
index 2b174c787a..cf3a34c9e5 100644
--- a/src/southbridge/intel/lynxpoint/early_smbus.c
+++ b/src/southbridge/intel/lynxpoint/early_smbus.c
@@ -18,8 +18,8 @@
#include <console/console.h>
#include <device/pci_ids.h>
#include <device/pci_def.h>
+#include <southbridge/intel/common/smbus.h>
#include "pch.h"
-#include "smbus.h"
void enable_smbus(void)
{
diff --git a/src/southbridge/intel/lynxpoint/pch.h b/src/southbridge/intel/lynxpoint/pch.h
index c9c9c32acd..000f5460ef 100644
--- a/src/southbridge/intel/lynxpoint/pch.h
+++ b/src/southbridge/intel/lynxpoint/pch.h
@@ -473,22 +473,6 @@ void pch_enable_lpc(void);
#define SMB_SMI_EN (1 << 1)
#define HST_EN (1 << 0)
-/* SMBus I/O bits. */
-#define SMBHSTSTAT 0x0
-#define SMBHSTCTL 0x2
-#define SMBHSTCMD 0x3
-#define SMBXMITADD 0x4
-#define SMBHSTDAT0 0x5
-#define SMBHSTDAT1 0x6
-#define SMBBLKDAT 0x7
-#define SMBTRNSADD 0x9
-#define SMBSLVDATA 0xa
-#define SMLINK_PIN_CTL 0xe
-#define SMBUS_PIN_CTL 0xf
-
-#define SMBUS_TIMEOUT (10 * 1000 * 100)
-
-
/* Southbridge IO BARs */
#define GPIOBASE 0x48
diff --git a/src/southbridge/intel/lynxpoint/smbus.c b/src/southbridge/intel/lynxpoint/smbus.c
index d81a097fef..ccb5ea08f6 100644
--- a/src/southbridge/intel/lynxpoint/smbus.c
+++ b/src/southbridge/intel/lynxpoint/smbus.c
@@ -22,8 +22,8 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
+#include <southbridge/intel/common/smbus.h>
#include "pch.h"
-#include "smbus.h"
static void pch_smbus_init(device_t dev)
{
@@ -54,54 +54,6 @@ static int lsmbus_read_byte(device_t dev, u8 address)
return do_smbus_read_byte(res->base, device, address);
}
-static int do_smbus_write_byte(unsigned smbus_base, unsigned device,
- unsigned address, unsigned data)
-{
- unsigned char global_status_register;
-
- if (smbus_wait_until_ready(smbus_base) < 0)
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
-
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(data, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0) {
- printk(BIOS_ERR, "SMBUS transaction timeout\n");
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
- }
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- if (global_status_register != (1 << 1)) {
- printk(BIOS_ERR, "SMBUS transaction error\n");
- return SMBUS_ERROR;
- }
-
- return 0;
-}
-
static int lsmbus_write_byte(device_t dev, u8 address, u8 data)
{
u16 device;
diff --git a/src/southbridge/intel/lynxpoint/smbus.h b/src/southbridge/intel/lynxpoint/smbus.h
deleted file mode 100644
index 0978963723..0000000000
--- a/src/southbridge/intel/lynxpoint/smbus.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
- * Copyright (C) 2009 coresystems GmbH
- *
- * 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.
- */
-
-#include <device/smbus_def.h>
-#include "pch.h"
-
-static void smbus_delay(void)
-{
- inb(0x80);
-}
-
-static int smbus_wait_until_ready(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while (byte & 1);
- return loops ? 0 : -1;
-}
-
-static int smbus_wait_until_done(u16 smbus_base)
-{
- unsigned loops = SMBUS_TIMEOUT;
- unsigned char byte;
- do {
- smbus_delay();
- if (--loops == 0)
- break;
- byte = inb(smbus_base + SMBHSTSTAT);
- } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
- return loops ? 0 : -1;
-}
-
-static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address)
-{
- unsigned char global_status_register;
- unsigned char byte;
-
- if (smbus_wait_until_ready(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
- }
- /* Setup transaction */
- /* Disable interrupts */
- outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
- /* Set the device I'm talking too */
- outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
- /* Set the command/address... */
- outb(address & 0xff, smbus_base + SMBHSTCMD);
- /* Set up for a byte data read */
- outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
- (smbus_base + SMBHSTCTL));
- /* Clear any lingering errors, so the transaction will run */
- outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
-
- /* Clear the data byte... */
- outb(0, smbus_base + SMBHSTDAT0);
-
- /* Start the command */
- outb((inb(smbus_base + SMBHSTCTL) | 0x40),
- smbus_base + SMBHSTCTL);
-
- /* Poll for transaction completion */
- if (smbus_wait_until_done(smbus_base) < 0) {
- return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
- }
-
- global_status_register = inb(smbus_base + SMBHSTSTAT);
-
- /* Ignore the "In Use" status... */
- global_status_register &= ~(3 << 5);
-
- /* Read results of transaction */
- byte = inb(smbus_base + SMBHSTDAT0);
- if (global_status_register != (1 << 1)) {
- return SMBUS_ERROR;
- }
- return byte;
-}