[coreboot-gerrit] Patch set updated for coreboot: 8af5879 tegra124: i2c: Reset the controller when there's an error.

Marc Jones (marc.jones@se-eng.com) gerrit at coreboot.org
Thu Nov 13 22:12:26 CET 2014


Marc Jones (marc.jones at se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/7460

-gerrit

commit 8af58793844d4b4dd1229b3abf9ba6f9d0511bb7
Author: Gabe Black <gabeblack at google.com>
Date:   Wed Mar 26 21:43:53 2014 -0700

    tegra124: i2c: Reset the controller when there's an error.
    
    This is the only way to clear the error bits in the controller. Without
    clearing them, every future transaction will look like it failed.
    
    BUG=chrome-os-partner:27220
    TEST=Built and booted on nyan with the TPM frequency turned up to 400 KHz.
    BRANCH=None
    
    Original-Change-Id: Ib654e60ec3039ad9f5f96aa7288d3d877e5c843a
    Original-Signed-off-by: Gabe Black <gabeblack at google.com>
    Original-Reviewed-on: https://chromium-review.googlesource.com/191811
    Original-Reviewed-by: Tom Warren <twarren at nvidia.com>
    Original-Reviewed-by: Gabe Black <gabeblack at chromium.org>
    Original-Commit-Queue: Gabe Black <gabeblack at chromium.org>
    Original-Tested-by: Gabe Black <gabeblack at chromium.org>
    (cherry picked from commit 7b19a095652f1561590dcca922b9f8c308d7de9d)
    Signed-off-by: Marc Jones <marc.jones at se-eng.com>
    
    Change-Id: I301b6694cc521601b618973de891e4ed44c6a97d
---
 src/soc/nvidia/tegra/i2c.c    | 13 +++++++++----
 src/soc/nvidia/tegra/i2c.h    |  8 +++++++-
 src/soc/nvidia/tegra124/i2c.c | 36 ++++++++++++++++++++++++++++++++----
 3 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/src/soc/nvidia/tegra/i2c.c b/src/soc/nvidia/tegra/i2c.c
index e9001f0..8c8a372 100644
--- a/src/soc/nvidia/tegra/i2c.c
+++ b/src/soc/nvidia/tegra/i2c.c
@@ -26,10 +26,13 @@
 
 #include "i2c.h"
 
-static int tegra_i2c_send_recv(struct tegra_i2c_regs *regs, int read,
+static int tegra_i2c_send_recv(int bus, int read,
 			       uint32_t *headers, int header_words,
 			       uint8_t *data, int data_len)
 {
+	struct tegra_i2c_bus_info *info = &tegra_i2c_info[bus];
+	struct tegra_i2c_regs * const regs = info->base;
+
 	while (data_len) {
 		uint32_t status = read32(&regs->fifo_status);
 		int tx_empty = status & I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT_MASK;
@@ -75,16 +78,19 @@ static int tegra_i2c_send_recv(struct tegra_i2c_regs *regs, int read,
 			printk(BIOS_ERR,
 			       "%s: The address was not acknowledged.\n",
 			       __func__);
+			info->reset_func(info->reset_bit);
 			return -1;
 		} else if (transfer_status & I2C_PKT_STATUS_NOACK_DATA) {
 			printk(BIOS_ERR,
 			       "%s: The data was not acknowledged.\n",
 			       __func__);
+			info->reset_func(info->reset_bit);
 			return -1;
 		} else if (transfer_status & I2C_PKT_STATUS_ARB_LOST) {
 			printk(BIOS_ERR,
 			       "%s: Lost arbitration.\n",
 			       __func__);
+			info->reset_func(info->reset_bit);
 			return -1;
 		}
 	}
@@ -95,7 +101,6 @@ static int tegra_i2c_send_recv(struct tegra_i2c_regs *regs, int read,
 static int tegra_i2c_request(int bus, unsigned chip, int cont, int restart,
 			     int read, void *data, int data_len)
 {
-	struct tegra_i2c_regs * const regs = tegra_i2c_bases[bus];
 	uint32_t headers[3];
 
 	if (restart && cont) {
@@ -121,7 +126,7 @@ static int tegra_i2c_request(int bus, unsigned chip, int cont, int restart,
 	if (cont)
 		headers[2] |= IOHEADER_I2C_REQ_CONTINUE_XFER;
 
-	return tegra_i2c_send_recv(regs, read, headers, ARRAY_SIZE(headers),
+	return tegra_i2c_send_recv(bus, read, headers, ARRAY_SIZE(headers),
 				   data, data_len);
 }
 
@@ -166,7 +171,7 @@ int i2c_write(unsigned bus, unsigned chip, unsigned addr,
 
 void i2c_init(unsigned bus)
 {
-	struct tegra_i2c_regs * const regs = tegra_i2c_bases[bus];
+	struct tegra_i2c_regs * const regs = tegra_i2c_info[bus].base;
 
 	write32(I2C_CNFG_PACKET_MODE_EN, &regs->cnfg);
 }
diff --git a/src/soc/nvidia/tegra/i2c.h b/src/soc/nvidia/tegra/i2c.h
index 5f299e8..03a6d66 100644
--- a/src/soc/nvidia/tegra/i2c.h
+++ b/src/soc/nvidia/tegra/i2c.h
@@ -110,7 +110,13 @@ enum {
 		0xf << I2C_FIFO_STATUS_RX_FIFO_FULL_CNT_SHIFT
 };
 
-extern void * const tegra_i2c_bases[];
+struct tegra_i2c_bus_info {
+	void *base;
+	uint32_t reset_bit;
+	void (*reset_func)(u32 bit);
+};
+
+extern struct tegra_i2c_bus_info tegra_i2c_info[];
 
 struct tegra_i2c_regs {
 	uint32_t cnfg;
diff --git a/src/soc/nvidia/tegra124/i2c.c b/src/soc/nvidia/tegra124/i2c.c
index b54230b..a7eee68 100644
--- a/src/soc/nvidia/tegra124/i2c.c
+++ b/src/soc/nvidia/tegra124/i2c.c
@@ -18,10 +18,38 @@
  */
 
 #include <soc/addressmap.h>
+#include <soc/clock.h>
 #include <soc/nvidia/tegra/i2c.h>
 
-void * const tegra_i2c_bases[TEGRA_I2C_BASE_COUNT] = {
-	(void *)TEGRA_I2C_BASE,  (void *)TEGRA_I2C2_BASE,
-	(void *)TEGRA_I2C3_BASE, (void *)TEGRA_I2C4_BASE,
-	(void *)TEGRA_I2C5_BASE, (void *)TEGRA_I2C6_BASE
+struct tegra_i2c_bus_info tegra_i2c_info[] = {
+	{
+		.base = (void *)TEGRA_I2C_BASE,
+		.reset_bit = CLK_L_I2C1,
+		.reset_func = &clock_reset_l
+	},
+	{
+		.base = (void *)TEGRA_I2C2_BASE,
+		.reset_bit = CLK_H_I2C2,
+		.reset_func = &clock_reset_h
+	},
+	{
+		.base = (void *)TEGRA_I2C3_BASE,
+		.reset_bit = CLK_U_I2C3,
+		.reset_func = &clock_reset_u
+	},
+	{
+		.base = (void *)TEGRA_I2C4_BASE,
+		.reset_bit = CLK_V_I2C4,
+		.reset_func = &clock_reset_v
+	},
+	{
+		.base = (void *)TEGRA_I2C5_BASE,
+		.reset_bit = CLK_H_I2C5,
+		.reset_func = &clock_reset_h
+	},
+	{
+		.base = (void *)TEGRA_I2C6_BASE,
+		.reset_bit = CLK_X_I2C6,
+		.reset_func = &clock_reset_x
+	}
 };



More information about the coreboot-gerrit mailing list