aboutsummaryrefslogtreecommitdiff
path: root/src/southbridge/intel/common/smbus.c
diff options
context:
space:
mode:
authorFrans Hendriks <fhendriks@eltan.com>2019-06-19 11:01:27 +0200
committerMartin Roth <martinroth@google.com>2019-06-20 15:25:51 +0000
commite48be35bca9a0656d1becb0c8a030a11eb8ffaa7 (patch)
tree636b4299c20c7ccc8d0912e672304be6792843af /src/southbridge/intel/common/smbus.c
parentb09de70eda443d2fc9f4891c7647aac4526a8e99 (diff)
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>
Diffstat (limited to 'src/southbridge/intel/common/smbus.c')
-rw-r--r--src/southbridge/intel/common/smbus.c45
1 files changed, 45 insertions, 0 deletions
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 <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 @@ 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:
+ * <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;
+}