diff options
-rw-r--r-- | src/soc/nvidia/tegra/i2c.c | 13 | ||||
-rw-r--r-- | src/soc/nvidia/tegra/i2c.h | 8 | ||||
-rw-r--r-- | 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 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(®s->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, ®s->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 + } }; |