From e48be35bca9a0656d1becb0c8a030a11eb8ffaa7 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Wed, 19 Jun 2019 11:01:27 +0200 Subject: southbridge/intel/common/smbus: Add do_i2c_block_write() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/30800 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- src/southbridge/intel/common/smbus.c | 45 ++++++++++++++++++++++++++++++++++++ src/southbridge/intel/common/smbus.h | 2 ++ 2 files changed, 47 insertions(+) (limited to 'src') diff --git a/src/southbridge/intel/common/smbus.c b/src/southbridge/intel/common/smbus.c index af1eb602a0..e575abc40e 100644 --- a/src/southbridge/intel/common/smbus.c +++ b/src/southbridge/intel/common/smbus.c @@ -4,6 +4,7 @@ * Copyright (C) 2005 Yinghai Lu * 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 @@ int do_i2c_eeprom_read(unsigned int smbus_base, u8 device, 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: + * .. + * 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 ded31d0ae2..4875581573 100644 --- a/src/southbridge/intel/common/smbus.h +++ b/src/southbridge/intel/common/smbus.h @@ -43,4 +43,6 @@ int do_smbus_block_write(unsigned int smbus_base, u8 device, /* 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 -- cgit v1.2.3