diff options
author | Christian Walter <christian.walter@9elements.com> | 2020-03-27 11:59:43 +0100 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2020-05-12 20:08:20 +0000 |
commit | 04953ebf5f343dcb37e1288705a160b4cf1b64cf (patch) | |
tree | 48281e7a1038886dbc1614f1fecd2d72678d2a7b | |
parent | 5cb34e2ea0034f3d3781006234a0c8b66f4efcfe (diff) |
southbridge/intel/common: Add Process Call
Add functionality to use process call cycle. It can be used to
write/read data to/from e.g. EEPROM attached to SMBus Controller
via I2C.
Tested on:
* C246
Change-Id: Ifdac6cf70a4ce744601f5d152a83d2125ea88360
Signed-off-by: Christian Walter <christian.walter@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/39875
Reviewed-by: Patrick Rudolph <siro@das-labor.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-rw-r--r-- | src/include/device/smbus_host.h | 1 | ||||
-rw-r--r-- | src/southbridge/intel/common/smbus.c | 37 |
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; |