Martin Roth has submitted this change and it was merged. ( https://review.coreboot.org/c/coreboot/+/30800 )
Change subject: southbridge/intel/common/smbus: Add do_i2c_block_write() ......................................................................
southbridge/intel/common/smbus: Add do_i2c_block_write()
Intel Braswell supports i2c block writes using SMBus controller. This support is missing in actual smbus routines.
Add do_i2c_block_write() which is a based on do_smbus_block_write() but also write first byte to SMBHSTDAT1. The caller needs to configure the SMBus controller in i2c mode.
In i2c mode SMBus controller will send the next sequence: SMBXINTADD, SMBHSTDAT1, SMBBLKDAT .. SMBBLKDAT
To ensure the the command is send over the bus the SMBHSTCMD register must be written also
BUG=N/A TEST=Config eDP for LCD display on Facebook FBG-1701
Change-Id: I40f8c0f5257a62398189f36892b8159052481693 Signed-off-by: Frans Hendriks fhendriks@eltan.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/30800 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Kyösti Mälkki kyosti.malkki@gmail.com --- M src/southbridge/intel/common/smbus.c M src/southbridge/intel/common/smbus.h 2 files changed, 47 insertions(+), 0 deletions(-)
Approvals: build bot (Jenkins): Verified Kyösti Mälkki: Looks good to me, approved
diff --git a/src/southbridge/intel/common/smbus.c b/src/southbridge/intel/common/smbus.c index af1eb60..e575abc 100644 --- a/src/southbridge/intel/common/smbus.c +++ b/src/southbridge/intel/common/smbus.c @@ -4,6 +4,7 @@ * Copyright (C) 2005 Yinghai Lu yinghailu@gmail.com * Copyright (C) 2009 coresystems GmbH * Copyright (C) 2013 Vladimir Serbinenko + * Copyright (C) 2018-2019 Eltan B.V. * * 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 @@ -410,3 +411,47 @@
return ret; } + +/* + * The caller is responsible of settings HOSTC I2C_EN bit prior to making this + * call! + */ +int do_i2c_block_write(unsigned int smbus_base, u8 device, + unsigned int bytes, u8 *buf) +{ + u8 cmd; + int ret; + + if (!CONFIG(SOC_INTEL_BRASWELL)) + return SMBUS_ERROR; + + if (!bytes || (bytes > SMBUS_BLOCK_MAXLEN)) + return SMBUS_ERROR; + + /* Set up for a block data write. */ + ret = setup_command(smbus_base, I801_BLOCK_DATA, XMIT_WRITE(device)); + if (ret < 0) + return ret; + + /* + * In i2c mode SMBus controller sequence on bus will be: + * <SMBXINTADD> <SMBHSTDAT1> <SMBBLKDAT> .. <SMBBLKDAT> + * The SMBHSTCMD must be written also to ensure the SMBUs controller + * will generate the i2c sequence. + */ + cmd = *buf++; + bytes--; + outb(cmd, smbus_base + SMBHSTCMD); + outb(cmd, smbus_base + SMBHSTDAT1); + + /* Execute block transaction. */ + ret = block_cmd_loop(smbus_base, buf, bytes, BLOCK_WRITE); + if (ret < 0) + return ret; + + if (ret < bytes) + return SMBUS_ERROR; + + ret++; /* 1st byte has been written using SMBHSTDAT1 */ + return ret; +} diff --git a/src/southbridge/intel/common/smbus.h b/src/southbridge/intel/common/smbus.h index ded31d0..4875581 100644 --- a/src/southbridge/intel/common/smbus.h +++ b/src/southbridge/intel/common/smbus.h @@ -43,4 +43,6 @@ /* Only since ICH5 */ int do_i2c_eeprom_read(unsigned int smbus_base, u8 device, unsigned int offset, unsigned int bytes, u8 *buf); +int do_i2c_block_write(unsigned int smbus_base, u8 device, + unsigned int bytes, u8 *buf); #endif