Merge branch 'i2c-mux-dt-3' of https://github.com/peda-r/i2c-mux into i2c/for-4.9
authorWolfram Sang <wsa@the-dreams.de>
Thu, 25 Aug 2016 22:49:37 +0000 (00:49 +0200)
committerWolfram Sang <wsa@the-dreams.de>
Thu, 25 Aug 2016 22:49:37 +0000 (00:49 +0200)
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
69 files changed:
MAINTAINERS
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-amd756.c
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-axxia.c
drivers/i2c/busses/i2c-bcm-iproc.c
drivers/i2c/busses/i2c-bcm-kona.c
drivers/i2c/busses/i2c-bfin-twi.c
drivers/i2c/busses/i2c-brcmstb.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-cpm.c
drivers/i2c/busses/i2c-cros-ec-tunnel.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-diolan-u2c.c
drivers/i2c/busses/i2c-dln2.c
drivers/i2c/busses/i2c-efm32.c
drivers/i2c/busses/i2c-exynos5.c
drivers/i2c/busses/i2c-hix5hd2.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-img-scb.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-isch.c
drivers/i2c/busses/i2c-ismt.c
drivers/i2c/busses/i2c-jz4780.c
drivers/i2c/busses/i2c-lpc2k.c
drivers/i2c/busses/i2c-meson.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mt65xx.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-octeon-core.c [new file with mode: 0644]
drivers/i2c/busses/i2c-octeon-core.h [new file with mode: 0644]
drivers/i2c/busses/i2c-octeon-platdrv.c [new file with mode: 0644]
drivers/i2c/busses/i2c-octeon.c [deleted file]
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-pmcmsp.c
drivers/i2c/busses/i2c-pnx.c
drivers/i2c/busses/i2c-puv3.c
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-riic.c
drivers/i2c/busses/i2c-rk3x.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sh7760.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/i2c/busses/i2c-sirf.c
drivers/i2c/busses/i2c-st.c
drivers/i2c/busses/i2c-stu300.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/busses/i2c-thunderx-pcidrv.c [new file with mode: 0644]
drivers/i2c/busses/i2c-uniphier-f.c
drivers/i2c/busses/i2c-uniphier.c
drivers/i2c/busses/i2c-wmt.c
drivers/i2c/busses/i2c-xgene-slimpro.c
drivers/i2c/busses/i2c-xiic.c
drivers/i2c/busses/i2c-xlp9xx.c
drivers/i2c/busses/i2c-xlr.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-mux.c
drivers/misc/eeprom/at24.c
include/linux/i2c.h

index 353bfe6..c58ee8c 100644 (file)
@@ -2878,6 +2878,14 @@ S:       Maintained
 F:     drivers/iio/light/cm*
 F:     Documentation/devicetree/bindings/i2c/trivial-devices.txt
 
+CAVIUM I2C DRIVER
+M:     Jan Glauber <jglauber@cavium.com>
+M:     David Daney <david.daney@cavium.com>
+W:     http://www.cavium.com
+S:     Supported
+F:     drivers/i2c/busses/i2c-octeon*
+F:     drivers/i2c/busses/i2c-thunderx*
+
 CAVIUM LIQUIDIO NETWORK DRIVER
 M:     Derek Chickles <derek.chickles@caviumnetworks.com>
 M:     Satanand Burla <satananda.burla@caviumnetworks.com>
index 5c3993b..1f3239e 100644 (file)
@@ -956,6 +956,17 @@ config I2C_OCTEON
          This driver can also be built as a module.  If so, the module
          will be called i2c-octeon.
 
+config I2C_THUNDERX
+       tristate "Cavium ThunderX I2C bus support"
+       depends on 64BIT && PCI && (ARM64 || COMPILE_TEST)
+       select I2C_SMBUS
+       help
+         Say yes if you want to support the I2C serial bus on Cavium
+         ThunderX SOC.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-thunderx.
+
 config I2C_XILINX
        tristate "Xilinx I2C Controller"
        depends on HAS_IOMEM
index 37f2819..29764cc 100644 (file)
@@ -91,7 +91,10 @@ obj-$(CONFIG_I2C_UNIPHIER)   += i2c-uniphier.o
 obj-$(CONFIG_I2C_UNIPHIER_F)   += i2c-uniphier-f.o
 obj-$(CONFIG_I2C_VERSATILE)    += i2c-versatile.o
 obj-$(CONFIG_I2C_WMT)          += i2c-wmt.o
+i2c-octeon-objs := i2c-octeon-core.o i2c-octeon-platdrv.o
 obj-$(CONFIG_I2C_OCTEON)       += i2c-octeon.o
+i2c-thunderx-objs := i2c-octeon-core.o i2c-thunderx-pcidrv.o
+obj-$(CONFIG_I2C_THUNDERX)     += i2c-thunderx.o
 obj-$(CONFIG_I2C_XILINX)       += i2c-xiic.o
 obj-$(CONFIG_I2C_XLR)          += i2c-xlr.o
 obj-$(CONFIG_I2C_XLP9XX)       += i2c-xlp9xx.o
index 6c7113d..274908c 100644 (file)
@@ -378,11 +378,8 @@ static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                 amd756_ioport);
 
        error = i2c_add_adapter(&amd756_smbus);
-       if (error) {
-               dev_err(&pdev->dev,
-                       "Adapter registration failed, module not inserted\n");
+       if (error)
                goto out_err;
-       }
 
        return 0;
 
index 1bb97f6..0b86c61 100644 (file)
@@ -1122,8 +1122,6 @@ static int at91_twi_probe(struct platform_device *pdev)
 
        rc = i2c_add_numbered_adapter(&dev->adapter);
        if (rc) {
-               dev_err(dev->dev, "Adapter %s registration failed\n",
-                       dev->adapter.name);
                clk_disable_unprepare(dev->clk);
 
                pm_runtime_disable(dev->dev);
index c335cc7..d3bcaf4 100644 (file)
@@ -558,13 +558,7 @@ static int axxia_i2c_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, idev);
 
-       ret = i2c_add_adapter(&idev->adapter);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to add adapter\n");
-               return ret;
-       }
-
-       return 0;
+       return i2c_add_adapter(&idev->adapter);
 }
 
 static int axxia_i2c_remove(struct platform_device *pdev)
index 95f7cac..326b3db 100644 (file)
@@ -488,13 +488,7 @@ static int bcm_iproc_i2c_probe(struct platform_device *pdev)
        adap->dev.parent = &pdev->dev;
        adap->dev.of_node = pdev->dev.of_node;
 
-       ret = i2c_add_adapter(adap);
-       if (ret) {
-               dev_err(iproc_i2c->device, "failed to add adapter\n");
-               return ret;
-       }
-
-       return 0;
+       return i2c_add_adapter(adap);
 }
 
 static int bcm_iproc_i2c_remove(struct platform_device *pdev)
index f987432..d8494f8 100644 (file)
@@ -858,10 +858,8 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev)
        adap->dev.of_node = pdev->dev.of_node;
 
        rc = i2c_add_adapter(adap);
-       if (rc) {
-               dev_err(dev->device, "failed to add adapter\n");
+       if (rc)
                return rc;
-       }
 
        dev_info(dev->device, "device registered successfully\n");
 
index 025686d..29d00c4 100644 (file)
@@ -685,10 +685,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
        write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
 
        rc = i2c_add_numbered_adapter(p_adap);
-       if (rc < 0) {
-               dev_err(&pdev->dev, "Can't add i2c adapter!\n");
+       if (rc < 0)
                goto out_error;
-       }
 
        platform_set_drvdata(pdev, iface);
 
index 385b57b..0652281 100644 (file)
@@ -648,10 +648,8 @@ static int brcmstb_i2c_probe(struct platform_device *pdev)
        adap->dev.parent = &pdev->dev;
        adap->dev.of_node = pdev->dev.of_node;
        rc = i2c_add_adapter(adap);
-       if (rc) {
-               dev_err(dev->device, "failed to add adapter\n");
+       if (rc)
                goto probe_errorout;
-       }
 
        dev_info(dev->device, "%s@%dhz registered in %s mode\n",
                 int_name ? int_name : " ", dev->clk_freq_hz,
index 90bbd9f..1cc1e79 100644 (file)
@@ -963,10 +963,8 @@ static int cdns_i2c_probe(struct platform_device *pdev)
        }
 
        ret = i2c_add_adapter(&id->adap);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
+       if (ret < 0)
                goto err_clk_dis;
-       }
 
        /*
         * Cadence I2C controller has a bug wherein it generates
index ee57c1e..d89bde2 100644 (file)
@@ -665,10 +665,8 @@ static int cpm_i2c_probe(struct platform_device *ofdev)
        cpm->adap.nr = (data && len == 4) ? be32_to_cpup(data) : -1;
        result = i2c_add_numbered_adapter(&cpm->adap);
 
-       if (result < 0) {
-               dev_err(&ofdev->dev, "Unable to register with I2C\n");
+       if (result < 0)
                goto out_shut;
-       }
 
        dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
                cpm->adap.name);
index 2d5ff86..9b36a7b 100644 (file)
@@ -281,10 +281,8 @@ static int ec_i2c_probe(struct platform_device *pdev)
        bus->adap.retries = I2C_MAX_RETRIES;
 
        err = i2c_add_adapter(&bus->adap);
-       if (err) {
-               dev_err(dev, "cannot register i2c adapter\n");
+       if (err)
                return err;
-       }
        platform_set_drvdata(pdev, bus);
 
        return err;
index a8bdcb5..9e7ef5c 100644 (file)
@@ -846,10 +846,8 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 
        adap->nr = pdev->id;
        r = i2c_add_numbered_adapter(adap);
-       if (r) {
-               dev_err(&pdev->dev, "failure adding adapter\n");
+       if (r)
                goto err_unuse_clocks;
-       }
 
        return 0;
 
index c6922b8..52a603a 100644 (file)
@@ -42,6 +42,8 @@
 #define DW_IC_SS_SCL_LCNT      0x18
 #define DW_IC_FS_SCL_HCNT      0x1c
 #define DW_IC_FS_SCL_LCNT      0x20
+#define DW_IC_HS_SCL_HCNT      0x24
+#define DW_IC_HS_SCL_LCNT      0x28
 #define DW_IC_INTR_STAT                0x2c
 #define DW_IC_INTR_MASK                0x30
 #define DW_IC_RAW_INTR_STAT    0x34
                                         DW_IC_INTR_TX_ABRT | \
                                         DW_IC_INTR_STOP_DET)
 
-#define DW_IC_STATUS_ACTIVITY  0x1
+#define DW_IC_STATUS_ACTIVITY          0x1
+#define DW_IC_STATUS_TFE               BIT(2)
+#define DW_IC_STATUS_MST_ACTIVITY      BIT(5)
 
 #define DW_IC_ERR_TX_ABRT      0x1
 
 #define DW_IC_TAR_10BITADDR_MASTER BIT(12)
 
+#define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH     (BIT(2) | BIT(3))
+#define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK     GENMASK(3, 2)
+
 /*
  * status codes
  */
@@ -251,11 +258,16 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
 }
 
 static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
+{
+       dw_writel(dev, enable, DW_IC_ENABLE);
+}
+
+static void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable)
 {
        int timeout = 100;
 
        do {
-               dw_writel(dev, enable, DW_IC_ENABLE);
+               __i2c_dw_enable(dev, enable);
                if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == enable)
                        return;
 
@@ -282,6 +294,28 @@ static unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
        return dev->get_clk_rate_khz(dev);
 }
 
+static int i2c_dw_acquire_lock(struct dw_i2c_dev *dev)
+{
+       int ret;
+
+       if (!dev->acquire_lock)
+               return 0;
+
+       ret = dev->acquire_lock(dev);
+       if (!ret)
+               return 0;
+
+       dev_err(dev->dev, "couldn't acquire bus ownership\n");
+
+       return ret;
+}
+
+static void i2c_dw_release_lock(struct dw_i2c_dev *dev)
+{
+       if (dev->release_lock)
+               dev->release_lock(dev);
+}
+
 /**
  * i2c_dw_init() - initialize the designware i2c master hardware
  * @dev: device private data
@@ -293,17 +327,13 @@ static unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
 int i2c_dw_init(struct dw_i2c_dev *dev)
 {
        u32 hcnt, lcnt;
-       u32 reg;
+       u32 reg, comp_param1;
        u32 sda_falling_time, scl_falling_time;
        int ret;
 
-       if (dev->acquire_lock) {
-               ret = dev->acquire_lock(dev);
-               if (ret) {
-                       dev_err(dev->dev, "couldn't acquire bus ownership\n");
-                       return ret;
-               }
-       }
+       ret = i2c_dw_acquire_lock(dev);
+       if (ret)
+               return ret;
 
        reg = dw_readl(dev, DW_IC_COMP_TYPE);
        if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
@@ -315,13 +345,14 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
        } else if (reg != DW_IC_COMP_TYPE_VALUE) {
                dev_err(dev->dev, "Unknown Synopsys component type: "
                        "0x%08x\n", reg);
-               if (dev->release_lock)
-                       dev->release_lock(dev);
+               i2c_dw_release_lock(dev);
                return -ENODEV;
        }
 
+       comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
+
        /* Disable the adapter */
-       __i2c_dw_enable(dev, false);
+       __i2c_dw_enable_and_wait(dev, false);
 
        /* set standard and fast speed deviders for high/low periods */
 
@@ -347,8 +378,11 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
        dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
        dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
 
-       /* Set SCL timing parameters for fast-mode */
-       if (dev->fs_hcnt && dev->fs_lcnt) {
+       /* Set SCL timing parameters for fast-mode or fast-mode plus */
+       if ((dev->clk_freq == 1000000) && dev->fp_hcnt && dev->fp_lcnt) {
+               hcnt = dev->fp_hcnt;
+               lcnt = dev->fp_lcnt;
+       } else if (dev->fs_hcnt && dev->fs_lcnt) {
                hcnt = dev->fs_hcnt;
                lcnt = dev->fs_lcnt;
        } else {
@@ -366,6 +400,23 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
        dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
        dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
 
+       if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) ==
+               DW_IC_CON_SPEED_HIGH) {
+               if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK)
+                       != DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH) {
+                       dev_err(dev->dev, "High Speed not supported!\n");
+                       dev->master_cfg &= ~DW_IC_CON_SPEED_MASK;
+                       dev->master_cfg |= DW_IC_CON_SPEED_FAST;
+               } else if (dev->hs_hcnt && dev->hs_lcnt) {
+                       hcnt = dev->hs_hcnt;
+                       lcnt = dev->hs_lcnt;
+                       dw_writel(dev, hcnt, DW_IC_HS_SCL_HCNT);
+                       dw_writel(dev, lcnt, DW_IC_HS_SCL_LCNT);
+                       dev_dbg(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n",
+                               hcnt, lcnt);
+               }
+       }
+
        /* Configure SDA Hold Time if required */
        if (dev->sda_hold_time) {
                reg = dw_readl(dev, DW_IC_COMP_VERSION);
@@ -383,8 +434,8 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
        /* configure the i2c master */
        dw_writel(dev, dev->master_cfg , DW_IC_CON);
 
-       if (dev->release_lock)
-               dev->release_lock(dev);
+       i2c_dw_release_lock(dev);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(i2c_dw_init);
@@ -411,27 +462,45 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
 static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
 {
        struct i2c_msg *msgs = dev->msgs;
-       u32 ic_con, ic_tar = 0;
+       u32 ic_tar = 0;
+       bool enabled;
 
-       /* Disable the adapter */
-       __i2c_dw_enable(dev, false);
+       enabled = dw_readl(dev, DW_IC_ENABLE_STATUS) & 1;
+
+       if (enabled) {
+               u32 ic_status;
+
+               /*
+                * Only disable adapter if ic_tar and ic_con can't be
+                * dynamically updated
+                */
+               ic_status = dw_readl(dev, DW_IC_STATUS);
+               if (!dev->dynamic_tar_update_enabled ||
+                   (ic_status & DW_IC_STATUS_MST_ACTIVITY) ||
+                   !(ic_status & DW_IC_STATUS_TFE)) {
+                       __i2c_dw_enable_and_wait(dev, false);
+                       enabled = false;
+               }
+       }
 
        /* if the slave address is ten bit address, enable 10BITADDR */
-       ic_con = dw_readl(dev, DW_IC_CON);
-       if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) {
-               ic_con |= DW_IC_CON_10BITADDR_MASTER;
+       if (dev->dynamic_tar_update_enabled) {
                /*
                 * If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing
-                * mode has to be enabled via bit 12 of IC_TAR register.
-                * We set it always as I2C_DYNAMIC_TAR_UPDATE can't be
-                * detected from registers.
+                * mode has to be enabled via bit 12 of IC_TAR register,
+                * otherwise bit 4 of IC_CON is used.
                 */
-               ic_tar = DW_IC_TAR_10BITADDR_MASTER;
+               if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
+                       ic_tar = DW_IC_TAR_10BITADDR_MASTER;
        } else {
-               ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
-       }
+               u32 ic_con = dw_readl(dev, DW_IC_CON);
 
-       dw_writel(dev, ic_con, DW_IC_CON);
+               if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
+                       ic_con |= DW_IC_CON_10BITADDR_MASTER;
+               else
+                       ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
+               dw_writel(dev, ic_con, DW_IC_CON);
+       }
 
        /*
         * Set the slave (target) address and enable 10-bit addressing mode
@@ -442,8 +511,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
        /* enforce disabled interrupts (due to HW issues) */
        i2c_dw_disable_int(dev);
 
-       /* Enable the adapter */
-       __i2c_dw_enable(dev, true);
+       if (!enabled)
+               __i2c_dw_enable(dev, true);
 
        /* Clear and enable interrupts */
        dw_readl(dev, DW_IC_CLR_INTR);
@@ -624,7 +693,8 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
 }
 
 /*
- * Prepare controller for a transaction and call i2c_dw_xfer_msg
+ * Prepare controller for a transaction and start transfer by calling
+ * i2c_dw_xfer_init()
  */
 static int
 i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
@@ -647,13 +717,9 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        dev->abort_source = 0;
        dev->rx_outstanding = 0;
 
-       if (dev->acquire_lock) {
-               ret = dev->acquire_lock(dev);
-               if (ret) {
-                       dev_err(dev->dev, "couldn't acquire bus ownership\n");
-                       goto done_nolock;
-               }
-       }
+       ret = i2c_dw_acquire_lock(dev);
+       if (ret)
+               goto done_nolock;
 
        ret = i2c_dw_wait_bus_not_busy(dev);
        if (ret < 0)
@@ -671,16 +737,6 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
                goto done;
        }
 
-       /*
-        * We must disable the adapter before returning and signaling the end
-        * of the current transfer. Otherwise the hardware might continue
-        * generating interrupts which in turn causes a race condition with
-        * the following transfer.  Needs some more investigation if the
-        * additional interrupts are a hardware bug or this driver doesn't
-        * handle them correctly yet.
-        */
-       __i2c_dw_enable(dev, false);
-
        if (dev->msg_err) {
                ret = dev->msg_err;
                goto done;
@@ -700,8 +756,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        ret = -EIO;
 
 done:
-       if (dev->release_lock)
-               dev->release_lock(dev);
+       i2c_dw_release_lock(dev);
 
 done_nolock:
        pm_runtime_mark_last_busy(dev->dev);
@@ -818,9 +873,19 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
         */
 
 tx_aborted:
-       if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
+       if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET))
+                       || dev->msg_err) {
+               /*
+                * We must disable interruts before returning and signaling
+                * the end of the current transfer. Otherwise the hardware
+                * might continue generating interrupts for non-existent
+                * transfers.
+                */
+               i2c_dw_disable_int(dev);
+               dw_readl(dev, DW_IC_CLR_INTR);
+
                complete(&dev->cmd_complete);
-       else if (unlikely(dev->accessor_flags & ACCESS_INTR_MASK)) {
+       else if (unlikely(dev->accessor_flags & ACCESS_INTR_MASK)) {
                /* workaround to trigger pending interrupt */
                stat = dw_readl(dev, DW_IC_INTR_MASK);
                i2c_dw_disable_int(dev);
@@ -833,7 +898,7 @@ tx_aborted:
 void i2c_dw_disable(struct dw_i2c_dev *dev)
 {
        /* Disable controller */
-       __i2c_dw_enable(dev, false);
+       __i2c_dw_enable_and_wait(dev, false);
 
        /* Disable all interupts */
        dw_writel(dev, 0, DW_IC_INTR_MASK);
@@ -857,6 +922,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
 {
        struct i2c_adapter *adap = &dev->adapter;
        int r;
+       u32 reg;
 
        init_completion(&dev->cmd_complete);
 
@@ -864,6 +930,26 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
        if (r)
                return r;
 
+       r = i2c_dw_acquire_lock(dev);
+       if (r)
+               return r;
+
+       /*
+        * Test if dynamic TAR update is enabled in this controller by writing
+        * to IC_10BITADDR_MASTER field in IC_CON: when it is enabled this
+        * field is read-only so it should not succeed
+        */
+       reg = dw_readl(dev, DW_IC_CON);
+       dw_writel(dev, reg ^ DW_IC_CON_10BITADDR_MASTER, DW_IC_CON);
+
+       if ((dw_readl(dev, DW_IC_CON) & DW_IC_CON_10BITADDR_MASTER) ==
+           (reg & DW_IC_CON_10BITADDR_MASTER)) {
+               dev->dynamic_tar_update_enabled = true;
+               dev_dbg(dev->dev, "Dynamic TAR update enabled");
+       }
+
+       i2c_dw_release_lock(dev);
+
        snprintf(adap->name, sizeof(adap->name),
                 "Synopsys DesignWare I2C adapter");
        adap->retries = 3;
index 38493a7..0d44d2a 100644 (file)
@@ -26,6 +26,7 @@
 #define DW_IC_CON_MASTER               0x1
 #define DW_IC_CON_SPEED_STD            0x2
 #define DW_IC_CON_SPEED_FAST           0x4
+#define DW_IC_CON_SPEED_HIGH           0x6
 #define DW_IC_CON_SPEED_MASK           0x6
 #define DW_IC_CON_10BITADDR_MASTER     0x10
 #define DW_IC_CON_RESTART_EN           0x20
  * @tx_fifo_depth: depth of the hardware tx fifo
  * @rx_fifo_depth: depth of the hardware rx fifo
  * @rx_outstanding: current master-rx elements in tx fifo
+ * @clk_freq: bus clock frequency
  * @ss_hcnt: standard speed HCNT value
  * @ss_lcnt: standard speed LCNT value
  * @fs_hcnt: fast speed HCNT value
  * @fs_lcnt: fast speed LCNT value
+ * @fp_hcnt: fast plus HCNT value
+ * @fp_lcnt: fast plus LCNT value
+ * @hs_hcnt: high speed HCNT value
+ * @hs_lcnt: high speed LCNT value
  * @acquire_lock: function to acquire a hardware lock on the bus
  * @release_lock: function to release a hardware lock on the bus
  * @pm_runtime_disabled: true if pm runtime is disabled
@@ -96,6 +102,7 @@ struct dw_i2c_dev {
        unsigned int            tx_fifo_depth;
        unsigned int            rx_fifo_depth;
        int                     rx_outstanding;
+       u32                     clk_freq;
        u32                     sda_hold_time;
        u32                     sda_falling_time;
        u32                     scl_falling_time;
@@ -103,9 +110,14 @@ struct dw_i2c_dev {
        u16                     ss_lcnt;
        u16                     fs_hcnt;
        u16                     fs_lcnt;
+       u16                     fp_hcnt;
+       u16                     fp_lcnt;
+       u16                     hs_hcnt;
+       u16                     hs_lcnt;
        int                     (*acquire_lock)(struct dw_i2c_dev *dev);
        void                    (*release_lock)(struct dw_i2c_dev *dev);
        bool                    pm_runtime_disabled;
+       bool                    dynamic_tar_update_enabled;
 };
 
 #define ACCESS_SWAP            0x00000001
index d656657..0b42a12 100644 (file)
@@ -107,6 +107,8 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
        dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, NULL);
        dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
                           &dev->sda_hold_time);
+       dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, NULL);
+       dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, NULL);
 
        id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
        if (id && id->driver_data)
@@ -155,7 +157,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
        struct i2c_adapter *adap;
        struct resource *mem;
        int irq, r;
-       u32 clk_freq, ht = 0;
+       u32 acpi_speed, ht = 0;
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
@@ -175,10 +177,10 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, dev);
 
        /* fast mode by default because of legacy reasons */
-       clk_freq = 400000;
+       dev->clk_freq = 400000;
 
        if (pdata) {
-               clk_freq = pdata->i2c_scl_freq;
+               dev->clk_freq = pdata->i2c_scl_freq;
        } else {
                device_property_read_u32(&pdev->dev, "i2c-sda-hold-time-ns",
                                         &ht);
@@ -187,17 +189,24 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
                device_property_read_u32(&pdev->dev, "i2c-scl-falling-time-ns",
                                         &dev->scl_falling_time);
                device_property_read_u32(&pdev->dev, "clock-frequency",
-                                        &clk_freq);
+                                        &dev->clk_freq);
        }
 
+       acpi_speed = i2c_acpi_find_bus_speed(&pdev->dev);
+       if (acpi_speed)
+               dev->clk_freq = acpi_speed;
+
        if (has_acpi_companion(&pdev->dev))
                dw_i2c_acpi_configure(pdev);
 
        /*
-        * Only standard mode at 100kHz and fast mode at 400kHz are supported.
+        * Only standard mode at 100kHz, fast mode at 400kHz,
+        * fast mode plus at 1MHz and high speed mode at 3.4MHz are supported.
         */
-       if (clk_freq != 100000 && clk_freq != 400000) {
-               dev_err(&pdev->dev, "Only 100kHz and 400kHz supported");
+       if (dev->clk_freq != 100000 && dev->clk_freq != 400000
+           && dev->clk_freq != 1000000 && dev->clk_freq != 3400000) {
+               dev_err(&pdev->dev,
+                       "Only 100kHz, 400kHz, 1MHz and 3.4MHz supported");
                return -EINVAL;
        }
 
@@ -212,12 +221,20 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
                I2C_FUNC_SMBUS_BYTE_DATA |
                I2C_FUNC_SMBUS_WORD_DATA |
                I2C_FUNC_SMBUS_I2C_BLOCK;
-       if (clk_freq == 100000)
-               dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
-                       DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_STD;
-       else
-               dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
-                       DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
+
+       dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+                         DW_IC_CON_RESTART_EN;
+
+       switch (dev->clk_freq) {
+       case 100000:
+               dev->master_cfg |= DW_IC_CON_SPEED_STD;
+               break;
+       case 3400000:
+               dev->master_cfg |= DW_IC_CON_SPEED_HIGH;
+               break;
+       default:
+               dev->master_cfg |= DW_IC_CON_SPEED_FAST;
+       }
 
        dev->clk = devm_clk_get(&pdev->dev, NULL);
        if (!i2c_dw_plat_prepare_clk(dev, true)) {
index b19a310..f718ee4 100644 (file)
@@ -487,10 +487,8 @@ static int diolan_u2c_probe(struct usb_interface *interface,
 
        /* and finally attach to i2c layer */
        ret = i2c_add_adapter(&dev->adapter);
-       if (ret < 0) {
-               dev_err(&interface->dev, "failed to add I2C adapter\n");
+       if (ret < 0)
                goto error_free;
-       }
 
        dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n");
 
index f2eb4f7..8acda2a 100644 (file)
@@ -228,10 +228,8 @@ static int dln2_i2c_probe(struct platform_device *pdev)
 
        /* and finally attach to i2c layer */
        ret = i2c_add_adapter(&dln2->adapter);
-       if (ret < 0) {
-               dev_err(dev, "failed to add I2C adapter: %d\n", ret);
+       if (ret < 0)
                goto out_disable;
-       }
 
        return 0;
 
index e253598..aa336ba 100644 (file)
@@ -438,7 +438,6 @@ static int efm32_i2c_probe(struct platform_device *pdev)
 
        ret = i2c_add_adapter(&ddata->adapter);
        if (ret) {
-               dev_err(&pdev->dev, "failed to add i2c adapter (%d)\n", ret);
                free_irq(ddata->irq, ddata);
 
 err_disable_clk:
index c0e3ada..bea6071 100644 (file)
@@ -796,10 +796,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
        exynos5_i2c_reset(i2c);
 
        ret = i2c_add_adapter(&i2c->adap);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+       if (ret < 0)
                goto err_clk;
-       }
 
        platform_set_drvdata(pdev, i2c);
 
index 7c69664..ae7f318 100644 (file)
@@ -478,10 +478,8 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
        pm_runtime_enable(priv->dev);
 
        ret = i2c_add_adapter(&priv->adap);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+       if (ret < 0)
                goto err_runtime;
-       }
 
        return ret;
 
index 5ef9b73..22a0ed4 100644 (file)
@@ -1613,7 +1613,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
                "SMBus I801 adapter at %04lx", priv->smba);
        err = i2c_add_adapter(&priv->adapter);
        if (err) {
-               dev_err(&dev->dev, "Failed to add SMBus adapter\n");
                i801_acpi_remove(priv);
                return err;
        }
index cdaa7be..412b91d 100644 (file)
@@ -751,10 +751,8 @@ static int iic_probe(struct platform_device *ofdev)
        adap->timeout = HZ;
 
        ret = i2c_add_adapter(adap);
-       if (ret  < 0) {
-               dev_err(&ofdev->dev, "failed to register i2c adapter\n");
+       if (ret  < 0)
                goto error_cleanup;
-       }
 
        dev_info(&ofdev->dev, "using %s mode\n",
                 dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
index ea20425..db8e8b4 100644 (file)
@@ -1394,10 +1394,8 @@ static int img_i2c_probe(struct platform_device *pdev)
                goto disable_clk;
 
        ret = i2c_add_numbered_adapter(&i2c->adap);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to add adapter\n");
+       if (ret < 0)
                goto disable_clk;
-       }
 
        return 0;
 
index 1844bc9..cb11eee 100644 (file)
@@ -1129,10 +1129,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
 
        /* Add I2C adapter */
        ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "registration failed\n");
+       if (ret < 0)
                goto rpm_disable;
-       }
 
        pm_runtime_mark_last_busy(&pdev->dev);
        pm_runtime_put_autosuspend(&pdev->dev);
index c2f25f1..0cf1379 100644 (file)
@@ -288,10 +288,8 @@ static int smbus_sch_probe(struct platform_device *dev)
                "SMBus SCH adapter at %04x", sch_smba);
 
        retval = i2c_add_adapter(&sch_adapter);
-       if (retval) {
-               dev_err(&dev->dev, "Couldn't register adapter!\n");
+       if (retval)
                sch_smba = 0;
-       }
 
        return retval;
 }
index 1c87077..f573448 100644 (file)
@@ -922,10 +922,8 @@ ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                return err;
 
        err = i2c_add_adapter(&priv->adapter);
-       if (err) {
-               dev_err(&pdev->dev, "Failed to add SMBus iSMT adapter\n");
+       if (err)
                return -ENODEV;
-       }
        return 0;
 }
 
index cd98725..b8ea621 100644 (file)
@@ -798,10 +798,8 @@ static int jz4780_i2c_probe(struct platform_device *pdev)
                goto err;
 
        ret = i2c_add_adapter(&i2c->adap);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Failed to add bus\n");
+       if (ret < 0)
                goto err;
-       }
 
        return 0;
 
index 586a152..9b1fef4 100644 (file)
@@ -432,10 +432,8 @@ static int i2c_lpc2k_probe(struct platform_device *pdev)
        i2c->adap.dev.of_node = pdev->dev.of_node;
 
        ret = i2c_add_adapter(&i2c->adap);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to add adapter!\n");
+       if (ret < 0)
                goto fail_clk;
-       }
 
        dev_info(&pdev->dev, "LPC2K I2C adapter\n");
 
index 76e2898..8570e6d 100644 (file)
@@ -453,7 +453,6 @@ static int meson_i2c_probe(struct platform_device *pdev)
 
        ret = i2c_add_adapter(&i2c->adap);
        if (ret < 0) {
-               dev_err(&pdev->dev, "can't register adapter\n");
                clk_unprepare(i2c->clk);
                return ret;
        }
index 48ecffe..565a49a 100644 (file)
@@ -737,10 +737,8 @@ static int fsl_i2c_probe(struct platform_device *op)
        i2c->adap.dev.of_node = of_node_get(op->dev.of_node);
 
        result = i2c_add_adapter(&i2c->adap);
-       if (result < 0) {
-               dev_err(i2c->dev, "failed to add adapter\n");
+       if (result < 0)
                goto fail_add;
-       }
 
        return result;
 
index d9373e6..4a7d9bc 100644 (file)
@@ -786,10 +786,8 @@ static int mtk_i2c_probe(struct platform_device *pdev)
 
        i2c_set_adapdata(&i2c->adap, i2c);
        ret = i2c_add_adapter(&i2c->adap);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to add i2c bus to i2c core\n");
+       if (ret)
                return ret;
-       }
 
        platform_set_drvdata(pdev, i2c);
 
index 033846c..5738556 100644 (file)
@@ -868,7 +868,6 @@ static int mxs_i2c_probe(struct platform_device *pdev)
        i2c_set_adapdata(adap, i2c);
        err = i2c_add_numbered_adapter(adap);
        if (err) {
-               dev_err(dev, "Failed to add adapter (%d)\n", err);
                writel(MXS_I2C_CTRL0_SFTRST,
                                i2c->regs + MXS_I2C_CTRL0_SET);
                return err;
index 42fcc94..374b35e 100644 (file)
@@ -366,7 +366,6 @@ static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg,
 
        error = i2c_add_adapter(&smbus->adapter);
        if (error) {
-               dev_err(&smbus->adapter.dev, "Failed to register adapter.\n");
                release_region(smbus->base, smbus->size);
                return error;
        }
index bcd17e8..da6609d 100644 (file)
@@ -1046,10 +1046,8 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
                 adap->name, dev->virtbase);
 
        ret = i2c_add_adapter(adap);
-       if (ret) {
-               dev_err(&adev->dev, "failed to add adapter\n");
+       if (ret)
                goto err_no_adap;
-       }
 
        pm_runtime_put(&adev->dev);
 
index ac88a52..34f1889 100644 (file)
@@ -494,10 +494,8 @@ static int ocores_i2c_probe(struct platform_device *pdev)
 
        /* add i2c adapter to i2c tree */
        ret = i2c_add_adapter(&i2c->adap);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to add adapter\n");
+       if (ret)
                goto err_clk;
-       }
 
        /* add in known devices to the bus */
        if (pdata) {
diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c
new file mode 100644 (file)
index 0000000..f45ea5e
--- /dev/null
@@ -0,0 +1,810 @@
+/*
+ * (C) Copyright 2009-2010
+ * Nokia Siemens Networks, michael.lawnick.ext@nsn.com
+ *
+ * Portions Copyright (C) 2010 - 2016 Cavium, Inc.
+ *
+ * This file contains the shared part of the driver for the i2c adapter in
+ * Cavium Networks' OCTEON processors and ThunderX SOCs.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "i2c-octeon-core.h"
+
+/* interrupt service routine */
+irqreturn_t octeon_i2c_isr(int irq, void *dev_id)
+{
+       struct octeon_i2c *i2c = dev_id;
+
+       i2c->int_disable(i2c);
+       wake_up(&i2c->queue);
+
+       return IRQ_HANDLED;
+}
+
+static bool octeon_i2c_test_iflg(struct octeon_i2c *i2c)
+{
+       return (octeon_i2c_ctl_read(i2c) & TWSI_CTL_IFLG);
+}
+
+static bool octeon_i2c_test_ready(struct octeon_i2c *i2c, bool *first)
+{
+       if (octeon_i2c_test_iflg(i2c))
+               return true;
+
+       if (*first) {
+               *first = false;
+               return false;
+       }
+
+       /*
+        * IRQ has signaled an event but IFLG hasn't changed.
+        * Sleep and retry once.
+        */
+       usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT);
+       return octeon_i2c_test_iflg(i2c);
+}
+
+/**
+ * octeon_i2c_wait - wait for the IFLG to be set
+ * @i2c: The struct octeon_i2c
+ *
+ * Returns 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_wait(struct octeon_i2c *i2c)
+{
+       long time_left;
+       bool first = true;
+
+       /*
+        * Some chip revisions don't assert the irq in the interrupt
+        * controller. So we must poll for the IFLG change.
+        */
+       if (i2c->broken_irq_mode) {
+               u64 end = get_jiffies_64() + i2c->adap.timeout;
+
+               while (!octeon_i2c_test_iflg(i2c) &&
+                      time_before64(get_jiffies_64(), end))
+                       usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT);
+
+               return octeon_i2c_test_iflg(i2c) ? 0 : -ETIMEDOUT;
+       }
+
+       i2c->int_enable(i2c);
+       time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_ready(i2c, &first),
+                                      i2c->adap.timeout);
+       i2c->int_disable(i2c);
+
+       if (i2c->broken_irq_check && !time_left &&
+           octeon_i2c_test_iflg(i2c)) {
+               dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n");
+               i2c->broken_irq_mode = true;
+               return 0;
+       }
+
+       if (!time_left)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static bool octeon_i2c_hlc_test_valid(struct octeon_i2c *i2c)
+{
+       return (__raw_readq(i2c->twsi_base + SW_TWSI(i2c)) & SW_TWSI_V) == 0;
+}
+
+static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c, bool *first)
+{
+       /* check if valid bit is cleared */
+       if (octeon_i2c_hlc_test_valid(i2c))
+               return true;
+
+       if (*first) {
+               *first = false;
+               return false;
+       }
+
+       /*
+        * IRQ has signaled an event but valid bit isn't cleared.
+        * Sleep and retry once.
+        */
+       usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT);
+       return octeon_i2c_hlc_test_valid(i2c);
+}
+
+static void octeon_i2c_hlc_int_clear(struct octeon_i2c *i2c)
+{
+       /* clear ST/TS events, listen for neither */
+       octeon_i2c_write_int(i2c, TWSI_INT_ST_INT | TWSI_INT_TS_INT);
+}
+
+/*
+ * Cleanup low-level state & enable high-level controller.
+ */
+static void octeon_i2c_hlc_enable(struct octeon_i2c *i2c)
+{
+       int try = 0;
+       u64 val;
+
+       if (i2c->hlc_enabled)
+               return;
+       i2c->hlc_enabled = true;
+
+       while (1) {
+               val = octeon_i2c_ctl_read(i2c);
+               if (!(val & (TWSI_CTL_STA | TWSI_CTL_STP)))
+                       break;
+
+               /* clear IFLG event */
+               if (val & TWSI_CTL_IFLG)
+                       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
+
+               if (try++ > 100) {
+                       pr_err("%s: giving up\n", __func__);
+                       break;
+               }
+
+               /* spin until any start/stop has finished */
+               udelay(10);
+       }
+       octeon_i2c_ctl_write(i2c, TWSI_CTL_CE | TWSI_CTL_AAK | TWSI_CTL_ENAB);
+}
+
+static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c)
+{
+       if (!i2c->hlc_enabled)
+               return;
+
+       i2c->hlc_enabled = false;
+       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
+}
+
+/**
+ * octeon_i2c_hlc_wait - wait for an HLC operation to complete
+ * @i2c: The struct octeon_i2c
+ *
+ * Returns 0 on success, otherwise -ETIMEDOUT.
+ */
+static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
+{
+       bool first = true;
+       int time_left;
+
+       /*
+        * Some cn38xx boards don't assert the irq in the interrupt
+        * controller. So we must poll for the valid bit change.
+        */
+       if (i2c->broken_irq_mode) {
+               u64 end = get_jiffies_64() + i2c->adap.timeout;
+
+               while (!octeon_i2c_hlc_test_valid(i2c) &&
+                      time_before64(get_jiffies_64(), end))
+                       usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT);
+
+               return octeon_i2c_hlc_test_valid(i2c) ? 0 : -ETIMEDOUT;
+       }
+
+       i2c->hlc_int_enable(i2c);
+       time_left = wait_event_timeout(i2c->queue,
+                                      octeon_i2c_hlc_test_ready(i2c, &first),
+                                      i2c->adap.timeout);
+       i2c->hlc_int_disable(i2c);
+       if (!time_left)
+               octeon_i2c_hlc_int_clear(i2c);
+
+       if (i2c->broken_irq_check && !time_left &&
+           octeon_i2c_hlc_test_valid(i2c)) {
+               dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n");
+               i2c->broken_irq_mode = true;
+               return 0;
+       }
+
+       if (!time_left)
+               return -ETIMEDOUT;
+       return 0;
+}
+
+static int octeon_i2c_check_status(struct octeon_i2c *i2c, int final_read)
+{
+       u8 stat = octeon_i2c_stat_read(i2c);
+
+       switch (stat) {
+       /* Everything is fine */
+       case STAT_IDLE:
+       case STAT_AD2W_ACK:
+       case STAT_RXADDR_ACK:
+       case STAT_TXADDR_ACK:
+       case STAT_TXDATA_ACK:
+               return 0;
+
+       /* ACK allowed on pre-terminal bytes only */
+       case STAT_RXDATA_ACK:
+               if (!final_read)
+                       return 0;
+               return -EIO;
+
+       /* NAK allowed on terminal byte only */
+       case STAT_RXDATA_NAK:
+               if (final_read)
+                       return 0;
+               return -EIO;
+
+       /* Arbitration lost */
+       case STAT_LOST_ARB_38:
+       case STAT_LOST_ARB_68:
+       case STAT_LOST_ARB_78:
+       case STAT_LOST_ARB_B0:
+               return -EAGAIN;
+
+       /* Being addressed as slave, should back off & listen */
+       case STAT_SLAVE_60:
+       case STAT_SLAVE_70:
+       case STAT_GENDATA_ACK:
+       case STAT_GENDATA_NAK:
+               return -EOPNOTSUPP;
+
+       /* Core busy as slave */
+       case STAT_SLAVE_80:
+       case STAT_SLAVE_88:
+       case STAT_SLAVE_A0:
+       case STAT_SLAVE_A8:
+       case STAT_SLAVE_LOST:
+       case STAT_SLAVE_NAK:
+       case STAT_SLAVE_ACK:
+               return -EOPNOTSUPP;
+
+       case STAT_TXDATA_NAK:
+               return -EIO;
+       case STAT_TXADDR_NAK:
+       case STAT_RXADDR_NAK:
+       case STAT_AD2W_NAK:
+               return -ENXIO;
+       default:
+               dev_err(i2c->dev, "unhandled state: %d\n", stat);
+               return -EIO;
+       }
+}
+
+static int octeon_i2c_recovery(struct octeon_i2c *i2c)
+{
+       int ret;
+
+       ret = i2c_recover_bus(&i2c->adap);
+       if (ret)
+               /* recover failed, try hardware re-init */
+               ret = octeon_i2c_init_lowlevel(i2c);
+       return ret;
+}
+
+/**
+ * octeon_i2c_start - send START to the bus
+ * @i2c: The struct octeon_i2c
+ *
+ * Returns 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_start(struct octeon_i2c *i2c)
+{
+       int ret;
+       u8 stat;
+
+       octeon_i2c_hlc_disable(i2c);
+
+       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA);
+       ret = octeon_i2c_wait(i2c);
+       if (ret)
+               goto error;
+
+       stat = octeon_i2c_stat_read(i2c);
+       if (stat == STAT_START || stat == STAT_REP_START)
+               /* START successful, bail out */
+               return 0;
+
+error:
+       /* START failed, try to recover */
+       ret = octeon_i2c_recovery(i2c);
+       return (ret) ? ret : -EAGAIN;
+}
+
+/* send STOP to the bus */
+static void octeon_i2c_stop(struct octeon_i2c *i2c)
+{
+       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STP);
+}
+
+/**
+ * octeon_i2c_read - receive data from the bus via low-level controller
+ * @i2c: The struct octeon_i2c
+ * @target: Target address
+ * @data: Pointer to the location to store the data
+ * @rlength: Length of the data
+ * @recv_len: flag for length byte
+ *
+ * The address is sent over the bus, then the data is read.
+ *
+ * Returns 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
+                          u8 *data, u16 *rlength, bool recv_len)
+{
+       int i, result, length = *rlength;
+       bool final_read = false;
+
+       octeon_i2c_data_write(i2c, (target << 1) | 1);
+       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
+
+       result = octeon_i2c_wait(i2c);
+       if (result)
+               return result;
+
+       /* address OK ? */
+       result = octeon_i2c_check_status(i2c, false);
+       if (result)
+               return result;
+
+       for (i = 0; i < length; i++) {
+               /*
+                * For the last byte to receive TWSI_CTL_AAK must not be set.
+                *
+                * A special case is I2C_M_RECV_LEN where we don't know the
+                * additional length yet. If recv_len is set we assume we're
+                * not reading the final byte and therefore need to set
+                * TWSI_CTL_AAK.
+                */
+               if ((i + 1 == length) && !(recv_len && i == 0))
+                       final_read = true;
+
+               /* clear iflg to allow next event */
+               if (final_read)
+                       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
+               else
+                       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_AAK);
+
+               result = octeon_i2c_wait(i2c);
+               if (result)
+                       return result;
+
+               data[i] = octeon_i2c_data_read(i2c);
+               if (recv_len && i == 0) {
+                       if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
+                               return -EPROTO;
+                       length += data[i];
+               }
+
+               result = octeon_i2c_check_status(i2c, final_read);
+               if (result)
+                       return result;
+       }
+       *rlength = length;
+       return 0;
+}
+
+/**
+ * octeon_i2c_write - send data to the bus via low-level controller
+ * @i2c: The struct octeon_i2c
+ * @target: Target address
+ * @data: Pointer to the data to be sent
+ * @length: Length of the data
+ *
+ * The address is sent over the bus, then the data.
+ *
+ * Returns 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_write(struct octeon_i2c *i2c, int target,
+                           const u8 *data, int length)
+{
+       int i, result;
+
+       octeon_i2c_data_write(i2c, target << 1);
+       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
+
+       result = octeon_i2c_wait(i2c);
+       if (result)
+               return result;
+
+       for (i = 0; i < length; i++) {
+               result = octeon_i2c_check_status(i2c, false);
+               if (result)
+                       return result;
+
+               octeon_i2c_data_write(i2c, data[i]);
+               octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
+
+               result = octeon_i2c_wait(i2c);
+               if (result)
+                       return result;
+       }
+
+       return 0;
+}
+
+/* high-level-controller pure read of up to 8 bytes */
+static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+       int i, j, ret = 0;
+       u64 cmd;
+
+       octeon_i2c_hlc_enable(i2c);
+       octeon_i2c_hlc_int_clear(i2c);
+
+       cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR;
+       /* SIZE */
+       cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT;
+       /* A */
+       cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
+
+       if (msgs[0].flags & I2C_M_TEN)
+               cmd |= SW_TWSI_OP_10;
+       else
+               cmd |= SW_TWSI_OP_7;
+
+       octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI(i2c));
+       ret = octeon_i2c_hlc_wait(i2c);
+       if (ret)
+               goto err;
+
+       cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+       if ((cmd & SW_TWSI_R) == 0)
+               return -EAGAIN;
+
+       for (i = 0, j = msgs[0].len - 1; i  < msgs[0].len && i < 4; i++, j--)
+               msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff;
+
+       if (msgs[0].len > 4) {
+               cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT(i2c));
+               for (i = 0; i  < msgs[0].len - 4 && i < 4; i++, j--)
+                       msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff;
+       }
+
+err:
+       return ret;
+}
+
+/* high-level-controller pure write of up to 8 bytes */
+static int octeon_i2c_hlc_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+       int i, j, ret = 0;
+       u64 cmd;
+
+       octeon_i2c_hlc_enable(i2c);
+       octeon_i2c_hlc_int_clear(i2c);
+
+       cmd = SW_TWSI_V | SW_TWSI_SOVR;
+       /* SIZE */
+       cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT;
+       /* A */
+       cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
+
+       if (msgs[0].flags & I2C_M_TEN)
+               cmd |= SW_TWSI_OP_10;
+       else
+               cmd |= SW_TWSI_OP_7;
+
+       for (i = 0, j = msgs[0].len - 1; i  < msgs[0].len && i < 4; i++, j--)
+               cmd |= (u64)msgs[0].buf[j] << (8 * i);
+
+       if (msgs[0].len > 4) {
+               u64 ext = 0;
+
+               for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--)
+                       ext |= (u64)msgs[0].buf[j] << (8 * i);
+               octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT(i2c));
+       }
+
+       octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI(i2c));
+       ret = octeon_i2c_hlc_wait(i2c);
+       if (ret)
+               goto err;
+
+       cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+       if ((cmd & SW_TWSI_R) == 0)
+               return -EAGAIN;
+
+       ret = octeon_i2c_check_status(i2c, false);
+
+err:
+       return ret;
+}
+
+/* high-level-controller composite write+read, msg0=addr, msg1=data */
+static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+       int i, j, ret = 0;
+       u64 cmd;
+
+       octeon_i2c_hlc_enable(i2c);
+
+       cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR;
+       /* SIZE */
+       cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT;
+       /* A */
+       cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
+
+       if (msgs[0].flags & I2C_M_TEN)
+               cmd |= SW_TWSI_OP_10_IA;
+       else
+               cmd |= SW_TWSI_OP_7_IA;
+
+       if (msgs[0].len == 2) {
+               u64 ext = 0;
+
+               cmd |= SW_TWSI_EIA;
+               ext = (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+               cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT;
+               octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT(i2c));
+       } else {
+               cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+       }
+
+       octeon_i2c_hlc_int_clear(i2c);
+       octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI(i2c));
+
+       ret = octeon_i2c_hlc_wait(i2c);
+       if (ret)
+               goto err;
+
+       cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+       if ((cmd & SW_TWSI_R) == 0)
+               return -EAGAIN;
+
+       for (i = 0, j = msgs[1].len - 1; i  < msgs[1].len && i < 4; i++, j--)
+               msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff;
+
+       if (msgs[1].len > 4) {
+               cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT(i2c));
+               for (i = 0; i  < msgs[1].len - 4 && i < 4; i++, j--)
+                       msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff;
+       }
+
+err:
+       return ret;
+}
+
+/* high-level-controller composite write+write, m[0]len<=2, m[1]len<=8 */
+static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+       bool set_ext = false;
+       int i, j, ret = 0;
+       u64 cmd, ext = 0;
+
+       octeon_i2c_hlc_enable(i2c);
+
+       cmd = SW_TWSI_V | SW_TWSI_SOVR;
+       /* SIZE */
+       cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT;
+       /* A */
+       cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
+
+       if (msgs[0].flags & I2C_M_TEN)
+               cmd |= SW_TWSI_OP_10_IA;
+       else
+               cmd |= SW_TWSI_OP_7_IA;
+
+       if (msgs[0].len == 2) {
+               cmd |= SW_TWSI_EIA;
+               ext |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+               set_ext = true;
+               cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT;
+       } else {
+               cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+       }
+
+       for (i = 0, j = msgs[1].len - 1; i  < msgs[1].len && i < 4; i++, j--)
+               cmd |= (u64)msgs[1].buf[j] << (8 * i);
+
+       if (msgs[1].len > 4) {
+               for (i = 0; i < msgs[1].len - 4 && i < 4; i++, j--)
+                       ext |= (u64)msgs[1].buf[j] << (8 * i);
+               set_ext = true;
+       }
+       if (set_ext)
+               octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT(i2c));
+
+       octeon_i2c_hlc_int_clear(i2c);
+       octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI(i2c));
+
+       ret = octeon_i2c_hlc_wait(i2c);
+       if (ret)
+               goto err;
+
+       cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+       if ((cmd & SW_TWSI_R) == 0)
+               return -EAGAIN;
+
+       ret = octeon_i2c_check_status(i2c, false);
+
+err:
+       return ret;
+}
+
+/**
+ * octeon_i2c_xfer - The driver's master_xfer function
+ * @adap: Pointer to the i2c_adapter structure
+ * @msgs: Pointer to the messages to be processed
+ * @num: Length of the MSGS array
+ *
+ * Returns the number of messages processed, or a negative errno on failure.
+ */
+int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
+       int i, ret = 0;
+
+       if (num == 1) {
+               if (msgs[0].len > 0 && msgs[0].len <= 8) {
+                       if (msgs[0].flags & I2C_M_RD)
+                               ret = octeon_i2c_hlc_read(i2c, msgs);
+                       else
+                               ret = octeon_i2c_hlc_write(i2c, msgs);
+                       goto out;
+               }
+       } else if (num == 2) {
+               if ((msgs[0].flags & I2C_M_RD) == 0 &&
+                   (msgs[1].flags & I2C_M_RECV_LEN) == 0 &&
+                   msgs[0].len > 0 && msgs[0].len <= 2 &&
+                   msgs[1].len > 0 && msgs[1].len <= 8 &&
+                   msgs[0].addr == msgs[1].addr) {
+                       if (msgs[1].flags & I2C_M_RD)
+                               ret = octeon_i2c_hlc_comp_read(i2c, msgs);
+                       else
+                               ret = octeon_i2c_hlc_comp_write(i2c, msgs);
+                       goto out;
+               }
+       }
+
+       for (i = 0; ret == 0 && i < num; i++) {
+               struct i2c_msg *pmsg = &msgs[i];
+
+               /* zero-length messages are not supported */
+               if (!pmsg->len) {
+                       ret = -EOPNOTSUPP;
+                       break;
+               }
+
+               ret = octeon_i2c_start(i2c);
+               if (ret)
+                       return ret;
+
+               if (pmsg->flags & I2C_M_RD)
+                       ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf,
+                                             &pmsg->len, pmsg->flags & I2C_M_RECV_LEN);
+               else
+                       ret = octeon_i2c_write(i2c, pmsg->addr, pmsg->buf,
+                                              pmsg->len);
+       }
+       octeon_i2c_stop(i2c);
+out:
+       return (ret != 0) ? ret : num;
+}
+
+/* calculate and set clock divisors */
+void octeon_i2c_set_clock(struct octeon_i2c *i2c)
+{
+       int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff;
+       int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000;
+
+       for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) {
+               /*
+                * An mdiv value of less than 2 seems to not work well
+                * with ds1337 RTCs, so we constrain it to larger values.
+                */
+               for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) {
+                       /*
+                        * For given ndiv and mdiv values check the
+                        * two closest thp values.
+                        */
+                       tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10;
+                       tclk *= (1 << ndiv_idx);
+                       thp_base = (i2c->sys_freq / (tclk * 2)) - 1;
+
+                       for (inc = 0; inc <= 1; inc++) {
+                               thp_idx = thp_base + inc;
+                               if (thp_idx < 5 || thp_idx > 0xff)
+                                       continue;
+
+                               foscl = i2c->sys_freq / (2 * (thp_idx + 1));
+                               foscl = foscl / (1 << ndiv_idx);
+                               foscl = foscl / (mdiv_idx + 1) / 10;
+                               diff = abs(foscl - i2c->twsi_freq);
+                               if (diff < delta_hz) {
+                                       delta_hz = diff;
+                                       thp = thp_idx;
+                                       mdiv = mdiv_idx;
+                                       ndiv = ndiv_idx;
+                               }
+                       }
+               }
+       }
+       octeon_i2c_reg_write(i2c, SW_TWSI_OP_TWSI_CLK, thp);
+       octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv);
+}
+
+int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c)
+{
+       u8 status = 0;
+       int tries;
+
+       /* reset controller */
+       octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_RST, 0);
+
+       for (tries = 10; tries && status != STAT_IDLE; tries--) {
+               udelay(1);
+               status = octeon_i2c_stat_read(i2c);
+               if (status == STAT_IDLE)
+                       break;
+       }
+
+       if (status != STAT_IDLE) {
+               dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n",
+                       __func__, status);
+               return -EIO;
+       }
+
+       /* toggle twice to force both teardowns */
+       octeon_i2c_hlc_enable(i2c);
+       octeon_i2c_hlc_disable(i2c);
+       return 0;
+}
+
+static int octeon_i2c_get_scl(struct i2c_adapter *adap)
+{
+       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
+       u64 state;
+
+       state = octeon_i2c_read_int(i2c);
+       return state & TWSI_INT_SCL;
+}
+
+static void octeon_i2c_set_scl(struct i2c_adapter *adap, int val)
+{
+       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
+
+       octeon_i2c_write_int(i2c, TWSI_INT_SCL_OVR);
+}
+
+static int octeon_i2c_get_sda(struct i2c_adapter *adap)
+{
+       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
+       u64 state;
+
+       state = octeon_i2c_read_int(i2c);
+       return state & TWSI_INT_SDA;
+}
+
+static void octeon_i2c_prepare_recovery(struct i2c_adapter *adap)
+{
+       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
+
+       /*
+        * The stop resets the state machine, does not _transmit_ STOP unless
+        * engine was active.
+        */
+       octeon_i2c_stop(i2c);
+
+       octeon_i2c_hlc_disable(i2c);
+       octeon_i2c_write_int(i2c, 0);
+}
+
+static void octeon_i2c_unprepare_recovery(struct i2c_adapter *adap)
+{
+       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
+
+       octeon_i2c_write_int(i2c, 0);
+}
+
+struct i2c_bus_recovery_info octeon_i2c_recovery_info = {
+       .recover_bus = i2c_generic_scl_recovery,
+       .get_scl = octeon_i2c_get_scl,
+       .set_scl = octeon_i2c_set_scl,
+       .get_sda = octeon_i2c_get_sda,
+       .prepare_recovery = octeon_i2c_prepare_recovery,
+       .unprepare_recovery = octeon_i2c_unprepare_recovery,
+};
diff --git a/drivers/i2c/busses/i2c-octeon-core.h b/drivers/i2c/busses/i2c-octeon-core.h
new file mode 100644 (file)
index 0000000..87151ea
--- /dev/null
@@ -0,0 +1,211 @@
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-smbus.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+/* Controller command patterns */
+#define SW_TWSI_V              BIT_ULL(63)     /* Valid bit */
+#define SW_TWSI_EIA            BIT_ULL(61)     /* Extended internal address */
+#define SW_TWSI_R              BIT_ULL(56)     /* Result or read bit */
+#define SW_TWSI_SOVR           BIT_ULL(55)     /* Size override */
+#define SW_TWSI_SIZE_SHIFT     52
+#define SW_TWSI_ADDR_SHIFT     40
+#define SW_TWSI_IA_SHIFT       32              /* Internal address */
+
+/* Controller opcode word (bits 60:57) */
+#define SW_TWSI_OP_SHIFT       57
+#define SW_TWSI_OP_7           (0ULL << SW_TWSI_OP_SHIFT)
+#define SW_TWSI_OP_7_IA                (1ULL << SW_TWSI_OP_SHIFT)
+#define SW_TWSI_OP_10          (2ULL << SW_TWSI_OP_SHIFT)
+#define SW_TWSI_OP_10_IA       (3ULL << SW_TWSI_OP_SHIFT)
+#define SW_TWSI_OP_TWSI_CLK    (4ULL << SW_TWSI_OP_SHIFT)
+#define SW_TWSI_OP_EOP         (6ULL << SW_TWSI_OP_SHIFT) /* Extended opcode */
+
+/* Controller extended opcode word (bits 34:32) */
+#define SW_TWSI_EOP_SHIFT      32
+#define SW_TWSI_EOP_TWSI_DATA  (SW_TWSI_OP_EOP | 1ULL << SW_TWSI_EOP_SHIFT)
+#define SW_TWSI_EOP_TWSI_CTL   (SW_TWSI_OP_EOP | 2ULL << SW_TWSI_EOP_SHIFT)
+#define SW_TWSI_EOP_TWSI_CLKCTL        (SW_TWSI_OP_EOP | 3ULL << SW_TWSI_EOP_SHIFT)
+#define SW_TWSI_EOP_TWSI_STAT  (SW_TWSI_OP_EOP | 3ULL << SW_TWSI_EOP_SHIFT)
+#define SW_TWSI_EOP_TWSI_RST   (SW_TWSI_OP_EOP | 7ULL << SW_TWSI_EOP_SHIFT)
+
+/* Controller command and status bits */
+#define TWSI_CTL_CE            0x80    /* High level controller enable */
+#define TWSI_CTL_ENAB          0x40    /* Bus enable */
+#define TWSI_CTL_STA           0x20    /* Master-mode start, HW clears when done */
+#define TWSI_CTL_STP           0x10    /* Master-mode stop, HW clears when done */
+#define TWSI_CTL_IFLG          0x08    /* HW event, SW writes 0 to ACK */
+#define TWSI_CTL_AAK           0x04    /* Assert ACK */
+
+/* Status values */
+#define STAT_ERROR             0x00
+#define STAT_START             0x08
+#define STAT_REP_START         0x10
+#define STAT_TXADDR_ACK                0x18
+#define STAT_TXADDR_NAK                0x20
+#define STAT_TXDATA_ACK                0x28
+#define STAT_TXDATA_NAK                0x30
+#define STAT_LOST_ARB_38       0x38
+#define STAT_RXADDR_ACK                0x40
+#define STAT_RXADDR_NAK                0x48
+#define STAT_RXDATA_ACK                0x50
+#define STAT_RXDATA_NAK                0x58
+#define STAT_SLAVE_60          0x60
+#define STAT_LOST_ARB_68       0x68
+#define STAT_SLAVE_70          0x70
+#define STAT_LOST_ARB_78       0x78
+#define STAT_SLAVE_80          0x80
+#define STAT_SLAVE_88          0x88
+#define STAT_GENDATA_ACK       0x90
+#define STAT_GENDATA_NAK       0x98
+#define STAT_SLAVE_A0          0xA0
+#define STAT_SLAVE_A8          0xA8
+#define STAT_LOST_ARB_B0       0xB0
+#define STAT_SLAVE_LOST                0xB8
+#define STAT_SLAVE_NAK         0xC0
+#define STAT_SLAVE_ACK         0xC8
+#define STAT_AD2W_ACK          0xD0
+#define STAT_AD2W_NAK          0xD8
+#define STAT_IDLE              0xF8
+
+/* TWSI_INT values */
+#define TWSI_INT_ST_INT                BIT_ULL(0)
+#define TWSI_INT_TS_INT                BIT_ULL(1)
+#define TWSI_INT_CORE_INT      BIT_ULL(2)
+#define TWSI_INT_ST_EN         BIT_ULL(4)
+#define TWSI_INT_TS_EN         BIT_ULL(5)
+#define TWSI_INT_CORE_EN       BIT_ULL(6)
+#define TWSI_INT_SDA_OVR       BIT_ULL(8)
+#define TWSI_INT_SCL_OVR       BIT_ULL(9)
+#define TWSI_INT_SDA           BIT_ULL(10)
+#define TWSI_INT_SCL           BIT_ULL(11)
+
+#define I2C_OCTEON_EVENT_WAIT 80 /* microseconds */
+
+/* Register offsets */
+struct octeon_i2c_reg_offset {
+       unsigned int sw_twsi;
+       unsigned int twsi_int;
+       unsigned int sw_twsi_ext;
+};
+
+#define SW_TWSI(x)     (x->roff.sw_twsi)
+#define TWSI_INT(x)    (x->roff.twsi_int)
+#define SW_TWSI_EXT(x) (x->roff.sw_twsi_ext)
+
+struct octeon_i2c {
+       wait_queue_head_t queue;
+       struct i2c_adapter adap;
+       struct octeon_i2c_reg_offset roff;
+       struct clk *clk;
+       int irq;
+       int hlc_irq;            /* For cn7890 only */
+       u32 twsi_freq;
+       int sys_freq;
+       void __iomem *twsi_base;
+       struct device *dev;
+       bool hlc_enabled;
+       bool broken_irq_mode;
+       bool broken_irq_check;
+       void (*int_enable)(struct octeon_i2c *);
+       void (*int_disable)(struct octeon_i2c *);
+       void (*hlc_int_enable)(struct octeon_i2c *);
+       void (*hlc_int_disable)(struct octeon_i2c *);
+       atomic_t int_enable_cnt;
+       atomic_t hlc_int_enable_cnt;
+#if IS_ENABLED(CONFIG_I2C_THUNDERX)
+       struct msix_entry i2c_msix;
+#endif
+       struct i2c_smbus_alert_setup alert_data;
+       struct i2c_client *ara;
+};
+
+static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr)
+{
+       __raw_writeq(val, addr);
+       __raw_readq(addr);      /* wait for write to land */
+}
+
+/**
+ * octeon_i2c_reg_write - write an I2C core register
+ * @i2c: The struct octeon_i2c
+ * @eop_reg: Register selector
+ * @data: Value to be written
+ *
+ * The I2C core registers are accessed indirectly via the SW_TWSI CSR.
+ */
+static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data)
+{
+       u64 tmp;
+
+       __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI(i2c));
+       do {
+               tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+       } while ((tmp & SW_TWSI_V) != 0);
+}
+
+#define octeon_i2c_ctl_write(i2c, val)                                 \
+       octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, val)
+#define octeon_i2c_data_write(i2c, val)                                        \
+       octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, val)
+
+/**
+ * octeon_i2c_reg_read - read lower bits of an I2C core register
+ * @i2c: The struct octeon_i2c
+ * @eop_reg: Register selector
+ *
+ * Returns the data.
+ *
+ * The I2C core registers are accessed indirectly via the SW_TWSI CSR.
+ */
+static inline u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg)
+{
+       u64 tmp;
+
+       __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI(i2c));
+       do {
+               tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+       } while ((tmp & SW_TWSI_V) != 0);
+
+       return tmp & 0xFF;
+}
+
+#define octeon_i2c_ctl_read(i2c)                                       \
+       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL)
+#define octeon_i2c_data_read(i2c)                                      \
+       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA)
+#define octeon_i2c_stat_read(i2c)                                      \
+       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT)
+
+/**
+ * octeon_i2c_read_int - read the TWSI_INT register
+ * @i2c: The struct octeon_i2c
+ *
+ * Returns the value of the register.
+ */
+static inline u64 octeon_i2c_read_int(struct octeon_i2c *i2c)
+{
+       return __raw_readq(i2c->twsi_base + TWSI_INT(i2c));
+}
+
+/**
+ * octeon_i2c_write_int - write the TWSI_INT register
+ * @i2c: The struct octeon_i2c
+ * @data: Value to be written
+ */
+static inline void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)
+{
+       octeon_i2c_writeq_flush(data, i2c->twsi_base + TWSI_INT(i2c));
+}
+
+/* Prototypes */
+irqreturn_t octeon_i2c_isr(int irq, void *dev_id);
+int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
+int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c);
+void octeon_i2c_set_clock(struct octeon_i2c *i2c);
+extern struct i2c_bus_recovery_info octeon_i2c_recovery_info;
diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c
new file mode 100644 (file)
index 0000000..917524c
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * (C) Copyright 2009-2010
+ * Nokia Siemens Networks, michael.lawnick.ext@nsn.com
+ *
+ * Portions Copyright (C) 2010 - 2016 Cavium, Inc.
+ *
+ * This is a driver for the i2c adapter in Cavium Networks' OCTEON processors.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/atomic.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <asm/octeon/octeon.h>
+#include "i2c-octeon-core.h"
+
+#define DRV_NAME "i2c-octeon"
+
+/**
+ * octeon_i2c_int_enable - enable the CORE interrupt
+ * @i2c: The struct octeon_i2c
+ *
+ * The interrupt will be asserted when there is non-STAT_IDLE state in
+ * the SW_TWSI_EOP_TWSI_STAT register.
+ */
+static void octeon_i2c_int_enable(struct octeon_i2c *i2c)
+{
+       octeon_i2c_write_int(i2c, TWSI_INT_CORE_EN);
+}
+
+/* disable the CORE interrupt */
+static void octeon_i2c_int_disable(struct octeon_i2c *i2c)
+{
+       /* clear TS/ST/IFLG events */
+       octeon_i2c_write_int(i2c, 0);
+}
+
+/**
+ * octeon_i2c_int_enable78 - enable the CORE interrupt
+ * @i2c: The struct octeon_i2c
+ *
+ * The interrupt will be asserted when there is non-STAT_IDLE state in the
+ * SW_TWSI_EOP_TWSI_STAT register.
+ */
+static void octeon_i2c_int_enable78(struct octeon_i2c *i2c)
+{
+       atomic_inc_return(&i2c->int_enable_cnt);
+       enable_irq(i2c->irq);
+}
+
+static void __octeon_i2c_irq_disable(atomic_t *cnt, int irq)
+{
+       int count;
+
+       /*
+        * The interrupt can be disabled in two places, but we only
+        * want to make the disable_irq_nosync() call once, so keep
+        * track with the atomic variable.
+        */
+       count = atomic_dec_if_positive(cnt);
+       if (count >= 0)
+               disable_irq_nosync(irq);
+}
+
+/* disable the CORE interrupt */
+static void octeon_i2c_int_disable78(struct octeon_i2c *i2c)
+{
+       __octeon_i2c_irq_disable(&i2c->int_enable_cnt, i2c->irq);
+}
+
+/**
+ * octeon_i2c_hlc_int_enable78 - enable the ST interrupt
+ * @i2c: The struct octeon_i2c
+ *
+ * The interrupt will be asserted when there is non-STAT_IDLE state in
+ * the SW_TWSI_EOP_TWSI_STAT register.
+ */
+static void octeon_i2c_hlc_int_enable78(struct octeon_i2c *i2c)
+{
+       atomic_inc_return(&i2c->hlc_int_enable_cnt);
+       enable_irq(i2c->hlc_irq);
+}
+
+/* disable the ST interrupt */
+static void octeon_i2c_hlc_int_disable78(struct octeon_i2c *i2c)
+{
+       __octeon_i2c_irq_disable(&i2c->hlc_int_enable_cnt, i2c->hlc_irq);
+}
+
+/* HLC interrupt service routine */
+static irqreturn_t octeon_i2c_hlc_isr78(int irq, void *dev_id)
+{
+       struct octeon_i2c *i2c = dev_id;
+
+       i2c->hlc_int_disable(i2c);
+       wake_up(&i2c->queue);
+
+       return IRQ_HANDLED;
+}
+
+static void octeon_i2c_hlc_int_enable(struct octeon_i2c *i2c)
+{
+       octeon_i2c_write_int(i2c, TWSI_INT_ST_EN);
+}
+
+static u32 octeon_i2c_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
+              I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_SMBUS_BLOCK_PROC_CALL;
+}
+
+static const struct i2c_algorithm octeon_i2c_algo = {
+       .master_xfer = octeon_i2c_xfer,
+       .functionality = octeon_i2c_functionality,
+};
+
+static struct i2c_adapter octeon_i2c_ops = {
+       .owner = THIS_MODULE,
+       .name = "OCTEON adapter",
+       .algo = &octeon_i2c_algo,
+};
+
+static int octeon_i2c_probe(struct platform_device *pdev)
+{
+       struct device_node *node = pdev->dev.of_node;
+       int irq, result = 0, hlc_irq = 0;
+       struct resource *res_mem;
+       struct octeon_i2c *i2c;
+       bool cn78xx_style;
+
+       cn78xx_style = of_device_is_compatible(node, "cavium,octeon-7890-twsi");
+       if (cn78xx_style) {
+               hlc_irq = platform_get_irq(pdev, 0);
+               if (hlc_irq < 0)
+                       return hlc_irq;
+
+               irq = platform_get_irq(pdev, 2);
+               if (irq < 0)
+                       return irq;
+       } else {
+               /* All adaptors have an irq.  */
+               irq = platform_get_irq(pdev, 0);
+               if (irq < 0)
+                       return irq;
+       }
+
+       i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
+       if (!i2c) {
+               result = -ENOMEM;
+               goto out;
+       }
+       i2c->dev = &pdev->dev;
+
+       i2c->roff.sw_twsi = 0x00;
+       i2c->roff.twsi_int = 0x10;
+       i2c->roff.sw_twsi_ext = 0x18;
+
+       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       i2c->twsi_base = devm_ioremap_resource(&pdev->dev, res_mem);
+       if (IS_ERR(i2c->twsi_base)) {
+               result = PTR_ERR(i2c->twsi_base);
+               goto out;
+       }
+
+       /*
+        * "clock-rate" is a legacy binding, the official binding is
+        * "clock-frequency".  Try the official one first and then
+        * fall back if it doesn't exist.
+        */
+       if (of_property_read_u32(node, "clock-frequency", &i2c->twsi_freq) &&
+           of_property_read_u32(node, "clock-rate", &i2c->twsi_freq)) {
+               dev_err(i2c->dev,
+                       "no I2C 'clock-rate' or 'clock-frequency' property\n");
+               result = -ENXIO;
+               goto out;
+       }
+
+       i2c->sys_freq = octeon_get_io_clock_rate();
+
+       init_waitqueue_head(&i2c->queue);
+
+       i2c->irq = irq;
+
+       if (cn78xx_style) {
+               i2c->hlc_irq = hlc_irq;
+
+               i2c->int_enable = octeon_i2c_int_enable78;
+               i2c->int_disable = octeon_i2c_int_disable78;
+               i2c->hlc_int_enable = octeon_i2c_hlc_int_enable78;
+               i2c->hlc_int_disable = octeon_i2c_hlc_int_disable78;
+
+               irq_set_status_flags(i2c->irq, IRQ_NOAUTOEN);
+               irq_set_status_flags(i2c->hlc_irq, IRQ_NOAUTOEN);
+
+               result = devm_request_irq(&pdev->dev, i2c->hlc_irq,
+                                         octeon_i2c_hlc_isr78, 0,
+                                         DRV_NAME, i2c);
+               if (result < 0) {
+                       dev_err(i2c->dev, "failed to attach interrupt\n");
+                       goto out;
+               }
+       } else {
+               i2c->int_enable = octeon_i2c_int_enable;
+               i2c->int_disable = octeon_i2c_int_disable;
+               i2c->hlc_int_enable = octeon_i2c_hlc_int_enable;
+               i2c->hlc_int_disable = octeon_i2c_int_disable;
+       }
+
+       result = devm_request_irq(&pdev->dev, i2c->irq,
+                                 octeon_i2c_isr, 0, DRV_NAME, i2c);
+       if (result < 0) {
+               dev_err(i2c->dev, "failed to attach interrupt\n");
+               goto out;
+       }
+
+       if (OCTEON_IS_MODEL(OCTEON_CN38XX))
+               i2c->broken_irq_check = true;
+
+       result = octeon_i2c_init_lowlevel(i2c);
+       if (result) {
+               dev_err(i2c->dev, "init low level failed\n");
+               goto  out;
+       }
+
+       octeon_i2c_set_clock(i2c);
+
+       i2c->adap = octeon_i2c_ops;
+       i2c->adap.timeout = msecs_to_jiffies(2);
+       i2c->adap.retries = 5;
+       i2c->adap.bus_recovery_info = &octeon_i2c_recovery_info;
+       i2c->adap.dev.parent = &pdev->dev;
+       i2c->adap.dev.of_node = node;
+       i2c_set_adapdata(&i2c->adap, i2c);
+       platform_set_drvdata(pdev, i2c);
+
+       result = i2c_add_adapter(&i2c->adap);
+       if (result < 0)
+               goto out;
+       dev_info(i2c->dev, "probed\n");
+       return 0;
+
+out:
+       return result;
+};
+
+static int octeon_i2c_remove(struct platform_device *pdev)
+{
+       struct octeon_i2c *i2c = platform_get_drvdata(pdev);
+
+       i2c_del_adapter(&i2c->adap);
+       return 0;
+};
+
+static const struct of_device_id octeon_i2c_match[] = {
+       { .compatible = "cavium,octeon-3860-twsi", },
+       { .compatible = "cavium,octeon-7890-twsi", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, octeon_i2c_match);
+
+static struct platform_driver octeon_i2c_driver = {
+       .probe          = octeon_i2c_probe,
+       .remove         = octeon_i2c_remove,
+       .driver         = {
+               .name   = DRV_NAME,
+               .of_match_table = octeon_i2c_match,
+       },
+};
+
+module_platform_driver(octeon_i2c_driver);
+
+MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>");
+MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
deleted file mode 100644 (file)
index 30ae351..0000000
+++ /dev/null
@@ -1,1255 +0,0 @@
-/*
- * (C) Copyright 2009-2010
- * Nokia Siemens Networks, michael.lawnick.ext@nsn.com
- *
- * Portions Copyright (C) 2010 - 2016 Cavium, Inc.
- *
- * This is a driver for the i2c adapter in Cavium Networks' OCTEON processors.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/atomic.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/io.h>
-#include <linux/of.h>
-
-#include <asm/octeon/octeon.h>
-
-#define DRV_NAME "i2c-octeon"
-
-/* Register offsets */
-#define SW_TWSI                        0x00
-#define TWSI_INT               0x10
-#define SW_TWSI_EXT            0x18
-
-/* Controller command patterns */
-#define SW_TWSI_V              BIT_ULL(63)     /* Valid bit */
-#define SW_TWSI_EIA            BIT_ULL(61)     /* Extended internal address */
-#define SW_TWSI_R              BIT_ULL(56)     /* Result or read bit */
-#define SW_TWSI_SOVR           BIT_ULL(55)     /* Size override */
-#define SW_TWSI_SIZE_SHIFT     52
-#define SW_TWSI_ADDR_SHIFT     40
-#define SW_TWSI_IA_SHIFT       32              /* Internal address */
-
-/* Controller opcode word (bits 60:57) */
-#define SW_TWSI_OP_SHIFT       57
-#define SW_TWSI_OP_7           (0ULL << SW_TWSI_OP_SHIFT)
-#define SW_TWSI_OP_7_IA                (1ULL << SW_TWSI_OP_SHIFT)
-#define SW_TWSI_OP_10          (2ULL << SW_TWSI_OP_SHIFT)
-#define SW_TWSI_OP_10_IA       (3ULL << SW_TWSI_OP_SHIFT)
-#define SW_TWSI_OP_TWSI_CLK    (4ULL << SW_TWSI_OP_SHIFT)
-#define SW_TWSI_OP_EOP         (6ULL << SW_TWSI_OP_SHIFT) /* Extended opcode */
-
-/* Controller extended opcode word (bits 34:32) */
-#define SW_TWSI_EOP_SHIFT      32
-#define SW_TWSI_EOP_TWSI_DATA  (SW_TWSI_OP_EOP | 1ULL << SW_TWSI_EOP_SHIFT)
-#define SW_TWSI_EOP_TWSI_CTL   (SW_TWSI_OP_EOP | 2ULL << SW_TWSI_EOP_SHIFT)
-#define SW_TWSI_EOP_TWSI_CLKCTL        (SW_TWSI_OP_EOP | 3ULL << SW_TWSI_EOP_SHIFT)
-#define SW_TWSI_EOP_TWSI_STAT  (SW_TWSI_OP_EOP | 3ULL << SW_TWSI_EOP_SHIFT)
-#define SW_TWSI_EOP_TWSI_RST   (SW_TWSI_OP_EOP | 7ULL << SW_TWSI_EOP_SHIFT)
-
-/* Controller command and status bits */
-#define TWSI_CTL_CE            0x80    /* High level controller enable */
-#define TWSI_CTL_ENAB          0x40    /* Bus enable */
-#define TWSI_CTL_STA           0x20    /* Master-mode start, HW clears when done */
-#define TWSI_CTL_STP           0x10    /* Master-mode stop, HW clears when done */
-#define TWSI_CTL_IFLG          0x08    /* HW event, SW writes 0 to ACK */
-#define TWSI_CTL_AAK           0x04    /* Assert ACK */
-
-/* Status values */
-#define STAT_ERROR             0x00
-#define STAT_START             0x08
-#define STAT_REP_START         0x10
-#define STAT_TXADDR_ACK                0x18
-#define STAT_TXADDR_NAK                0x20
-#define STAT_TXDATA_ACK                0x28
-#define STAT_TXDATA_NAK                0x30
-#define STAT_LOST_ARB_38       0x38
-#define STAT_RXADDR_ACK                0x40
-#define STAT_RXADDR_NAK                0x48
-#define STAT_RXDATA_ACK                0x50
-#define STAT_RXDATA_NAK                0x58
-#define STAT_SLAVE_60          0x60
-#define STAT_LOST_ARB_68       0x68
-#define STAT_SLAVE_70          0x70
-#define STAT_LOST_ARB_78       0x78
-#define STAT_SLAVE_80          0x80
-#define STAT_SLAVE_88          0x88
-#define STAT_GENDATA_ACK       0x90
-#define STAT_GENDATA_NAK       0x98
-#define STAT_SLAVE_A0          0xA0
-#define STAT_SLAVE_A8          0xA8
-#define STAT_LOST_ARB_B0       0xB0
-#define STAT_SLAVE_LOST                0xB8
-#define STAT_SLAVE_NAK         0xC0
-#define STAT_SLAVE_ACK         0xC8
-#define STAT_AD2W_ACK          0xD0
-#define STAT_AD2W_NAK          0xD8
-#define STAT_IDLE              0xF8
-
-/* TWSI_INT values */
-#define TWSI_INT_ST_INT                BIT_ULL(0)
-#define TWSI_INT_TS_INT                BIT_ULL(1)
-#define TWSI_INT_CORE_INT      BIT_ULL(2)
-#define TWSI_INT_ST_EN         BIT_ULL(4)
-#define TWSI_INT_TS_EN         BIT_ULL(5)
-#define TWSI_INT_CORE_EN       BIT_ULL(6)
-#define TWSI_INT_SDA_OVR       BIT_ULL(8)
-#define TWSI_INT_SCL_OVR       BIT_ULL(9)
-#define TWSI_INT_SDA           BIT_ULL(10)
-#define TWSI_INT_SCL           BIT_ULL(11)
-
-#define I2C_OCTEON_EVENT_WAIT 80 /* microseconds */
-
-struct octeon_i2c {
-       wait_queue_head_t queue;
-       struct i2c_adapter adap;
-       int irq;
-       int hlc_irq;            /* For cn7890 only */
-       u32 twsi_freq;
-       int sys_freq;
-       void __iomem *twsi_base;
-       struct device *dev;
-       bool hlc_enabled;
-       bool broken_irq_mode;
-       bool broken_irq_check;
-       void (*int_enable)(struct octeon_i2c *);
-       void (*int_disable)(struct octeon_i2c *);
-       void (*hlc_int_enable)(struct octeon_i2c *);
-       void (*hlc_int_disable)(struct octeon_i2c *);
-       atomic_t int_enable_cnt;
-       atomic_t hlc_int_enable_cnt;
-};
-
-static void octeon_i2c_writeq_flush(u64 val, void __iomem *addr)
-{
-       __raw_writeq(val, addr);
-       __raw_readq(addr);      /* wait for write to land */
-}
-
-/**
- * octeon_i2c_reg_write - write an I2C core register
- * @i2c: The struct octeon_i2c
- * @eop_reg: Register selector
- * @data: Value to be written
- *
- * The I2C core registers are accessed indirectly via the SW_TWSI CSR.
- */
-static void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data)
-{
-       u64 tmp;
-
-       __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI);
-       do {
-               tmp = __raw_readq(i2c->twsi_base + SW_TWSI);
-       } while ((tmp & SW_TWSI_V) != 0);
-}
-
-#define octeon_i2c_ctl_write(i2c, val)                                 \
-       octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, val)
-#define octeon_i2c_data_write(i2c, val)                                        \
-       octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, val)
-
-/**
- * octeon_i2c_reg_read - read lower bits of an I2C core register
- * @i2c: The struct octeon_i2c
- * @eop_reg: Register selector
- *
- * Returns the data.
- *
- * The I2C core registers are accessed indirectly via the SW_TWSI CSR.
- */
-static u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg)
-{
-       u64 tmp;
-
-       __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI);
-       do {
-               tmp = __raw_readq(i2c->twsi_base + SW_TWSI);
-       } while ((tmp & SW_TWSI_V) != 0);
-
-       return tmp & 0xFF;
-}
-
-#define octeon_i2c_ctl_read(i2c)                                       \
-       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL)
-#define octeon_i2c_data_read(i2c)                                      \
-       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA)
-#define octeon_i2c_stat_read(i2c)                                      \
-       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT)
-
-/**
- * octeon_i2c_read_int - read the TWSI_INT register
- * @i2c: The struct octeon_i2c
- *
- * Returns the value of the register.
- */
-static u64 octeon_i2c_read_int(struct octeon_i2c *i2c)
-{
-       return __raw_readq(i2c->twsi_base + TWSI_INT);
-}
-
-/**
- * octeon_i2c_write_int - write the TWSI_INT register
- * @i2c: The struct octeon_i2c
- * @data: Value to be written
- */
-static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)
-{
-       octeon_i2c_writeq_flush(data, i2c->twsi_base + TWSI_INT);
-}
-
-/**
- * octeon_i2c_int_enable - enable the CORE interrupt
- * @i2c: The struct octeon_i2c
- *
- * The interrupt will be asserted when there is non-STAT_IDLE state in
- * the SW_TWSI_EOP_TWSI_STAT register.
- */
-static void octeon_i2c_int_enable(struct octeon_i2c *i2c)
-{
-       octeon_i2c_write_int(i2c, TWSI_INT_CORE_EN);
-}
-
-/* disable the CORE interrupt */
-static void octeon_i2c_int_disable(struct octeon_i2c *i2c)
-{
-       /* clear TS/ST/IFLG events */
-       octeon_i2c_write_int(i2c, 0);
-}
-
-/**
- * octeon_i2c_int_enable78 - enable the CORE interrupt
- * @i2c: The struct octeon_i2c
- *
- * The interrupt will be asserted when there is non-STAT_IDLE state in the
- * SW_TWSI_EOP_TWSI_STAT register.
- */
-static void octeon_i2c_int_enable78(struct octeon_i2c *i2c)
-{
-       atomic_inc_return(&i2c->int_enable_cnt);
-       enable_irq(i2c->irq);
-}
-
-static void __octeon_i2c_irq_disable(atomic_t *cnt, int irq)
-{
-       int count;
-
-       /*
-        * The interrupt can be disabled in two places, but we only
-        * want to make the disable_irq_nosync() call once, so keep
-        * track with the atomic variable.
-        */
-       count = atomic_dec_if_positive(cnt);
-       if (count >= 0)
-               disable_irq_nosync(irq);
-}
-
-/* disable the CORE interrupt */
-static void octeon_i2c_int_disable78(struct octeon_i2c *i2c)
-{
-       __octeon_i2c_irq_disable(&i2c->int_enable_cnt, i2c->irq);
-}
-
-/**
- * octeon_i2c_hlc_int_enable78 - enable the ST interrupt
- * @i2c: The struct octeon_i2c
- *
- * The interrupt will be asserted when there is non-STAT_IDLE state in
- * the SW_TWSI_EOP_TWSI_STAT register.
- */
-static void octeon_i2c_hlc_int_enable78(struct octeon_i2c *i2c)
-{
-       atomic_inc_return(&i2c->hlc_int_enable_cnt);
-       enable_irq(i2c->hlc_irq);
-}
-
-/* disable the ST interrupt */
-static void octeon_i2c_hlc_int_disable78(struct octeon_i2c *i2c)
-{
-       __octeon_i2c_irq_disable(&i2c->hlc_int_enable_cnt, i2c->hlc_irq);
-}
-
-/*
- * Cleanup low-level state & enable high-level controller.
- */
-static void octeon_i2c_hlc_enable(struct octeon_i2c *i2c)
-{
-       int try = 0;
-       u64 val;
-
-       if (i2c->hlc_enabled)
-               return;
-       i2c->hlc_enabled = true;
-
-       while (1) {
-               val = octeon_i2c_ctl_read(i2c);
-               if (!(val & (TWSI_CTL_STA | TWSI_CTL_STP)))
-                       break;
-
-               /* clear IFLG event */
-               if (val & TWSI_CTL_IFLG)
-                       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
-
-               if (try++ > 100) {
-                       pr_err("%s: giving up\n", __func__);
-                       break;
-               }
-
-               /* spin until any start/stop has finished */
-               udelay(10);
-       }
-       octeon_i2c_ctl_write(i2c, TWSI_CTL_CE | TWSI_CTL_AAK | TWSI_CTL_ENAB);
-}
-
-static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c)
-{
-       if (!i2c->hlc_enabled)
-               return;
-
-       i2c->hlc_enabled = false;
-       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
-}
-
-/* interrupt service routine */
-static irqreturn_t octeon_i2c_isr(int irq, void *dev_id)
-{
-       struct octeon_i2c *i2c = dev_id;
-
-       i2c->int_disable(i2c);
-       wake_up(&i2c->queue);
-
-       return IRQ_HANDLED;
-}
-
-/* HLC interrupt service routine */
-static irqreturn_t octeon_i2c_hlc_isr78(int irq, void *dev_id)
-{
-       struct octeon_i2c *i2c = dev_id;
-
-       i2c->hlc_int_disable(i2c);
-       wake_up(&i2c->queue);
-
-       return IRQ_HANDLED;
-}
-
-static bool octeon_i2c_test_iflg(struct octeon_i2c *i2c)
-{
-       return (octeon_i2c_ctl_read(i2c) & TWSI_CTL_IFLG);
-}
-
-static bool octeon_i2c_test_ready(struct octeon_i2c *i2c, bool *first)
-{
-       if (octeon_i2c_test_iflg(i2c))
-               return true;
-
-       if (*first) {
-               *first = false;
-               return false;
-       }
-
-       /*
-        * IRQ has signaled an event but IFLG hasn't changed.
-        * Sleep and retry once.
-        */
-       usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT);
-       return octeon_i2c_test_iflg(i2c);
-}
-
-/**
- * octeon_i2c_wait - wait for the IFLG to be set
- * @i2c: The struct octeon_i2c
- *
- * Returns 0 on success, otherwise a negative errno.
- */
-static int octeon_i2c_wait(struct octeon_i2c *i2c)
-{
-       long time_left;
-       bool first = 1;
-
-       /*
-        * Some chip revisions don't assert the irq in the interrupt
-        * controller. So we must poll for the IFLG change.
-        */
-       if (i2c->broken_irq_mode) {
-               u64 end = get_jiffies_64() + i2c->adap.timeout;
-
-               while (!octeon_i2c_test_iflg(i2c) &&
-                      time_before64(get_jiffies_64(), end))
-                       usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT);
-
-               return octeon_i2c_test_iflg(i2c) ? 0 : -ETIMEDOUT;
-       }
-
-       i2c->int_enable(i2c);
-       time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_ready(i2c, &first),
-                                      i2c->adap.timeout);
-       i2c->int_disable(i2c);
-
-       if (i2c->broken_irq_check && !time_left &&
-           octeon_i2c_test_iflg(i2c)) {
-               dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n");
-               i2c->broken_irq_mode = true;
-               return 0;
-       }
-
-       if (!time_left)
-               return -ETIMEDOUT;
-
-       return 0;
-}
-
-static int octeon_i2c_check_status(struct octeon_i2c *i2c, int final_read)
-{
-       u8 stat = octeon_i2c_stat_read(i2c);
-
-       switch (stat) {
-       /* Everything is fine */
-       case STAT_IDLE:
-       case STAT_AD2W_ACK:
-       case STAT_RXADDR_ACK:
-       case STAT_TXADDR_ACK:
-       case STAT_TXDATA_ACK:
-               return 0;
-
-       /* ACK allowed on pre-terminal bytes only */
-       case STAT_RXDATA_ACK:
-               if (!final_read)
-                       return 0;
-               return -EIO;
-
-       /* NAK allowed on terminal byte only */
-       case STAT_RXDATA_NAK:
-               if (final_read)
-                       return 0;
-               return -EIO;
-
-       /* Arbitration lost */
-       case STAT_LOST_ARB_38:
-       case STAT_LOST_ARB_68:
-       case STAT_LOST_ARB_78:
-       case STAT_LOST_ARB_B0:
-               return -EAGAIN;
-
-       /* Being addressed as slave, should back off & listen */
-       case STAT_SLAVE_60:
-       case STAT_SLAVE_70:
-       case STAT_GENDATA_ACK:
-       case STAT_GENDATA_NAK:
-               return -EOPNOTSUPP;
-
-       /* Core busy as slave */
-       case STAT_SLAVE_80:
-       case STAT_SLAVE_88:
-       case STAT_SLAVE_A0:
-       case STAT_SLAVE_A8:
-       case STAT_SLAVE_LOST:
-       case STAT_SLAVE_NAK:
-       case STAT_SLAVE_ACK:
-               return -EOPNOTSUPP;
-
-       case STAT_TXDATA_NAK:
-               return -EIO;
-       case STAT_TXADDR_NAK:
-       case STAT_RXADDR_NAK:
-       case STAT_AD2W_NAK:
-               return -ENXIO;
-       default:
-               dev_err(i2c->dev, "unhandled state: %d\n", stat);
-               return -EIO;
-       }
-}
-
-static bool octeon_i2c_hlc_test_valid(struct octeon_i2c *i2c)
-{
-       return (__raw_readq(i2c->twsi_base + SW_TWSI) & SW_TWSI_V) == 0;
-}
-
-static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c, bool *first)
-{
-       /* check if valid bit is cleared */
-       if (octeon_i2c_hlc_test_valid(i2c))
-               return true;
-
-       if (*first) {
-               *first = false;
-               return false;
-       }
-
-       /*
-        * IRQ has signaled an event but valid bit isn't cleared.
-        * Sleep and retry once.
-        */
-       usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT);
-       return octeon_i2c_hlc_test_valid(i2c);
-}
-
-static void octeon_i2c_hlc_int_enable(struct octeon_i2c *i2c)
-{
-       octeon_i2c_write_int(i2c, TWSI_INT_ST_EN);
-}
-
-static void octeon_i2c_hlc_int_clear(struct octeon_i2c *i2c)
-{
-       /* clear ST/TS events, listen for neither */
-       octeon_i2c_write_int(i2c, TWSI_INT_ST_INT | TWSI_INT_TS_INT);
-}
-
-/**
- * octeon_i2c_hlc_wait - wait for an HLC operation to complete
- * @i2c: The struct octeon_i2c
- *
- * Returns 0 on success, otherwise -ETIMEDOUT.
- */
-static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
-{
-       bool first = 1;
-       int time_left;
-
-       /*
-        * Some cn38xx boards don't assert the irq in the interrupt
-        * controller. So we must poll for the valid bit change.
-        */
-       if (i2c->broken_irq_mode) {
-               u64 end = get_jiffies_64() + i2c->adap.timeout;
-
-               while (!octeon_i2c_hlc_test_valid(i2c) &&
-                      time_before64(get_jiffies_64(), end))
-                       usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT);
-
-               return octeon_i2c_hlc_test_valid(i2c) ? 0 : -ETIMEDOUT;
-       }
-
-       i2c->hlc_int_enable(i2c);
-       time_left = wait_event_timeout(i2c->queue,
-                                      octeon_i2c_hlc_test_ready(i2c, &first),
-                                      i2c->adap.timeout);
-       i2c->hlc_int_disable(i2c);
-       if (!time_left)
-               octeon_i2c_hlc_int_clear(i2c);
-
-       if (i2c->broken_irq_check && !time_left &&
-           octeon_i2c_hlc_test_valid(i2c)) {
-               dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n");
-               i2c->broken_irq_mode = true;
-               return 0;
-       }
-
-       if (!time_left)
-               return -ETIMEDOUT;
-       return 0;
-}
-
-/* high-level-controller pure read of up to 8 bytes */
-static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
-{
-       int i, j, ret = 0;
-       u64 cmd;
-
-       octeon_i2c_hlc_enable(i2c);
-       octeon_i2c_hlc_int_clear(i2c);
-
-       cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR;
-       /* SIZE */
-       cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT;
-       /* A */
-       cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
-
-       if (msgs[0].flags & I2C_M_TEN)
-               cmd |= SW_TWSI_OP_10;
-       else
-               cmd |= SW_TWSI_OP_7;
-
-       octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
-       ret = octeon_i2c_hlc_wait(i2c);
-       if (ret)
-               goto err;
-
-       cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
-       if ((cmd & SW_TWSI_R) == 0)
-               return -EAGAIN;
-
-       for (i = 0, j = msgs[0].len - 1; i  < msgs[0].len && i < 4; i++, j--)
-               msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff;
-
-       if (msgs[0].len > 4) {
-               cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT);
-               for (i = 0; i  < msgs[0].len - 4 && i < 4; i++, j--)
-                       msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff;
-       }
-
-err:
-       return ret;
-}
-
-/* high-level-controller pure write of up to 8 bytes */
-static int octeon_i2c_hlc_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
-{
-       int i, j, ret = 0;
-       u64 cmd;
-
-       octeon_i2c_hlc_enable(i2c);
-       octeon_i2c_hlc_int_clear(i2c);
-
-       cmd = SW_TWSI_V | SW_TWSI_SOVR;
-       /* SIZE */
-       cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT;
-       /* A */
-       cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
-
-       if (msgs[0].flags & I2C_M_TEN)
-               cmd |= SW_TWSI_OP_10;
-       else
-               cmd |= SW_TWSI_OP_7;
-
-       for (i = 0, j = msgs[0].len - 1; i  < msgs[0].len && i < 4; i++, j--)
-               cmd |= (u64)msgs[0].buf[j] << (8 * i);
-
-       if (msgs[0].len > 4) {
-               u64 ext = 0;
-
-               for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--)
-                       ext |= (u64)msgs[0].buf[j] << (8 * i);
-               octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT);
-       }
-
-       octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
-       ret = octeon_i2c_hlc_wait(i2c);
-       if (ret)
-               goto err;
-
-       cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
-       if ((cmd & SW_TWSI_R) == 0)
-               return -EAGAIN;
-
-       ret = octeon_i2c_check_status(i2c, false);
-
-err:
-       return ret;
-}
-
-/* high-level-controller composite write+read, msg0=addr, msg1=data */
-static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
-{
-       int i, j, ret = 0;
-       u64 cmd;
-
-       octeon_i2c_hlc_enable(i2c);
-
-       cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR;
-       /* SIZE */
-       cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT;
-       /* A */
-       cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
-
-       if (msgs[0].flags & I2C_M_TEN)
-               cmd |= SW_TWSI_OP_10_IA;
-       else
-               cmd |= SW_TWSI_OP_7_IA;
-
-       if (msgs[0].len == 2) {
-               u64 ext = 0;
-
-               cmd |= SW_TWSI_EIA;
-               ext = (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
-               cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT;
-               octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT);
-       } else {
-               cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
-       }
-
-       octeon_i2c_hlc_int_clear(i2c);
-       octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
-
-       ret = octeon_i2c_hlc_wait(i2c);
-       if (ret)
-               goto err;
-
-       cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
-       if ((cmd & SW_TWSI_R) == 0)
-               return -EAGAIN;
-
-       for (i = 0, j = msgs[1].len - 1; i  < msgs[1].len && i < 4; i++, j--)
-               msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff;
-
-       if (msgs[1].len > 4) {
-               cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT);
-               for (i = 0; i  < msgs[1].len - 4 && i < 4; i++, j--)
-                       msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff;
-       }
-
-err:
-       return ret;
-}
-
-/* high-level-controller composite write+write, m[0]len<=2, m[1]len<=8 */
-static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
-{
-       bool set_ext = false;
-       int i, j, ret = 0;
-       u64 cmd, ext = 0;
-
-       octeon_i2c_hlc_enable(i2c);
-
-       cmd = SW_TWSI_V | SW_TWSI_SOVR;
-       /* SIZE */
-       cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT;
-       /* A */
-       cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
-
-       if (msgs[0].flags & I2C_M_TEN)
-               cmd |= SW_TWSI_OP_10_IA;
-       else
-               cmd |= SW_TWSI_OP_7_IA;
-
-       if (msgs[0].len == 2) {
-               cmd |= SW_TWSI_EIA;
-               ext |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
-               set_ext = true;
-               cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT;
-       } else {
-               cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
-       }
-
-       for (i = 0, j = msgs[1].len - 1; i  < msgs[1].len && i < 4; i++, j--)
-               cmd |= (u64)msgs[1].buf[j] << (8 * i);
-
-       if (msgs[1].len > 4) {
-               for (i = 0; i < msgs[1].len - 4 && i < 4; i++, j--)
-                       ext |= (u64)msgs[1].buf[j] << (8 * i);
-               set_ext = true;
-       }
-       if (set_ext)
-               octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT);
-
-       octeon_i2c_hlc_int_clear(i2c);
-       octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
-
-       ret = octeon_i2c_hlc_wait(i2c);
-       if (ret)
-               goto err;
-
-       cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
-       if ((cmd & SW_TWSI_R) == 0)
-               return -EAGAIN;
-
-       ret = octeon_i2c_check_status(i2c, false);
-
-err:
-       return ret;
-}
-
-/* calculate and set clock divisors */
-static void octeon_i2c_set_clock(struct octeon_i2c *i2c)
-{
-       int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff;
-       int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000;
-
-       for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) {
-               /*
-                * An mdiv value of less than 2 seems to not work well
-                * with ds1337 RTCs, so we constrain it to larger values.
-                */
-               for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) {
-                       /*
-                        * For given ndiv and mdiv values check the
-                        * two closest thp values.
-                        */
-                       tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10;
-                       tclk *= (1 << ndiv_idx);
-                       thp_base = (i2c->sys_freq / (tclk * 2)) - 1;
-
-                       for (inc = 0; inc <= 1; inc++) {
-                               thp_idx = thp_base + inc;
-                               if (thp_idx < 5 || thp_idx > 0xff)
-                                       continue;
-
-                               foscl = i2c->sys_freq / (2 * (thp_idx + 1));
-                               foscl = foscl / (1 << ndiv_idx);
-                               foscl = foscl / (mdiv_idx + 1) / 10;
-                               diff = abs(foscl - i2c->twsi_freq);
-                               if (diff < delta_hz) {
-                                       delta_hz = diff;
-                                       thp = thp_idx;
-                                       mdiv = mdiv_idx;
-                                       ndiv = ndiv_idx;
-                               }
-                       }
-               }
-       }
-       octeon_i2c_reg_write(i2c, SW_TWSI_OP_TWSI_CLK, thp);
-       octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv);
-}
-
-static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c)
-{
-       u8 status = 0;
-       int tries;
-
-       /* reset controller */
-       octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_RST, 0);
-
-       for (tries = 10; tries && status != STAT_IDLE; tries--) {
-               udelay(1);
-               status = octeon_i2c_stat_read(i2c);
-               if (status == STAT_IDLE)
-                       break;
-       }
-
-       if (status != STAT_IDLE) {
-               dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n",
-                       __func__, status);
-               return -EIO;
-       }
-
-       /* toggle twice to force both teardowns */
-       octeon_i2c_hlc_enable(i2c);
-       octeon_i2c_hlc_disable(i2c);
-       return 0;
-}
-
-static int octeon_i2c_recovery(struct octeon_i2c *i2c)
-{
-       int ret;
-
-       ret = i2c_recover_bus(&i2c->adap);
-       if (ret)
-               /* recover failed, try hardware re-init */
-               ret = octeon_i2c_init_lowlevel(i2c);
-       return ret;
-}
-
-/**
- * octeon_i2c_start - send START to the bus
- * @i2c: The struct octeon_i2c
- *
- * Returns 0 on success, otherwise a negative errno.
- */
-static int octeon_i2c_start(struct octeon_i2c *i2c)
-{
-       int ret;
-       u8 stat;
-
-       octeon_i2c_hlc_disable(i2c);
-
-       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA);
-       ret = octeon_i2c_wait(i2c);
-       if (ret)
-               goto error;
-
-       stat = octeon_i2c_stat_read(i2c);
-       if (stat == STAT_START || stat == STAT_REP_START)
-               /* START successful, bail out */
-               return 0;
-
-error:
-       /* START failed, try to recover */
-       ret = octeon_i2c_recovery(i2c);
-       return (ret) ? ret : -EAGAIN;
-}
-
-/* send STOP to the bus */
-static void octeon_i2c_stop(struct octeon_i2c *i2c)
-{
-       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STP);
-}
-
-/**
- * octeon_i2c_write - send data to the bus via low-level controller
- * @i2c: The struct octeon_i2c
- * @target: Target address
- * @data: Pointer to the data to be sent
- * @length: Length of the data
- *
- * The address is sent over the bus, then the data.
- *
- * Returns 0 on success, otherwise a negative errno.
- */
-static int octeon_i2c_write(struct octeon_i2c *i2c, int target,
-                           const u8 *data, int length)
-{
-       int i, result;
-
-       octeon_i2c_data_write(i2c, target << 1);
-       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
-
-       result = octeon_i2c_wait(i2c);
-       if (result)
-               return result;
-
-       for (i = 0; i < length; i++) {
-               result = octeon_i2c_check_status(i2c, false);
-               if (result)
-                       return result;
-
-               octeon_i2c_data_write(i2c, data[i]);
-               octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
-
-               result = octeon_i2c_wait(i2c);
-               if (result)
-                       return result;
-       }
-
-       return 0;
-}
-
-/**
- * octeon_i2c_read - receive data from the bus via low-level controller
- * @i2c: The struct octeon_i2c
- * @target: Target address
- * @data: Pointer to the location to store the data
- * @rlength: Length of the data
- * @recv_len: flag for length byte
- *
- * The address is sent over the bus, then the data is read.
- *
- * Returns 0 on success, otherwise a negative errno.
- */
-static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
-                          u8 *data, u16 *rlength, bool recv_len)
-{
-       int i, result, length = *rlength;
-       bool final_read = false;
-
-       octeon_i2c_data_write(i2c, (target << 1) | 1);
-       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
-
-       result = octeon_i2c_wait(i2c);
-       if (result)
-               return result;
-
-       /* address OK ? */
-       result = octeon_i2c_check_status(i2c, false);
-       if (result)
-               return result;
-
-       for (i = 0; i < length; i++) {
-               /*
-                * For the last byte to receive TWSI_CTL_AAK must not be set.
-                *
-                * A special case is I2C_M_RECV_LEN where we don't know the
-                * additional length yet. If recv_len is set we assume we're
-                * not reading the final byte and therefore need to set
-                * TWSI_CTL_AAK.
-                */
-               if ((i + 1 == length) && !(recv_len && i == 0))
-                       final_read = true;
-
-               /* clear iflg to allow next event */
-               if (final_read)
-                       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
-               else
-                       octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_AAK);
-
-               result = octeon_i2c_wait(i2c);
-               if (result)
-                       return result;
-
-               data[i] = octeon_i2c_data_read(i2c);
-               if (recv_len && i == 0) {
-                       if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
-                               return -EPROTO;
-                       length += data[i];
-               }
-
-               result = octeon_i2c_check_status(i2c, final_read);
-               if (result)
-                       return result;
-       }
-       *rlength = length;
-       return 0;
-}
-
-/**
- * octeon_i2c_xfer - The driver's master_xfer function
- * @adap: Pointer to the i2c_adapter structure
- * @msgs: Pointer to the messages to be processed
- * @num: Length of the MSGS array
- *
- * Returns the number of messages processed, or a negative errno on failure.
- */
-static int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
-                          int num)
-{
-       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
-       int i, ret = 0;
-
-       if (num == 1) {
-               if (msgs[0].len > 0 && msgs[0].len <= 8) {
-                       if (msgs[0].flags & I2C_M_RD)
-                               ret = octeon_i2c_hlc_read(i2c, msgs);
-                       else
-                               ret = octeon_i2c_hlc_write(i2c, msgs);
-                       goto out;
-               }
-       } else if (num == 2) {
-               if ((msgs[0].flags & I2C_M_RD) == 0 &&
-                   (msgs[1].flags & I2C_M_RECV_LEN) == 0 &&
-                   msgs[0].len > 0 && msgs[0].len <= 2 &&
-                   msgs[1].len > 0 && msgs[1].len <= 8 &&
-                   msgs[0].addr == msgs[1].addr) {
-                       if (msgs[1].flags & I2C_M_RD)
-                               ret = octeon_i2c_hlc_comp_read(i2c, msgs);
-                       else
-                               ret = octeon_i2c_hlc_comp_write(i2c, msgs);
-                       goto out;
-               }
-       }
-
-       for (i = 0; ret == 0 && i < num; i++) {
-               struct i2c_msg *pmsg = &msgs[i];
-
-               /* zero-length messages are not supported */
-               if (!pmsg->len) {
-                       ret = -EOPNOTSUPP;
-                       break;
-               }
-
-               ret = octeon_i2c_start(i2c);
-               if (ret)
-                       return ret;
-
-               if (pmsg->flags & I2C_M_RD)
-                       ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf,
-                                             &pmsg->len, pmsg->flags & I2C_M_RECV_LEN);
-               else
-                       ret = octeon_i2c_write(i2c, pmsg->addr, pmsg->buf,
-                                              pmsg->len);
-       }
-       octeon_i2c_stop(i2c);
-out:
-       return (ret != 0) ? ret : num;
-}
-
-static int octeon_i2c_get_scl(struct i2c_adapter *adap)
-{
-       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
-       u64 state;
-
-       state = octeon_i2c_read_int(i2c);
-       return state & TWSI_INT_SCL;
-}
-
-static void octeon_i2c_set_scl(struct i2c_adapter *adap, int val)
-{
-       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
-
-       octeon_i2c_write_int(i2c, TWSI_INT_SCL_OVR);
-}
-
-static int octeon_i2c_get_sda(struct i2c_adapter *adap)
-{
-       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
-       u64 state;
-
-       state = octeon_i2c_read_int(i2c);
-       return state & TWSI_INT_SDA;
-}
-
-static void octeon_i2c_prepare_recovery(struct i2c_adapter *adap)
-{
-       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
-
-       /*
-        * The stop resets the state machine, does not _transmit_ STOP unless
-        * engine was active.
-        */
-       octeon_i2c_stop(i2c);
-
-       octeon_i2c_hlc_disable(i2c);
-       octeon_i2c_write_int(i2c, 0);
-}
-
-static void octeon_i2c_unprepare_recovery(struct i2c_adapter *adap)
-{
-       struct octeon_i2c *i2c = i2c_get_adapdata(adap);
-
-       octeon_i2c_write_int(i2c, 0);
-}
-
-static struct i2c_bus_recovery_info octeon_i2c_recovery_info = {
-       .recover_bus = i2c_generic_scl_recovery,
-       .get_scl = octeon_i2c_get_scl,
-       .set_scl = octeon_i2c_set_scl,
-       .get_sda = octeon_i2c_get_sda,
-       .prepare_recovery = octeon_i2c_prepare_recovery,
-       .unprepare_recovery = octeon_i2c_unprepare_recovery,
-};
-
-static u32 octeon_i2c_functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
-              I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_SMBUS_BLOCK_PROC_CALL;
-}
-
-static const struct i2c_algorithm octeon_i2c_algo = {
-       .master_xfer = octeon_i2c_xfer,
-       .functionality = octeon_i2c_functionality,
-};
-
-static struct i2c_adapter octeon_i2c_ops = {
-       .owner = THIS_MODULE,
-       .name = "OCTEON adapter",
-       .algo = &octeon_i2c_algo,
-};
-
-static int octeon_i2c_probe(struct platform_device *pdev)
-{
-       struct device_node *node = pdev->dev.of_node;
-       int irq, result = 0, hlc_irq = 0;
-       struct resource *res_mem;
-       struct octeon_i2c *i2c;
-       bool cn78xx_style;
-
-       cn78xx_style = of_device_is_compatible(node, "cavium,octeon-7890-twsi");
-       if (cn78xx_style) {
-               hlc_irq = platform_get_irq(pdev, 0);
-               if (hlc_irq < 0)
-                       return hlc_irq;
-
-               irq = platform_get_irq(pdev, 2);
-               if (irq < 0)
-                       return irq;
-       } else {
-               /* All adaptors have an irq.  */
-               irq = platform_get_irq(pdev, 0);
-               if (irq < 0)
-                       return irq;
-       }
-
-       i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
-       if (!i2c) {
-               result = -ENOMEM;
-               goto out;
-       }
-       i2c->dev = &pdev->dev;
-
-       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       i2c->twsi_base = devm_ioremap_resource(&pdev->dev, res_mem);
-       if (IS_ERR(i2c->twsi_base)) {
-               result = PTR_ERR(i2c->twsi_base);
-               goto out;
-       }
-
-       /*
-        * "clock-rate" is a legacy binding, the official binding is
-        * "clock-frequency".  Try the official one first and then
-        * fall back if it doesn't exist.
-        */
-       if (of_property_read_u32(node, "clock-frequency", &i2c->twsi_freq) &&
-           of_property_read_u32(node, "clock-rate", &i2c->twsi_freq)) {
-               dev_err(i2c->dev,
-                       "no I2C 'clock-rate' or 'clock-frequency' property\n");
-               result = -ENXIO;
-               goto out;
-       }
-
-       i2c->sys_freq = octeon_get_io_clock_rate();
-
-       init_waitqueue_head(&i2c->queue);
-
-       i2c->irq = irq;
-
-       if (cn78xx_style) {
-               i2c->hlc_irq = hlc_irq;
-
-               i2c->int_enable = octeon_i2c_int_enable78;
-               i2c->int_disable = octeon_i2c_int_disable78;
-               i2c->hlc_int_enable = octeon_i2c_hlc_int_enable78;
-               i2c->hlc_int_disable = octeon_i2c_hlc_int_disable78;
-
-               irq_set_status_flags(i2c->irq, IRQ_NOAUTOEN);
-               irq_set_status_flags(i2c->hlc_irq, IRQ_NOAUTOEN);
-
-               result = devm_request_irq(&pdev->dev, i2c->hlc_irq,
-                                         octeon_i2c_hlc_isr78, 0,
-                                         DRV_NAME, i2c);
-               if (result < 0) {
-                       dev_err(i2c->dev, "failed to attach interrupt\n");
-                       goto out;
-               }
-       } else {
-               i2c->int_enable = octeon_i2c_int_enable;
-               i2c->int_disable = octeon_i2c_int_disable;
-               i2c->hlc_int_enable = octeon_i2c_hlc_int_enable;
-               i2c->hlc_int_disable = octeon_i2c_int_disable;
-       }
-
-       result = devm_request_irq(&pdev->dev, i2c->irq,
-                                 octeon_i2c_isr, 0, DRV_NAME, i2c);
-       if (result < 0) {
-               dev_err(i2c->dev, "failed to attach interrupt\n");
-               goto out;
-       }
-
-       if (OCTEON_IS_MODEL(OCTEON_CN38XX))
-               i2c->broken_irq_check = true;
-
-       result = octeon_i2c_init_lowlevel(i2c);
-       if (result) {
-               dev_err(i2c->dev, "init low level failed\n");
-               goto  out;
-       }
-
-       octeon_i2c_set_clock(i2c);
-
-       i2c->adap = octeon_i2c_ops;
-       i2c->adap.timeout = msecs_to_jiffies(2);
-       i2c->adap.retries = 5;
-       i2c->adap.bus_recovery_info = &octeon_i2c_recovery_info;
-       i2c->adap.dev.parent = &pdev->dev;
-       i2c->adap.dev.of_node = node;
-       i2c_set_adapdata(&i2c->adap, i2c);
-       platform_set_drvdata(pdev, i2c);
-
-       result = i2c_add_adapter(&i2c->adap);
-       if (result < 0) {
-               dev_err(i2c->dev, "failed to add adapter\n");
-               goto out;
-       }
-       dev_info(i2c->dev, "probed\n");
-       return 0;
-
-out:
-       return result;
-};
-
-static int octeon_i2c_remove(struct platform_device *pdev)
-{
-       struct octeon_i2c *i2c = platform_get_drvdata(pdev);
-
-       i2c_del_adapter(&i2c->adap);
-       return 0;
-};
-
-static const struct of_device_id octeon_i2c_match[] = {
-       { .compatible = "cavium,octeon-3860-twsi", },
-       { .compatible = "cavium,octeon-7890-twsi", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, octeon_i2c_match);
-
-static struct platform_driver octeon_i2c_driver = {
-       .probe          = octeon_i2c_probe,
-       .remove         = octeon_i2c_remove,
-       .driver         = {
-               .name   = DRV_NAME,
-               .of_match_table = octeon_i2c_match,
-       },
-};
-
-module_platform_driver(octeon_i2c_driver);
-
-MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>");
-MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors");
-MODULE_LICENSE("GPL");
index ab1279b..c7da0c4 100644 (file)
@@ -1425,10 +1425,8 @@ omap_i2c_probe(struct platform_device *pdev)
        /* i2c device drivers may be active on return from add_adapter() */
        adap->nr = pdev->id;
        r = i2c_add_numbered_adapter(adap);
-       if (r) {
-               dev_err(omap->dev, "failure adding adapter\n");
+       if (r)
                goto err_unuse_clocks;
-       }
 
        dev_info(omap->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr,
                 major, minor, omap->speed);
index 23d1c16..c2268cd 100644 (file)
@@ -694,7 +694,6 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
 
        retval = i2c_add_adapter(adap);
        if (retval) {
-               dev_err(&dev->dev, "Couldn't register adapter!\n");
                kfree(adapdata);
                kfree(adap);
                release_region(smba, SMBIOSIZE);
index 2c40edb..217c787 100644 (file)
@@ -329,10 +329,8 @@ static int pmcmsptwi_probe(struct platform_device *pldev)
        i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data);
 
        rc = i2c_add_adapter(&pmcmsptwi_adapter);
-       if (rc) {
-               dev_err(&pldev->dev, "Unable to register I2C adapter\n");
+       if (rc)
                goto ret_unmap;
-       }
 
        return 0;
 
index 7ea67aa..fd5f9d2 100644 (file)
@@ -714,10 +714,8 @@ static int i2c_pnx_probe(struct platform_device *pdev)
 
        /* Register this adapter with the I2C subsystem */
        ret = i2c_add_numbered_adapter(&alg_data->adapter);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "I2C: Failed to add bus\n");
+       if (ret < 0)
                goto out_clock;
-       }
 
        dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
                alg_data->adapter.name, res->start, alg_data->irq);
index 82b6f02..0c8b157 100644 (file)
@@ -212,11 +212,8 @@ static int puv3_i2c_probe(struct platform_device *pdev)
 
        adapter->nr = pdev->id;
        rc = i2c_add_numbered_adapter(adapter);
-       if (rc) {
-               dev_err(&pdev->dev, "Adapter '%s' registration failed\n",
-                               adapter->name);
+       if (rc)
                goto fail_add_adapter;
-       }
 
        dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n");
        return 0;
index 0d35195..e28b825 100644 (file)
@@ -1292,10 +1292,8 @@ static int i2c_pxa_probe(struct platform_device *dev)
 #endif
 
        ret = i2c_add_numbered_adapter(&i2c->adap);
-       if (ret < 0) {
-               dev_err(&dev->dev, "failed to add bus: %d\n", ret);
+       if (ret < 0)
                goto ereqirq;
-       }
 
        platform_set_drvdata(dev, i2c);
 
index 52407f3..400e344 100644 (file)
@@ -875,10 +875,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, priv);
 
        ret = i2c_add_numbered_adapter(adap);
-       if (ret < 0) {
-               dev_err(dev, "reg adap failed: %d\n", ret);
+       if (ret < 0)
                goto out_pm_disable;
-       }
 
        dev_info(dev, "probed\n");
 
index d7e3af6..6263ea8 100644 (file)
@@ -383,10 +383,8 @@ static int riic_i2c_probe(struct platform_device *pdev)
 
 
        ret = i2c_add_adapter(adap);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to add adapter\n");
+       if (ret)
                return ret;
-       }
 
        platform_set_drvdata(pdev, riic);
 
index 2bc8b01..3b87afe 100644 (file)
@@ -1303,10 +1303,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
        rk3x_i2c_adapt_div(i2c, clk_rate);
 
        ret = i2c_add_adapter(&i2c->adap);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Could not register adapter\n");
+       if (ret < 0)
                goto err_clk_notifier;
-       }
 
        dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs);
 
index 38dc1ca..499af26 100644 (file)
@@ -1215,7 +1215,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 
        ret = i2c_add_numbered_adapter(&i2c->adap);
        if (ret < 0) {
-               dev_err(&pdev->dev, "failed to add bus to i2c core\n");
                pm_runtime_disable(&pdev->dev);
                s3c24xx_i2c_deregister_cpufreq(i2c);
                clk_unprepare(i2c->clk);
index 2496838..c2005c7 100644 (file)
@@ -510,10 +510,8 @@ static int sh7760_i2c_probe(struct platform_device *pdev)
        }
 
        ret = i2c_add_numbered_adapter(&id->adap);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
+       if (ret < 0)
                goto out4;
-       }
 
        platform_set_drvdata(pdev, id);
 
index 6fb3e26..50f276e 100644 (file)
@@ -981,7 +981,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
        ret = i2c_add_numbered_adapter(adap);
        if (ret < 0) {
                sh_mobile_i2c_release_dma(pd);
-               dev_err(&dev->dev, "cannot add numbered adapter\n");
                return ret;
        }
 
index 792a42b..95e81d0 100644 (file)
@@ -387,10 +387,8 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
                writel(regval, siic->base + SIRFSOC_I2C_SDA_DELAY);
 
        err = i2c_add_numbered_adapter(adap);
-       if (err < 0) {
-               dev_err(&pdev->dev, "Can't add new i2c adapter\n");
+       if (err < 0)
                goto out;
-       }
 
        clk_disable(clk);
 
index 944ec42..1371547 100644 (file)
@@ -874,10 +874,8 @@ static int st_i2c_probe(struct platform_device *pdev)
        init_completion(&i2c_dev->complete);
 
        ret = i2c_add_adapter(adap);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to add adapter\n");
+       if (ret)
                return ret;
-       }
 
        platform_set_drvdata(pdev, i2c_dev);
 
index 460c134..dc63236 100644 (file)
@@ -920,11 +920,8 @@ static int stu300_probe(struct platform_device *pdev)
 
        /* i2c device drivers may be active on return from add_adapter() */
        ret = i2c_add_numbered_adapter(adap);
-       if (ret) {
-               dev_err(&pdev->dev, "failure adding ST Micro DDC "
-                      "I2C adapter\n");
+       if (ret)
                return ret;
-       }
 
        platform_set_drvdata(pdev, dev);
        dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n",
index b126dba..d9979da 100644 (file)
@@ -932,10 +932,8 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        i2c_dev->adapter.dev.of_node = pdev->dev.of_node;
 
        ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to add I2C adapter\n");
+       if (ret)
                goto disable_div_clk;
-       }
 
        return 0;
 
diff --git a/drivers/i2c/busses/i2c-thunderx-pcidrv.c b/drivers/i2c/busses/i2c-thunderx-pcidrv.c
new file mode 100644 (file)
index 0000000..bba5b42
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Cavium ThunderX i2c driver.
+ *
+ * Copyright (C) 2015,2016 Cavium Inc.
+ * Authors: Fred Martin <fmartin@caviumnetworks.com>
+ *         Jan Glauber <jglauber@cavium.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/i2c-smbus.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/pci.h>
+
+#include "i2c-octeon-core.h"
+
+#define DRV_NAME "i2c-thunderx"
+
+#define PCI_DEVICE_ID_THUNDER_TWSI     0xa012
+
+#define SYS_FREQ_DEFAULT               700000000
+
+#define TWSI_INT_ENA_W1C               0x1028
+#define TWSI_INT_ENA_W1S               0x1030
+
+/*
+ * Enable the CORE interrupt.
+ * The interrupt will be asserted when there is non-STAT_IDLE state in the
+ * SW_TWSI_EOP_TWSI_STAT register.
+ */
+static void thunder_i2c_int_enable(struct octeon_i2c *i2c)
+{
+       octeon_i2c_writeq_flush(TWSI_INT_CORE_INT,
+                               i2c->twsi_base + TWSI_INT_ENA_W1S);
+}
+
+/*
+ * Disable the CORE interrupt.
+ */
+static void thunder_i2c_int_disable(struct octeon_i2c *i2c)
+{
+       octeon_i2c_writeq_flush(TWSI_INT_CORE_INT,
+                               i2c->twsi_base + TWSI_INT_ENA_W1C);
+}
+
+static void thunder_i2c_hlc_int_enable(struct octeon_i2c *i2c)
+{
+       octeon_i2c_writeq_flush(TWSI_INT_ST_INT | TWSI_INT_TS_INT,
+                               i2c->twsi_base + TWSI_INT_ENA_W1S);
+}
+
+static void thunder_i2c_hlc_int_disable(struct octeon_i2c *i2c)
+{
+       octeon_i2c_writeq_flush(TWSI_INT_ST_INT | TWSI_INT_TS_INT,
+                               i2c->twsi_base + TWSI_INT_ENA_W1C);
+}
+
+static u32 thunderx_i2c_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
+              I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_SMBUS_BLOCK_PROC_CALL;
+}
+
+static const struct i2c_algorithm thunderx_i2c_algo = {
+       .master_xfer = octeon_i2c_xfer,
+       .functionality = thunderx_i2c_functionality,
+};
+
+static struct i2c_adapter thunderx_i2c_ops = {
+       .owner  = THIS_MODULE,
+       .name   = "ThunderX adapter",
+       .algo   = &thunderx_i2c_algo,
+};
+
+static void thunder_i2c_clock_enable(struct device *dev, struct octeon_i2c *i2c)
+{
+       int ret;
+
+       i2c->clk = clk_get(dev, NULL);
+       if (IS_ERR(i2c->clk)) {
+               i2c->clk = NULL;
+               goto skip;
+       }
+
+       ret = clk_prepare_enable(i2c->clk);
+       if (ret)
+               goto skip;
+       i2c->sys_freq = clk_get_rate(i2c->clk);
+
+skip:
+       if (!i2c->sys_freq)
+               i2c->sys_freq = SYS_FREQ_DEFAULT;
+}
+
+static void thunder_i2c_clock_disable(struct device *dev, struct clk *clk)
+{
+       if (!clk)
+               return;
+       clk_disable_unprepare(clk);
+       clk_put(clk);
+}
+
+static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,
+                                     struct device_node *node)
+{
+       u32 type;
+
+       if (!node)
+               return -EINVAL;
+
+       i2c->alert_data.irq = irq_of_parse_and_map(node, 0);
+       if (!i2c->alert_data.irq)
+               return -EINVAL;
+
+       type = irqd_get_trigger_type(irq_get_irq_data(i2c->alert_data.irq));
+       i2c->alert_data.alert_edge_triggered =
+               (type & IRQ_TYPE_LEVEL_MASK) ? 1 : 0;
+
+       i2c->ara = i2c_setup_smbus_alert(&i2c->adap, &i2c->alert_data);
+       if (!i2c->ara)
+               return -ENODEV;
+       return 0;
+}
+
+static int thunder_i2c_smbus_setup(struct octeon_i2c *i2c,
+                                  struct device_node *node)
+{
+       /* TODO: ACPI support */
+       if (!acpi_disabled)
+               return -EOPNOTSUPP;
+
+       return thunder_i2c_smbus_setup_of(i2c, node);
+}
+
+static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c)
+{
+       if (i2c->ara)
+               i2c_unregister_device(i2c->ara);
+}
+
+static int thunder_i2c_probe_pci(struct pci_dev *pdev,
+                                const struct pci_device_id *ent)
+{
+       struct device *dev = &pdev->dev;
+       struct octeon_i2c *i2c;
+       int ret;
+
+       i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
+       if (!i2c)
+               return -ENOMEM;
+
+       i2c->roff.sw_twsi = 0x1000;
+       i2c->roff.twsi_int = 0x1010;
+       i2c->roff.sw_twsi_ext = 0x1018;
+
+       i2c->dev = dev;
+       pci_set_drvdata(pdev, i2c);
+       ret = pcim_enable_device(pdev);
+       if (ret)
+               return ret;
+
+       ret = pci_request_regions(pdev, DRV_NAME);
+       if (ret)
+               return ret;
+
+       i2c->twsi_base = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0));
+       if (!i2c->twsi_base)
+               return -EINVAL;
+
+       thunder_i2c_clock_enable(dev, i2c);
+       ret = device_property_read_u32(dev, "clock-frequency", &i2c->twsi_freq);
+       if (ret)
+               i2c->twsi_freq = 100000;
+
+       init_waitqueue_head(&i2c->queue);
+
+       i2c->int_enable = thunder_i2c_int_enable;
+       i2c->int_disable = thunder_i2c_int_disable;
+       i2c->hlc_int_enable = thunder_i2c_hlc_int_enable;
+       i2c->hlc_int_disable = thunder_i2c_hlc_int_disable;
+
+       ret = pci_enable_msix(pdev, &i2c->i2c_msix, 1);
+       if (ret)
+               goto error;
+
+       ret = devm_request_irq(dev, i2c->i2c_msix.vector, octeon_i2c_isr, 0,
+                              DRV_NAME, i2c);
+       if (ret)
+               goto error;
+
+       ret = octeon_i2c_init_lowlevel(i2c);
+       if (ret)
+               goto error;
+
+       octeon_i2c_set_clock(i2c);
+
+       i2c->adap = thunderx_i2c_ops;
+       i2c->adap.retries = 5;
+       i2c->adap.bus_recovery_info = &octeon_i2c_recovery_info;
+       i2c->adap.dev.parent = dev;
+       i2c->adap.dev.of_node = pdev->dev.of_node;
+       snprintf(i2c->adap.name, sizeof(i2c->adap.name),
+                "Cavium ThunderX i2c adapter at %s", dev_name(dev));
+       i2c_set_adapdata(&i2c->adap, i2c);
+
+       ret = i2c_add_adapter(&i2c->adap);
+       if (ret)
+               goto error;
+
+       dev_info(i2c->dev, "Probed. Set system clock to %u\n", i2c->sys_freq);
+
+       ret = thunder_i2c_smbus_setup(i2c, pdev->dev.of_node);
+       if (ret)
+               dev_info(dev, "SMBUS alert not active on this bus\n");
+
+       return 0;
+
+error:
+       thunder_i2c_clock_disable(dev, i2c->clk);
+       return ret;
+}
+
+static void thunder_i2c_remove_pci(struct pci_dev *pdev)
+{
+       struct octeon_i2c *i2c = pci_get_drvdata(pdev);
+
+       thunder_i2c_smbus_remove(i2c);
+       thunder_i2c_clock_disable(&pdev->dev, i2c->clk);
+       i2c_del_adapter(&i2c->adap);
+}
+
+static const struct pci_device_id thunder_i2c_pci_id_table[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_TWSI) },
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, thunder_i2c_pci_id_table);
+
+static struct pci_driver thunder_i2c_pci_driver = {
+       .name           = DRV_NAME,
+       .id_table       = thunder_i2c_pci_id_table,
+       .probe          = thunder_i2c_probe_pci,
+       .remove         = thunder_i2c_remove_pci,
+};
+
+module_pci_driver(thunder_i2c_pci_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Fred Martin <fmartin@caviumnetworks.com>");
+MODULE_DESCRIPTION("I2C-Bus adapter for Cavium ThunderX SOC");
index aeead0d..3560853 100644 (file)
@@ -550,11 +550,6 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
        }
 
        ret = i2c_add_adapter(&priv->adap);
-       if (ret) {
-               dev_err(dev, "failed to add I2C adapter\n");
-               goto err;
-       }
-
 err:
        if (ret)
                clk_disable_unprepare(priv->clk);
index 475a5eb..d6e612a 100644 (file)
@@ -407,11 +407,6 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
        }
 
        ret = i2c_add_adapter(&priv->adap);
-       if (ret) {
-               dev_err(dev, "failed to add I2C adapter\n");
-               goto err;
-       }
-
 err:
        if (ret)
                clk_disable_unprepare(priv->clk);
index e1e3a85..fbd0fd5 100644 (file)
@@ -432,10 +432,8 @@ static int wmt_i2c_probe(struct platform_device *pdev)
        }
 
        err = i2c_add_adapter(adap);
-       if (err) {
-               dev_err(&pdev->dev, "failed to add adapter\n");
+       if (err)
                return err;
-       }
 
        platform_set_drvdata(pdev, i2c_dev);
 
index 4233f56..263685c 100644 (file)
@@ -418,7 +418,6 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
        i2c_set_adapdata(adapter, ctx);
        rc = i2c_add_adapter(adapter);
        if (rc) {
-               dev_err(&pdev->dev, "Adapter registeration failed\n");
                mbox_free_channel(ctx->mbox_chan);
                return rc;
        }
index 74f54f2..66bce3b 100644 (file)
@@ -804,7 +804,6 @@ static int xiic_i2c_probe(struct platform_device *pdev)
        /* add i2c adapter to i2c tree */
        ret = i2c_add_adapter(&i2c->adap);
        if (ret) {
-               dev_err(&pdev->dev, "Failed to add adapter\n");
                xiic_deinit(i2c);
                goto err_clk_dis;
        }
index 55a7bef..2a972ed 100644 (file)
@@ -400,10 +400,8 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
        i2c_set_adapdata(&priv->adapter, priv);
 
        err = i2c_add_adapter(&priv->adapter);
-       if (err) {
-               dev_err(&pdev->dev, "failed to add I2C adapter!\n");
+       if (err)
                return err;
-       }
 
        platform_set_drvdata(pdev, priv);
        dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr);
index 613c3a4..0968f59 100644 (file)
@@ -432,10 +432,8 @@ static int xlr_i2c_probe(struct platform_device *pdev)
 
        i2c_set_adapdata(&priv->adap, priv);
        ret = i2c_add_numbered_adapter(&priv->adap);
-       if (ret < 0) {
-               dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
+       if (ret < 0)
                return ret;
-       }
 
        platform_set_drvdata(pdev, priv);
        dev_info(&priv->adap.dev, "Added I2C Bus.\n");
index da3a02e..0579442 100644 (file)
@@ -88,7 +88,7 @@ void i2c_transfer_trace_unreg(void)
 }
 
 #if defined(CONFIG_ACPI)
-struct acpi_i2c_handler_data {
+struct i2c_acpi_handler_data {
        struct acpi_connection_info info;
        struct i2c_adapter *adapter;
 };
@@ -103,15 +103,18 @@ struct gsb_buffer {
        };
 } __packed;
 
-struct acpi_i2c_lookup {
+struct i2c_acpi_lookup {
        struct i2c_board_info *info;
        acpi_handle adapter_handle;
        acpi_handle device_handle;
+       acpi_handle search_handle;
+       u32 speed;
+       u32 min_speed;
 };
 
-static int acpi_i2c_fill_info(struct acpi_resource *ares, void *data)
+static int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)
 {
-       struct acpi_i2c_lookup *lookup = data;
+       struct i2c_acpi_lookup *lookup = data;
        struct i2c_board_info *info = lookup->info;
        struct acpi_resource_i2c_serialbus *sb;
        acpi_status status;
@@ -130,19 +133,18 @@ static int acpi_i2c_fill_info(struct acpi_resource *ares, void *data)
                return 1;
 
        info->addr = sb->slave_address;
+       lookup->speed = sb->connection_speed;
        if (sb->access_mode == ACPI_I2C_10BIT_MODE)
                info->flags |= I2C_CLIENT_TEN;
 
        return 1;
 }
 
-static int acpi_i2c_get_info(struct acpi_device *adev,
-                            struct i2c_board_info *info,
-                            acpi_handle *adapter_handle)
+static int i2c_acpi_do_lookup(struct acpi_device *adev,
+                             struct i2c_acpi_lookup *lookup)
 {
+       struct i2c_board_info *info = lookup->info;
        struct list_head resource_list;
-       struct resource_entry *entry;
-       struct acpi_i2c_lookup lookup;
        int ret;
 
        if (acpi_bus_get_status(adev) || !adev->status.present ||
@@ -150,24 +152,41 @@ static int acpi_i2c_get_info(struct acpi_device *adev,
                return -EINVAL;
 
        memset(info, 0, sizeof(*info));
-       info->fwnode = acpi_fwnode_handle(adev);
-
-       memset(&lookup, 0, sizeof(lookup));
-       lookup.device_handle = acpi_device_handle(adev);
-       lookup.info = info;
+       lookup->device_handle = acpi_device_handle(adev);
 
        /* Look up for I2cSerialBus resource */
        INIT_LIST_HEAD(&resource_list);
        ret = acpi_dev_get_resources(adev, &resource_list,
-                                    acpi_i2c_fill_info, &lookup);
+                                    i2c_acpi_fill_info, lookup);
        acpi_dev_free_resource_list(&resource_list);
 
        if (ret < 0 || !info->addr)
                return -EINVAL;
 
+       return 0;
+}
+
+static int i2c_acpi_get_info(struct acpi_device *adev,
+                            struct i2c_board_info *info,
+                            acpi_handle *adapter_handle)
+{
+       struct list_head resource_list;
+       struct resource_entry *entry;
+       struct i2c_acpi_lookup lookup;
+       int ret;
+
+       memset(&lookup, 0, sizeof(lookup));
+       lookup.info = info;
+
+       ret = i2c_acpi_do_lookup(adev, &lookup);
+       if (ret)
+               return ret;
+
+       info->fwnode = acpi_fwnode_handle(adev);
        *adapter_handle = lookup.adapter_handle;
 
        /* Then fill IRQ number if any */
+       INIT_LIST_HEAD(&resource_list);
        ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
        if (ret < 0)
                return -EINVAL;
@@ -186,7 +205,7 @@ static int acpi_i2c_get_info(struct acpi_device *adev,
        return 0;
 }
 
-static void acpi_i2c_register_device(struct i2c_adapter *adapter,
+static void i2c_acpi_register_device(struct i2c_adapter *adapter,
                                     struct acpi_device *adev,
                                     struct i2c_board_info *info)
 {
@@ -201,7 +220,7 @@ static void acpi_i2c_register_device(struct i2c_adapter *adapter,
        }
 }
 
-static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
+static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level,
                                       void *data, void **return_value)
 {
        struct i2c_adapter *adapter = data;
@@ -212,28 +231,28 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
        if (acpi_bus_get_device(handle, &adev))
                return AE_OK;
 
-       if (acpi_i2c_get_info(adev, &info, &adapter_handle))
+       if (i2c_acpi_get_info(adev, &info, &adapter_handle))
                return AE_OK;
 
        if (adapter_handle != ACPI_HANDLE(&adapter->dev))
                return AE_OK;
 
-       acpi_i2c_register_device(adapter, adev, &info);
+       i2c_acpi_register_device(adapter, adev, &info);
 
        return AE_OK;
 }
 
-#define ACPI_I2C_MAX_SCAN_DEPTH 32
+#define I2C_ACPI_MAX_SCAN_DEPTH 32
 
 /**
- * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
+ * i2c_acpi_register_devices - enumerate I2C slave devices behind adapter
  * @adap: pointer to adapter
  *
  * Enumerate all I2C slave devices behind this adapter by walking the ACPI
  * namespace. When a device is found it will be added to the Linux device
  * model and bound to the corresponding ACPI handle.
  */
-static void acpi_i2c_register_devices(struct i2c_adapter *adap)
+static void i2c_acpi_register_devices(struct i2c_adapter *adap)
 {
        acpi_status status;
 
@@ -241,14 +260,72 @@ static void acpi_i2c_register_devices(struct i2c_adapter *adap)
                return;
 
        status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-                                    ACPI_I2C_MAX_SCAN_DEPTH,
-                                    acpi_i2c_add_device, NULL,
+                                    I2C_ACPI_MAX_SCAN_DEPTH,
+                                    i2c_acpi_add_device, NULL,
                                     adap, NULL);
        if (ACPI_FAILURE(status))
                dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
 }
 
-static int acpi_i2c_match_adapter(struct device *dev, void *data)
+static acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level,
+                                          void *data, void **return_value)
+{
+       struct i2c_acpi_lookup *lookup = data;
+       struct acpi_device *adev;
+
+       if (acpi_bus_get_device(handle, &adev))
+               return AE_OK;
+
+       if (i2c_acpi_do_lookup(adev, lookup))
+               return AE_OK;
+
+       if (lookup->search_handle != lookup->adapter_handle)
+               return AE_OK;
+
+       if (lookup->speed <= lookup->min_speed)
+               lookup->min_speed = lookup->speed;
+
+       return AE_OK;
+}
+
+/**
+ * i2c_acpi_find_bus_speed - find I2C bus speed from ACPI
+ * @dev: The device owning the bus
+ *
+ * Find the I2C bus speed by walking the ACPI namespace for all I2C slaves
+ * devices connected to this bus and use the speed of slowest device.
+ *
+ * Returns the speed in Hz or zero
+ */
+u32 i2c_acpi_find_bus_speed(struct device *dev)
+{
+       struct i2c_acpi_lookup lookup;
+       struct i2c_board_info dummy;
+       acpi_status status;
+
+       if (!has_acpi_companion(dev))
+               return 0;
+
+       memset(&lookup, 0, sizeof(lookup));
+       lookup.search_handle = ACPI_HANDLE(dev);
+       lookup.min_speed = UINT_MAX;
+       lookup.info = &dummy;
+
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                                    I2C_ACPI_MAX_SCAN_DEPTH,
+                                    i2c_acpi_lookup_speed, NULL,
+                                    &lookup, NULL);
+
+       if (ACPI_FAILURE(status)) {
+               dev_warn(dev, "unable to find I2C bus speed from ACPI\n");
+               return 0;
+       }
+
+       return lookup.min_speed != UINT_MAX ? lookup.min_speed : 0;
+}
+EXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed);
+
+static int i2c_acpi_match_adapter(struct device *dev, void *data)
 {
        struct i2c_adapter *adapter = i2c_verify_adapter(dev);
 
@@ -258,29 +335,29 @@ static int acpi_i2c_match_adapter(struct device *dev, void *data)
        return ACPI_HANDLE(dev) == (acpi_handle)data;
 }
 
-static int acpi_i2c_match_device(struct device *dev, void *data)
+static int i2c_acpi_match_device(struct device *dev, void *data)
 {
        return ACPI_COMPANION(dev) == data;
 }
 
-static struct i2c_adapter *acpi_i2c_find_adapter_by_handle(acpi_handle handle)
+static struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle)
 {
        struct device *dev;
 
        dev = bus_find_device(&i2c_bus_type, NULL, handle,
-                             acpi_i2c_match_adapter);
+                             i2c_acpi_match_adapter);
        return dev ? i2c_verify_adapter(dev) : NULL;
 }
 
-static struct i2c_client *acpi_i2c_find_client_by_adev(struct acpi_device *adev)
+static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev)
 {
        struct device *dev;
 
-       dev = bus_find_device(&i2c_bus_type, NULL, adev, acpi_i2c_match_device);
+       dev = bus_find_device(&i2c_bus_type, NULL, adev, i2c_acpi_match_device);
        return dev ? i2c_verify_client(dev) : NULL;
 }
 
-static int acpi_i2c_notify(struct notifier_block *nb, unsigned long value,
+static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
                           void *arg)
 {
        struct acpi_device *adev = arg;
@@ -291,20 +368,20 @@ static int acpi_i2c_notify(struct notifier_block *nb, unsigned long value,
 
        switch (value) {
        case ACPI_RECONFIG_DEVICE_ADD:
-               if (acpi_i2c_get_info(adev, &info, &adapter_handle))
+               if (i2c_acpi_get_info(adev, &info, &adapter_handle))
                        break;
 
-               adapter = acpi_i2c_find_adapter_by_handle(adapter_handle);
+               adapter = i2c_acpi_find_adapter_by_handle(adapter_handle);
                if (!adapter)
                        break;
 
-               acpi_i2c_register_device(adapter, adev, &info);
+               i2c_acpi_register_device(adapter, adev, &info);
                break;
        case ACPI_RECONFIG_DEVICE_REMOVE:
                if (!acpi_device_enumerated(adev))
                        break;
 
-               client = acpi_i2c_find_client_by_adev(adev);
+               client = i2c_acpi_find_client_by_adev(adev);
                if (!client)
                        break;
 
@@ -317,10 +394,10 @@ static int acpi_i2c_notify(struct notifier_block *nb, unsigned long value,
 }
 
 static struct notifier_block i2c_acpi_notifier = {
-       .notifier_call = acpi_i2c_notify,
+       .notifier_call = i2c_acpi_notify,
 };
 #else /* CONFIG_ACPI */
-static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) { }
+static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
 extern struct notifier_block i2c_acpi_notifier;
 #endif /* CONFIG_ACPI */
 
@@ -386,12 +463,12 @@ static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
 }
 
 static acpi_status
-acpi_i2c_space_handler(u32 function, acpi_physical_address command,
+i2c_acpi_space_handler(u32 function, acpi_physical_address command,
                        u32 bits, u64 *value64,
                        void *handler_context, void *region_context)
 {
        struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
-       struct acpi_i2c_handler_data *data = handler_context;
+       struct i2c_acpi_handler_data *data = handler_context;
        struct acpi_connection_info *info = &data->info;
        struct acpi_resource_i2c_serialbus *sb;
        struct i2c_adapter *adapter = data->adapter;
@@ -510,10 +587,10 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command,
 }
 
 
-static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
+static int i2c_acpi_install_space_handler(struct i2c_adapter *adapter)
 {
        acpi_handle handle;
-       struct acpi_i2c_handler_data *data;
+       struct i2c_acpi_handler_data *data;
        acpi_status status;
 
        if (!adapter->dev.parent)
@@ -524,7 +601,7 @@ static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
        if (!handle)
                return -ENODEV;
 
-       data = kzalloc(sizeof(struct acpi_i2c_handler_data),
+       data = kzalloc(sizeof(struct i2c_acpi_handler_data),
                            GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -538,7 +615,7 @@ static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
 
        status = acpi_install_address_space_handler(handle,
                                ACPI_ADR_SPACE_GSBUS,
-                               &acpi_i2c_space_handler,
+                               &i2c_acpi_space_handler,
                                NULL,
                                data);
        if (ACPI_FAILURE(status)) {
@@ -552,10 +629,10 @@ static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
        return 0;
 }
 
-static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
+static void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter)
 {
        acpi_handle handle;
-       struct acpi_i2c_handler_data *data;
+       struct i2c_acpi_handler_data *data;
        acpi_status status;
 
        if (!adapter->dev.parent)
@@ -568,7 +645,7 @@ static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
 
        acpi_remove_address_space_handler(handle,
                                ACPI_ADR_SPACE_GSBUS,
-                               &acpi_i2c_space_handler);
+                               &i2c_acpi_space_handler);
 
        status = acpi_bus_get_private_data(handle, (void **)&data);
        if (ACPI_SUCCESS(status))
@@ -577,10 +654,10 @@ static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
        acpi_bus_detach_private_data(handle);
 }
 #else /* CONFIG_ACPI_I2C_OPREGION */
-static inline void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
+static inline void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter)
 { }
 
-static inline int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
+static inline int i2c_acpi_install_space_handler(struct i2c_adapter *adapter)
 { return 0; }
 #endif /* CONFIG_ACPI_I2C_OPREGION */
 
@@ -1752,8 +1829,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 
        /* create pre-declared device nodes */
        of_i2c_register_devices(adap);
-       acpi_i2c_register_devices(adap);
-       acpi_i2c_install_space_handler(adap);
+       i2c_acpi_register_devices(adap);
+       i2c_acpi_install_space_handler(adap);
 
        if (adap->nr < __i2c_first_dynamic_bus_num)
                i2c_scan_static_board_info(adap);
@@ -1925,7 +2002,7 @@ void i2c_del_adapter(struct i2c_adapter *adap)
                return;
        }
 
-       acpi_i2c_remove_space_handler(adap);
+       i2c_acpi_remove_space_handler(adap);
        /* Tell drivers about this removal */
        mutex_lock(&core_lock);
        bus_for_each_drv(&i2c_bus_type, NULL, adap,
@@ -2459,7 +2536,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 #endif
 
                if (in_atomic() || irqs_disabled()) {
-                       ret = adap->trylock_bus(adap, I2C_LOCK_SEGMENT);
+                       ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT);
                        if (!ret)
                                /* I2C activity is ongoing. */
                                return -EAGAIN;
index c1ae719..90f59c0 100644 (file)
@@ -159,7 +159,7 @@ static int i2c_mux_trylock_bus(struct i2c_adapter *adapter, unsigned int flags)
                return 0;       /* mux_lock not locked, failure */
        if (!(flags & I2C_LOCK_ROOT_ADAPTER))
                return 1;       /* we only want mux_lock, success */
-       if (parent->trylock_bus(parent, flags))
+       if (i2c_trylock_bus(parent, flags))
                return 1;       /* parent locked too, success */
        rt_mutex_unlock(&parent->mux_lock);
        return 0;               /* parent not locked, failure */
@@ -193,7 +193,7 @@ static int i2c_parent_trylock_bus(struct i2c_adapter *adapter,
 
        if (!rt_mutex_trylock(&parent->mux_lock))
                return 0;       /* mux_lock not locked, failure */
-       if (parent->trylock_bus(parent, flags))
+       if (i2c_trylock_bus(parent, flags))
                return 1;       /* parent locked too, success */
        rt_mutex_unlock(&parent->mux_lock);
        return 0;               /* parent not locked, failure */
index 3cdf8e1..051b147 100644 (file)
@@ -593,6 +593,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
        struct at24_data *at24;
        int err;
        unsigned i, num_addresses;
+       u8 test_byte;
 
        if (client->dev.platform_data) {
                chip = *(struct at24_platform_data *)client->dev.platform_data;
@@ -743,6 +744,18 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
                }
        }
 
+       i2c_set_clientdata(client, at24);
+
+       /*
+        * Perform a one-byte test read to verify that the
+        * chip is functional.
+        */
+       err = at24_read(at24, 0, &test_byte, 1);
+       if (err) {
+               err = -ENODEV;
+               goto err_clients;
+       }
+
        at24->nvmem_config.name = dev_name(&client->dev);
        at24->nvmem_config.dev = &client->dev;
        at24->nvmem_config.read_only = !writable;
@@ -764,8 +777,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
                goto err_clients;
        }
 
-       i2c_set_clientdata(client, at24);
-
        dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n",
                chip.byte_len, client->name,
                writable ? "writable" : "read-only", at24->write_max);
index fffdc27..5b4a3cb 100644 (file)
@@ -600,6 +600,20 @@ i2c_lock_bus(struct i2c_adapter *adapter, unsigned int flags)
        adapter->lock_bus(adapter, flags);
 }
 
+/**
+ * i2c_trylock_bus - Try to get exclusive access to an I2C bus segment
+ * @adapter: Target I2C bus segment
+ * @flags: I2C_LOCK_ROOT_ADAPTER tries to locks the root i2c adapter,
+ *     I2C_LOCK_SEGMENT tries to lock only this branch in the adapter tree
+ *
+ * Return: true if the I2C bus segment is locked, false otherwise
+ */
+static inline int
+i2c_trylock_bus(struct i2c_adapter *adapter, unsigned int flags)
+{
+       return adapter->trylock_bus(adapter, flags);
+}
+
 /**
  * i2c_unlock_bus - Release exclusive access to an I2C bus segment
  * @adapter: Target I2C bus segment
@@ -766,4 +780,13 @@ static inline struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node
 }
 #endif /* CONFIG_OF */
 
+#if IS_ENABLED(CONFIG_ACPI)
+u32 i2c_acpi_find_bus_speed(struct device *dev);
+#else
+static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
+{
+       return 0;
+}
+#endif /* CONFIG_ACPI */
+
 #endif /* _LINUX_I2C_H */