summaryrefslogtreecommitdiff
path: root/drivers/i2c/busses/i2c-hisi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-hisi.c')
-rw-r--r--drivers/i2c/busses/i2c-hisi.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/i2c/busses/i2c-hisi.c b/drivers/i2c/busses/i2c-hisi.c
index dfad5bad5075..4b735ad9e193 100644
--- a/drivers/i2c/busses/i2c-hisi.c
+++ b/drivers/i2c/busses/i2c-hisi.c
@@ -57,6 +57,8 @@
#define HISI_I2C_FS_SPK_LEN_CNT GENMASK(7, 0)
#define HISI_I2C_HS_SPK_LEN 0x003c
#define HISI_I2C_HS_SPK_LEN_CNT GENMASK(7, 0)
+#define HISI_I2C_TX_INT_CLR 0x0040
+#define HISI_I2C_TX_AEMPTY_INT BIT(0)
#define HISI_I2C_INT_MSTAT 0x0044
#define HISI_I2C_INT_CLR 0x0048
#define HISI_I2C_INT_MASK 0x004C
@@ -124,6 +126,11 @@ static void hisi_i2c_clear_int(struct hisi_i2c_controller *ctlr, u32 mask)
writel_relaxed(mask, ctlr->iobase + HISI_I2C_INT_CLR);
}
+static void hisi_i2c_clear_tx_int(struct hisi_i2c_controller *ctlr, u32 mask)
+{
+ writel_relaxed(mask, ctlr->iobase + HISI_I2C_TX_INT_CLR);
+}
+
static void hisi_i2c_handle_errors(struct hisi_i2c_controller *ctlr)
{
u32 int_err = ctlr->xfer_err, reg;
@@ -168,6 +175,7 @@ static int hisi_i2c_start_xfer(struct hisi_i2c_controller *ctlr)
writel(reg, ctlr->iobase + HISI_I2C_FIFO_CTRL);
hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL);
+ hisi_i2c_clear_tx_int(ctlr, HISI_I2C_TX_AEMPTY_INT);
hisi_i2c_enable_int(ctlr, HISI_I2C_INT_ALL);
return 0;
@@ -189,8 +197,8 @@ static void hisi_i2c_reset_xfer(struct hisi_i2c_controller *ctlr)
* wait for the transfer done. The major transfer process is performed
* in the IRQ handler.
*/
-static int hisi_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
- int num)
+static int hisi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num)
{
struct hisi_i2c_controller *ctlr = i2c_get_adapdata(adap);
DECLARE_COMPLETION_ONSTACK(done);
@@ -228,8 +236,8 @@ static u32 hisi_i2c_functionality(struct i2c_adapter *adap)
}
static const struct i2c_algorithm hisi_i2c_algo = {
- .master_xfer = hisi_i2c_master_xfer,
- .functionality = hisi_i2c_functionality,
+ .xfer = hisi_i2c_xfer,
+ .functionality = hisi_i2c_functionality,
};
static int hisi_i2c_read_rx_fifo(struct hisi_i2c_controller *ctlr)
@@ -266,7 +274,7 @@ static int hisi_i2c_read_rx_fifo(struct hisi_i2c_controller *ctlr)
static void hisi_i2c_xfer_msg(struct hisi_i2c_controller *ctlr)
{
- int max_write = HISI_I2C_TX_FIFO_DEPTH;
+ int max_write = HISI_I2C_TX_FIFO_DEPTH - HISI_I2C_TX_F_AE_THRESH;
bool need_restart = false, last_msg;
struct i2c_msg *cur_msg;
u32 cmd, fifo_state;
@@ -323,6 +331,8 @@ static void hisi_i2c_xfer_msg(struct hisi_i2c_controller *ctlr)
*/
if (ctlr->msg_tx_idx == ctlr->msg_num)
hisi_i2c_disable_int(ctlr, HISI_I2C_INT_TX_EMPTY);
+
+ hisi_i2c_clear_tx_int(ctlr, HISI_I2C_TX_AEMPTY_INT);
}
static irqreturn_t hisi_i2c_irq(int irq, void *context)
@@ -363,6 +373,7 @@ out:
if (int_stat & HISI_I2C_INT_TRANS_CPLT) {
hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL);
hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL);
+ hisi_i2c_clear_tx_int(ctlr, HISI_I2C_TX_AEMPTY_INT);
complete(ctlr->completion);
}