summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/device/smbus_host.h1
-rw-r--r--src/southbridge/intel/common/smbus.c37
2 files changed, 38 insertions, 0 deletions
diff --git a/src/include/device/smbus_host.h b/src/include/device/smbus_host.h
index 6e6163f062..d9390eaf2d 100644
--- a/src/include/device/smbus_host.h
+++ b/src/include/device/smbus_host.h
@@ -17,6 +17,7 @@ int do_smbus_write_word(uintptr_t base, u8 device, u8 address, u16 data);
int do_smbus_block_read(uintptr_t base, u8 device, u8 cmd, size_t max_bytes, u8 *buf);
int do_smbus_block_write(uintptr_t base, u8 device, u8 cmd, size_t bytes, const u8 *buf);
+int do_smbus_process_call(uintptr_t base, u8 device, u8 cmd, u16 data, u16 *buf);
/* For Intel, implemented since ICH5. */
int do_i2c_eeprom_read(uintptr_t base, u8 device, u8 offset, size_t bytes, u8 *buf);
diff --git a/src/southbridge/intel/common/smbus.c b/src/southbridge/intel/common/smbus.c
index 95c2fd0957..8b19b7d900 100644
--- a/src/southbridge/intel/common/smbus.c
+++ b/src/southbridge/intel/common/smbus.c
@@ -33,6 +33,7 @@
#define I801_BYTE (1 << 2)
#define I801_BYTE_DATA (2 << 2)
#define I801_WORD_DATA (3 << 2)
+#define I801_PROCESS_CALL (4 << 2)
#define I801_BLOCK_DATA (5 << 2)
#define I801_I2C_BLOCK_DATA (6 << 2) /* ICH5 and later */
@@ -391,6 +392,42 @@ int do_smbus_block_read(uintptr_t base, u8 device, u8 cmd, size_t max_bytes, u8
return ret;
}
+/*
+ * The caller is responsible of settings HOSTC I2C_EN bit prior to making this
+ * call!
+ */
+int do_smbus_process_call(uintptr_t base, u8 device, u8 cmd, u16 data, u16 *buf)
+{
+ int ret;
+
+ /* Set up for process call */
+ ret = setup_command(base, I801_PROCESS_CALL, XMIT_WRITE(device));
+ if (ret < 0)
+ return ret;
+
+ /* cmd will only be send if I2C_EN is zero */
+ host_outb(base, SMBHSTCMD, cmd);
+
+ host_outb(base, SMBHSTDAT0, data & 0x00ff);
+ host_outb(base, SMBHSTDAT1, (data & 0xff00) >> 8);
+
+ /* Start the command */
+ ret = execute_command(base);
+ if (ret < 0)
+ return ret;
+
+ /* Poll for transaction completion */
+ ret = complete_command(base);
+ if (ret < 0)
+ return ret;
+
+ /* Read results of transaction */
+ *buf = host_inb(base, SMBHSTDAT0);
+ *buf |= (host_inb(base, SMBHSTDAT1) << 8);
+
+ return ret;
+}
+
int do_smbus_block_write(uintptr_t base, u8 device, u8 cmd, const size_t bytes, const u8 *buf)
{
int ret;