summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/nvidia/tegra/i2c.c13
-rw-r--r--src/soc/nvidia/tegra/i2c.h8
-rw-r--r--src/soc/nvidia/tegra124/i2c.c36
3 files changed, 48 insertions, 9 deletions
diff --git a/src/soc/nvidia/tegra/i2c.c b/src/soc/nvidia/tegra/i2c.c
index e9001f09b2..8c8a372798 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 5f299e8ac7..03a6d66e1f 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 b54230b171..a7eee686b0 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
+ }
};