]> Pileus Git - ~andy/linux/blobdiff - drivers/i2c/busses/i2c-designware-core.c
Merge tag 'devicetree-for-linus' of git://git.secretlab.ca/git/linux
[~andy/linux] / drivers / i2c / busses / i2c-designware-core.c
index ad46616de29ec8638aeb2a17c6ff231d59c57596..dbecf08399f86dd30baa7fa7b8964e2daf616bcb 100644 (file)
@@ -317,6 +317,12 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
                                47,     /* tLOW = 4.7 us */
                                3,      /* tf = 0.3 us */
                                0);     /* No offset */
+
+       /* Allow platforms to specify the ideal HCNT and LCNT values */
+       if (dev->ss_hcnt && dev->ss_lcnt) {
+               hcnt = dev->ss_hcnt;
+               lcnt = dev->ss_lcnt;
+       }
        dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
        dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
        dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
@@ -331,6 +337,11 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
                                13,     /* tLOW = 1.3 us */
                                3,      /* tf = 0.3 us */
                                0);     /* No offset */
+
+       if (dev->fs_hcnt && dev->fs_lcnt) {
+               hcnt = dev->fs_hcnt;
+               lcnt = dev->fs_lcnt;
+       }
        dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
        dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
        dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
@@ -416,6 +427,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
        u32 addr = msgs[dev->msg_write_idx].addr;
        u32 buf_len = dev->tx_buf_len;
        u8 *buf = dev->tx_buf;
+       bool need_restart = false;
 
        intr_mask = DW_IC_INTR_DEFAULT_MASK;
 
@@ -443,6 +455,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
                        /* new i2c_msg */
                        buf = msgs[dev->msg_write_idx].buf;
                        buf_len = msgs[dev->msg_write_idx].len;
+
+                       /* If both IC_EMPTYFIFO_HOLD_MASTER_EN and
+                        * IC_RESTART_EN are set, we must manually
+                        * set restart bit between messages.
+                        */
+                       if ((dev->master_cfg & DW_IC_CON_RESTART_EN) &&
+                                       (dev->msg_write_idx > 0))
+                               need_restart = true;
                }
 
                tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
@@ -461,6 +481,11 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
                            buf_len == 1)
                                cmd |= BIT(9);
 
+                       if (need_restart) {
+                               cmd |= BIT(10);
+                               need_restart = false;
+                       }
+
                        if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
 
                                /* avoid rx buffer overrun */