i2c: wmt: split out common files
authorHans Hu <hanshu-oc@zhaoxin.com>
Mon, 8 Apr 2024 02:54:44 +0000 (10:54 +0800)
committerAndi Shyti <andi.shyti@kernel.org>
Sun, 5 May 2024 22:56:42 +0000 (00:56 +0200)
Since the I2C IP of both wmt and zhaoxin originates from VIA,
it is better to separate the common code first.
The common driver is named as i2c-viai2c-common.c.
Old i2c-wmt.c renamed to i2c-viai2c-wmt.c.

The MAINTAINERS file will be updated accordingly in upcoming commits.

Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Hans Hu <hanshu-oc@zhaoxin.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
MAINTAINERS
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-viai2c-common.c [new file with mode: 0644]
drivers/i2c/busses/i2c-viai2c-common.h [new file with mode: 0644]
drivers/i2c/busses/i2c-viai2c-wmt.c [new file with mode: 0644]
drivers/i2c/busses/i2c-wmt.c [deleted file]

index 75554f93e555b0a55bdd404a40be8184e41eca95..a3491d1aa7c372b19cb8fb9ab8525b4f296f1467 100644 (file)
@@ -3017,7 +3017,7 @@ S:        Orphan
 F:     Documentation/devicetree/bindings/i2c/i2c-wmt.txt
 F:     arch/arm/mach-vt8500/
 F:     drivers/clocksource/timer-vt8500.c
-F:     drivers/i2c/busses/i2c-wmt.c
+F:     drivers/i2c/busses/i2c-viai2c-wmt.c
 F:     drivers/mmc/host/wmt-sdmmc.c
 F:     drivers/pwm/pwm-vt8500.c
 F:     drivers/rtc/rtc-vt8500.c
index aa0ee8ecd6f2f53ea109cfeacffe5e2682ae228e..63c7bbad8134fcf15e5177bad1029cdb84424005 100644 (file)
@@ -118,6 +118,7 @@ obj-$(CONFIG_I2C_TEGRA_BPMP)        += i2c-tegra-bpmp.o
 obj-$(CONFIG_I2C_UNIPHIER)     += i2c-uniphier.o
 obj-$(CONFIG_I2C_UNIPHIER_F)   += i2c-uniphier-f.o
 obj-$(CONFIG_I2C_VERSATILE)    += i2c-versatile.o
+i2c-wmt-objs := i2c-viai2c-wmt.o i2c-viai2c-common.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
diff --git a/drivers/i2c/busses/i2c-viai2c-common.c b/drivers/i2c/busses/i2c-viai2c-common.c
new file mode 100644 (file)
index 0000000..b36a5d9
--- /dev/null
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <linux/of_irq.h>
+#include "i2c-viai2c-common.h"
+
+int wmt_i2c_wait_bus_not_busy(struct wmt_i2c_dev *i2c_dev)
+{
+       unsigned long timeout;
+
+       timeout = jiffies + WMT_I2C_TIMEOUT;
+       while (!(readw(i2c_dev->base + REG_CSR) & CSR_READY_MASK)) {
+               if (time_after(jiffies, timeout)) {
+                       dev_warn(i2c_dev->dev, "timeout waiting for bus ready\n");
+                       return -EBUSY;
+               }
+               msleep(20);
+       }
+
+       return 0;
+}
+
+int wmt_check_status(struct wmt_i2c_dev *i2c_dev)
+{
+       int ret = 0;
+       unsigned long wait_result;
+
+       wait_result = wait_for_completion_timeout(&i2c_dev->complete,
+                                                 msecs_to_jiffies(500));
+       if (!wait_result)
+               return -ETIMEDOUT;
+
+       if (i2c_dev->cmd_status & ISR_NACK_ADDR)
+               ret = -EIO;
+
+       if (i2c_dev->cmd_status & ISR_SCL_TIMEOUT)
+               ret = -ETIMEDOUT;
+
+       return ret;
+}
+
+static int wmt_i2c_write(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg, int last)
+{
+       u16 val, tcr_val = i2c_dev->tcr;
+       int ret;
+       int xfer_len = 0;
+
+       if (pmsg->len == 0) {
+               /*
+                * We still need to run through the while (..) once, so
+                * start at -1 and break out early from the loop
+                */
+               xfer_len = -1;
+               writew(0, i2c_dev->base + REG_CDR);
+       } else {
+               writew(pmsg->buf[0] & 0xFF, i2c_dev->base + REG_CDR);
+       }
+
+       if (!(pmsg->flags & I2C_M_NOSTART)) {
+               val = readw(i2c_dev->base + REG_CR);
+               val &= ~CR_TX_END;
+               val |= CR_CPU_RDY;
+               writew(val, i2c_dev->base + REG_CR);
+       }
+
+       reinit_completion(&i2c_dev->complete);
+
+       tcr_val |= (TCR_MASTER_WRITE | (pmsg->addr & TCR_SLAVE_ADDR_MASK));
+
+       writew(tcr_val, i2c_dev->base + REG_TCR);
+
+       if (pmsg->flags & I2C_M_NOSTART) {
+               val = readw(i2c_dev->base + REG_CR);
+               val |= CR_CPU_RDY;
+               writew(val, i2c_dev->base + REG_CR);
+       }
+
+       while (xfer_len < pmsg->len) {
+               ret = wmt_check_status(i2c_dev);
+               if (ret)
+                       return ret;
+
+               xfer_len++;
+
+               val = readw(i2c_dev->base + REG_CSR);
+               if ((val & CSR_RCV_ACK_MASK) == CSR_RCV_NOT_ACK) {
+                       dev_dbg(i2c_dev->dev, "write RCV NACK error\n");
+                       return -EIO;
+               }
+
+               if (pmsg->len == 0) {
+                       val = CR_TX_END | CR_CPU_RDY | CR_ENABLE;
+                       writew(val, i2c_dev->base + REG_CR);
+                       break;
+               }
+
+               if (xfer_len == pmsg->len) {
+                       if (last != 1)
+                               writew(CR_ENABLE, i2c_dev->base + REG_CR);
+               } else {
+                       writew(pmsg->buf[xfer_len] & 0xFF, i2c_dev->base +
+                                                               REG_CDR);
+                       writew(CR_CPU_RDY | CR_ENABLE, i2c_dev->base + REG_CR);
+               }
+       }
+
+       return 0;
+}
+
+static int wmt_i2c_read(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg)
+{
+       u16 val, tcr_val = i2c_dev->tcr;
+       int ret;
+       u32 xfer_len = 0;
+
+       val = readw(i2c_dev->base + REG_CR);
+       val &= ~(CR_TX_END | CR_TX_NEXT_NO_ACK);
+
+       if (!(pmsg->flags & I2C_M_NOSTART))
+               val |= CR_CPU_RDY;
+
+       if (pmsg->len == 1)
+               val |= CR_TX_NEXT_NO_ACK;
+
+       writew(val, i2c_dev->base + REG_CR);
+
+       reinit_completion(&i2c_dev->complete);
+
+       tcr_val |= TCR_MASTER_READ | (pmsg->addr & TCR_SLAVE_ADDR_MASK);
+
+       writew(tcr_val, i2c_dev->base + REG_TCR);
+
+       if (pmsg->flags & I2C_M_NOSTART) {
+               val = readw(i2c_dev->base + REG_CR);
+               val |= CR_CPU_RDY;
+               writew(val, i2c_dev->base + REG_CR);
+       }
+
+       while (xfer_len < pmsg->len) {
+               ret = wmt_check_status(i2c_dev);
+               if (ret)
+                       return ret;
+
+               pmsg->buf[xfer_len] = readw(i2c_dev->base + REG_CDR) >> 8;
+               xfer_len++;
+
+               val = readw(i2c_dev->base + REG_CR) | CR_CPU_RDY;
+               if (xfer_len == pmsg->len - 1)
+                       val |= CR_TX_NEXT_NO_ACK;
+               writew(val, i2c_dev->base + REG_CR);
+       }
+
+       return 0;
+}
+
+int wmt_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+       struct i2c_msg *pmsg;
+       int i;
+       int ret = 0;
+       struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+
+       for (i = 0; ret >= 0 && i < num; i++) {
+               pmsg = &msgs[i];
+               if (!(pmsg->flags & I2C_M_NOSTART)) {
+                       ret = wmt_i2c_wait_bus_not_busy(i2c_dev);
+                       if (ret < 0)
+                               return ret;
+               }
+
+               if (pmsg->flags & I2C_M_RD)
+                       ret = wmt_i2c_read(i2c_dev, pmsg);
+               else
+                       ret = wmt_i2c_write(i2c_dev, pmsg, (i + 1) == num);
+       }
+
+       return (ret < 0) ? ret : i;
+}
+
+static irqreturn_t wmt_i2c_isr(int irq, void *data)
+{
+       struct wmt_i2c_dev *i2c_dev = data;
+
+       /* save the status and write-clear it */
+       i2c_dev->cmd_status = readw(i2c_dev->base + REG_ISR);
+       writew(i2c_dev->cmd_status, i2c_dev->base + REG_ISR);
+
+       complete(&i2c_dev->complete);
+
+       return IRQ_HANDLED;
+}
+
+int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c_dev **pi2c_dev)
+{
+       int err;
+       struct wmt_i2c_dev *i2c_dev;
+       struct device_node *np = pdev->dev.of_node;
+
+       i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
+       if (!i2c_dev)
+               return -ENOMEM;
+
+       i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+       if (IS_ERR(i2c_dev->base))
+               return PTR_ERR(i2c_dev->base);
+
+       i2c_dev->irq = irq_of_parse_and_map(np, 0);
+       if (!i2c_dev->irq)
+               return -EINVAL;
+
+       err = devm_request_irq(&pdev->dev, i2c_dev->irq, wmt_i2c_isr,
+                              0, pdev->name, i2c_dev);
+       if (err)
+               return dev_err_probe(&pdev->dev, err,
+                               "failed to request irq %i\n", i2c_dev->irq);
+
+       i2c_dev->dev = &pdev->dev;
+       init_completion(&i2c_dev->complete);
+       platform_set_drvdata(pdev, i2c_dev);
+
+       *pi2c_dev = i2c_dev;
+       return 0;
+}
diff --git a/drivers/i2c/busses/i2c-viai2c-common.h b/drivers/i2c/busses/i2c-viai2c-common.h
new file mode 100644 (file)
index 0000000..fcff8e4
--- /dev/null
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef __I2C_VIAI2C_COMMON_H_
+#define __I2C_VIAI2C_COMMON_H_
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+
+#define REG_CR         0x00
+#define REG_TCR                0x02
+#define REG_CSR                0x04
+#define REG_ISR                0x06
+#define REG_IMR                0x08
+#define REG_CDR                0x0A
+#define REG_TR         0x0C
+#define REG_MCR                0x0E
+
+/* REG_CR Bit fields */
+#define CR_TX_NEXT_ACK         0x0000
+#define CR_ENABLE              0x0001
+#define CR_TX_NEXT_NO_ACK      0x0002
+#define CR_TX_END              0x0004
+#define CR_CPU_RDY             0x0008
+#define SLAV_MODE_SEL          0x8000
+
+/* REG_TCR Bit fields */
+#define TCR_STANDARD_MODE      0x0000
+#define TCR_MASTER_WRITE       0x0000
+#define TCR_HS_MODE            0x2000
+#define TCR_MASTER_READ                0x4000
+#define TCR_FAST_MODE          0x8000
+#define TCR_SLAVE_ADDR_MASK    0x007F
+
+/* REG_ISR Bit fields */
+#define ISR_NACK_ADDR          0x0001
+#define ISR_BYTE_END           0x0002
+#define ISR_SCL_TIMEOUT                0x0004
+#define ISR_WRITE_ALL          0x0007
+
+/* REG_IMR Bit fields */
+#define IMR_ENABLE_ALL         0x0007
+
+/* REG_CSR Bit fields */
+#define CSR_RCV_NOT_ACK                0x0001
+#define CSR_RCV_ACK_MASK       0x0001
+#define CSR_READY_MASK         0x0002
+
+#define WMT_I2C_TIMEOUT                (msecs_to_jiffies(1000))
+
+struct wmt_i2c_dev {
+       struct i2c_adapter      adapter;
+       struct completion       complete;
+       struct device           *dev;
+       void __iomem            *base;
+       struct clk              *clk;
+       u16                     tcr;
+       int                     irq;
+       u16                     cmd_status;
+};
+
+int wmt_i2c_wait_bus_not_busy(struct wmt_i2c_dev *i2c_dev);
+int wmt_check_status(struct wmt_i2c_dev *i2c_dev);
+int wmt_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num);
+int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c_dev **pi2c_dev);
+
+#endif
diff --git a/drivers/i2c/busses/i2c-viai2c-wmt.c b/drivers/i2c/busses/i2c-viai2c-wmt.c
new file mode 100644 (file)
index 0000000..3125374
--- /dev/null
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  Wondermedia I2C Master Mode Driver
+ *
+ *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ *  Derived from GPLv2+ licensed source:
+ *  - Copyright (C) 2008 WonderMedia Technologies, Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include "i2c-viai2c-common.h"
+
+#define REG_SLAVE_CR   0x10
+#define REG_SLAVE_SR   0x12
+#define REG_SLAVE_ISR  0x14
+#define REG_SLAVE_IMR  0x16
+#define REG_SLAVE_DR   0x18
+#define REG_SLAVE_TR   0x1A
+
+/* REG_TR */
+#define SCL_TIMEOUT(x)         (((x) & 0xFF) << 8)
+#define TR_STD                 0x0064
+#define TR_HS                  0x0019
+
+/* REG_MCR */
+#define MCR_APB_96M            7
+#define MCR_APB_166M           12
+
+static u32 wmt_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART;
+}
+
+static const struct i2c_algorithm wmt_i2c_algo = {
+       .master_xfer    = wmt_i2c_xfer,
+       .functionality  = wmt_i2c_func,
+};
+
+static int wmt_i2c_reset_hardware(struct wmt_i2c_dev *i2c_dev)
+{
+       int err;
+
+       err = clk_prepare_enable(i2c_dev->clk);
+       if (err) {
+               dev_err(i2c_dev->dev, "failed to enable clock\n");
+               return err;
+       }
+
+       err = clk_set_rate(i2c_dev->clk, 20000000);
+       if (err) {
+               dev_err(i2c_dev->dev, "failed to set clock = 20Mhz\n");
+               clk_disable_unprepare(i2c_dev->clk);
+               return err;
+       }
+
+       writew(0, i2c_dev->base + REG_CR);
+       writew(MCR_APB_166M, i2c_dev->base + REG_MCR);
+       writew(ISR_WRITE_ALL, i2c_dev->base + REG_ISR);
+       writew(IMR_ENABLE_ALL, i2c_dev->base + REG_IMR);
+       writew(CR_ENABLE, i2c_dev->base + REG_CR);
+       readw(i2c_dev->base + REG_CSR);         /* read clear */
+       writew(ISR_WRITE_ALL, i2c_dev->base + REG_ISR);
+
+       if (i2c_dev->tcr == TCR_FAST_MODE)
+               writew(SCL_TIMEOUT(128) | TR_HS, i2c_dev->base + REG_TR);
+       else
+               writew(SCL_TIMEOUT(128) | TR_STD, i2c_dev->base + REG_TR);
+
+       return 0;
+}
+
+static int wmt_i2c_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct wmt_i2c_dev *i2c_dev;
+       struct i2c_adapter *adap;
+       int err;
+       u32 clk_rate;
+
+       err = wmt_i2c_init(pdev, &i2c_dev);
+       if (err)
+               return err;
+
+       i2c_dev->clk = of_clk_get(np, 0);
+       if (IS_ERR(i2c_dev->clk)) {
+               dev_err(&pdev->dev, "unable to request clock\n");
+               return PTR_ERR(i2c_dev->clk);
+       }
+
+       err = of_property_read_u32(np, "clock-frequency", &clk_rate);
+       if (!err && clk_rate == I2C_MAX_FAST_MODE_FREQ)
+               i2c_dev->tcr = TCR_FAST_MODE;
+
+       adap = &i2c_dev->adapter;
+       i2c_set_adapdata(adap, i2c_dev);
+       strscpy(adap->name, "WMT I2C adapter", sizeof(adap->name));
+       adap->owner = THIS_MODULE;
+       adap->algo = &wmt_i2c_algo;
+       adap->dev.parent = &pdev->dev;
+       adap->dev.of_node = pdev->dev.of_node;
+
+       err = wmt_i2c_reset_hardware(i2c_dev);
+       if (err) {
+               dev_err(&pdev->dev, "error initializing hardware\n");
+               return err;
+       }
+
+       err = i2c_add_adapter(adap);
+       if (err)
+               /* wmt_i2c_reset_hardware() enables i2c_dev->clk */
+               clk_disable_unprepare(i2c_dev->clk);
+
+       return err;
+}
+
+static void wmt_i2c_remove(struct platform_device *pdev)
+{
+       struct wmt_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+
+       /* Disable interrupts, clock and delete adapter */
+       writew(0, i2c_dev->base + REG_IMR);
+       clk_disable_unprepare(i2c_dev->clk);
+       i2c_del_adapter(&i2c_dev->adapter);
+}
+
+static const struct of_device_id wmt_i2c_dt_ids[] = {
+       { .compatible = "wm,wm8505-i2c" },
+       { /* Sentinel */ },
+};
+
+static struct platform_driver wmt_i2c_driver = {
+       .probe          = wmt_i2c_probe,
+       .remove_new     = wmt_i2c_remove,
+       .driver         = {
+               .name   = "wmt-i2c",
+               .of_match_table = wmt_i2c_dt_ids,
+       },
+};
+
+module_platform_driver(wmt_i2c_driver);
+
+MODULE_DESCRIPTION("Wondermedia I2C master-mode bus adapter");
+MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, wmt_i2c_dt_ids);
diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c
deleted file mode 100644 (file)
index 76ede43..0000000
+++ /dev/null
@@ -1,430 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *  Wondermedia I2C Master Mode Driver
- *
- *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
- *
- *  Derived from GPLv2+ licensed source:
- *  - Copyright (C) 2008 WonderMedia Technologies, Inc.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/platform_device.h>
-
-#define REG_CR         0x00
-#define REG_TCR                0x02
-#define REG_CSR                0x04
-#define REG_ISR                0x06
-#define REG_IMR                0x08
-#define REG_CDR                0x0A
-#define REG_TR         0x0C
-#define REG_MCR                0x0E
-#define REG_SLAVE_CR   0x10
-#define REG_SLAVE_SR   0x12
-#define REG_SLAVE_ISR  0x14
-#define REG_SLAVE_IMR  0x16
-#define REG_SLAVE_DR   0x18
-#define REG_SLAVE_TR   0x1A
-
-/* REG_CR Bit fields */
-#define CR_TX_NEXT_ACK         0x0000
-#define CR_ENABLE              0x0001
-#define CR_TX_NEXT_NO_ACK      0x0002
-#define CR_TX_END              0x0004
-#define CR_CPU_RDY             0x0008
-#define SLAV_MODE_SEL          0x8000
-
-/* REG_TCR Bit fields */
-#define TCR_STANDARD_MODE      0x0000
-#define TCR_MASTER_WRITE       0x0000
-#define TCR_HS_MODE            0x2000
-#define TCR_MASTER_READ                0x4000
-#define TCR_FAST_MODE          0x8000
-#define TCR_SLAVE_ADDR_MASK    0x007F
-
-/* REG_ISR Bit fields */
-#define ISR_NACK_ADDR          0x0001
-#define ISR_BYTE_END           0x0002
-#define ISR_SCL_TIMEOUT                0x0004
-#define ISR_WRITE_ALL          0x0007
-
-/* REG_IMR Bit fields */
-#define IMR_ENABLE_ALL         0x0007
-
-/* REG_CSR Bit fields */
-#define CSR_RCV_NOT_ACK                0x0001
-#define CSR_RCV_ACK_MASK       0x0001
-#define CSR_READY_MASK         0x0002
-
-/* REG_TR */
-#define SCL_TIMEOUT(x)         (((x) & 0xFF) << 8)
-#define TR_STD                 0x0064
-#define TR_HS                  0x0019
-
-/* REG_MCR */
-#define MCR_APB_96M            7
-#define MCR_APB_166M           12
-
-#define WMT_I2C_TIMEOUT                (msecs_to_jiffies(1000))
-
-struct wmt_i2c_dev {
-       struct i2c_adapter      adapter;
-       struct completion       complete;
-       struct device           *dev;
-       void __iomem            *base;
-       struct clk              *clk;
-       u16                     tcr;
-       int                     irq;
-       u16                     cmd_status;
-};
-
-static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c_dev *i2c_dev)
-{
-       unsigned long timeout;
-
-       timeout = jiffies + WMT_I2C_TIMEOUT;
-       while (!(readw(i2c_dev->base + REG_CSR) & CSR_READY_MASK)) {
-               if (time_after(jiffies, timeout)) {
-                       dev_warn(i2c_dev->dev, "timeout waiting for bus ready\n");
-                       return -EBUSY;
-               }
-               msleep(20);
-       }
-
-       return 0;
-}
-
-static int wmt_check_status(struct wmt_i2c_dev *i2c_dev)
-{
-       int ret = 0;
-       unsigned long wait_result;
-
-       wait_result = wait_for_completion_timeout(&i2c_dev->complete,
-                                                 msecs_to_jiffies(500));
-       if (!wait_result)
-               return -ETIMEDOUT;
-
-       if (i2c_dev->cmd_status & ISR_NACK_ADDR)
-               ret = -EIO;
-
-       if (i2c_dev->cmd_status & ISR_SCL_TIMEOUT)
-               ret = -ETIMEDOUT;
-
-       return ret;
-}
-
-static int wmt_i2c_write(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg,
-                        int last)
-{
-       u16 val, tcr_val = i2c_dev->tcr;
-       int ret;
-       int xfer_len = 0;
-
-       if (pmsg->len == 0) {
-               /*
-                * We still need to run through the while (..) once, so
-                * start at -1 and break out early from the loop
-                */
-               xfer_len = -1;
-               writew(0, i2c_dev->base + REG_CDR);
-       } else {
-               writew(pmsg->buf[0] & 0xFF, i2c_dev->base + REG_CDR);
-       }
-
-       if (!(pmsg->flags & I2C_M_NOSTART)) {
-               val = readw(i2c_dev->base + REG_CR);
-               val &= ~CR_TX_END;
-               val |= CR_CPU_RDY;
-               writew(val, i2c_dev->base + REG_CR);
-       }
-
-       reinit_completion(&i2c_dev->complete);
-
-       tcr_val |= (TCR_MASTER_WRITE | (pmsg->addr & TCR_SLAVE_ADDR_MASK));
-
-       writew(tcr_val, i2c_dev->base + REG_TCR);
-
-       if (pmsg->flags & I2C_M_NOSTART) {
-               val = readw(i2c_dev->base + REG_CR);
-               val |= CR_CPU_RDY;
-               writew(val, i2c_dev->base + REG_CR);
-       }
-
-       while (xfer_len < pmsg->len) {
-               ret = wmt_check_status(i2c_dev);
-               if (ret)
-                       return ret;
-
-               xfer_len++;
-
-               val = readw(i2c_dev->base + REG_CSR);
-               if ((val & CSR_RCV_ACK_MASK) == CSR_RCV_NOT_ACK) {
-                       dev_dbg(i2c_dev->dev, "write RCV NACK error\n");
-                       return -EIO;
-               }
-
-               if (pmsg->len == 0) {
-                       val = CR_TX_END | CR_CPU_RDY | CR_ENABLE;
-                       writew(val, i2c_dev->base + REG_CR);
-                       break;
-               }
-
-               if (xfer_len == pmsg->len) {
-                       if (last != 1)
-                               writew(CR_ENABLE, i2c_dev->base + REG_CR);
-               } else {
-                       writew(pmsg->buf[xfer_len] & 0xFF, i2c_dev->base +
-                                                               REG_CDR);
-                       writew(CR_CPU_RDY | CR_ENABLE, i2c_dev->base + REG_CR);
-               }
-       }
-
-       return 0;
-}
-
-static int wmt_i2c_read(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg)
-{
-       u16 val, tcr_val = i2c_dev->tcr;
-       int ret;
-       u32 xfer_len = 0;
-
-       val = readw(i2c_dev->base + REG_CR);
-       val &= ~(CR_TX_END | CR_TX_NEXT_NO_ACK);
-
-       if (!(pmsg->flags & I2C_M_NOSTART))
-               val |= CR_CPU_RDY;
-
-       if (pmsg->len == 1)
-               val |= CR_TX_NEXT_NO_ACK;
-
-       writew(val, i2c_dev->base + REG_CR);
-
-       reinit_completion(&i2c_dev->complete);
-
-       tcr_val |= TCR_MASTER_READ | (pmsg->addr & TCR_SLAVE_ADDR_MASK);
-
-       writew(tcr_val, i2c_dev->base + REG_TCR);
-
-       if (pmsg->flags & I2C_M_NOSTART) {
-               val = readw(i2c_dev->base + REG_CR);
-               val |= CR_CPU_RDY;
-               writew(val, i2c_dev->base + REG_CR);
-       }
-
-       while (xfer_len < pmsg->len) {
-               ret = wmt_check_status(i2c_dev);
-               if (ret)
-                       return ret;
-
-               pmsg->buf[xfer_len] = readw(i2c_dev->base + REG_CDR) >> 8;
-               xfer_len++;
-
-               val = readw(i2c_dev->base + REG_CR) | CR_CPU_RDY;
-               if (xfer_len == pmsg->len - 1)
-                       val |= CR_TX_NEXT_NO_ACK;
-               writew(val, i2c_dev->base + REG_CR);
-       }
-
-       return 0;
-}
-
-static int wmt_i2c_xfer(struct i2c_adapter *adap,
-                       struct i2c_msg msgs[],
-                       int num)
-{
-       struct i2c_msg *pmsg;
-       int i;
-       int ret = 0;
-       struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
-
-       for (i = 0; ret >= 0 && i < num; i++) {
-               pmsg = &msgs[i];
-               if (!(pmsg->flags & I2C_M_NOSTART)) {
-                       ret = wmt_i2c_wait_bus_not_busy(i2c_dev);
-                       if (ret < 0)
-                               return ret;
-               }
-
-               if (pmsg->flags & I2C_M_RD)
-                       ret = wmt_i2c_read(i2c_dev, pmsg);
-               else
-                       ret = wmt_i2c_write(i2c_dev, pmsg, (i + 1) == num);
-       }
-
-       return (ret < 0) ? ret : i;
-}
-
-static u32 wmt_i2c_func(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART;
-}
-
-static const struct i2c_algorithm wmt_i2c_algo = {
-       .master_xfer    = wmt_i2c_xfer,
-       .functionality  = wmt_i2c_func,
-};
-
-static irqreturn_t wmt_i2c_isr(int irq, void *data)
-{
-       struct wmt_i2c_dev *i2c_dev = data;
-
-       /* save the status and write-clear it */
-       i2c_dev->cmd_status = readw(i2c_dev->base + REG_ISR);
-       writew(i2c_dev->cmd_status, i2c_dev->base + REG_ISR);
-
-       complete(&i2c_dev->complete);
-
-       return IRQ_HANDLED;
-}
-
-static int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c_dev **pi2c_dev)
-{
-       int err;
-       struct wmt_i2c_dev *i2c_dev;
-       struct device_node *np = pdev->dev.of_node;
-
-       i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
-       if (!i2c_dev)
-               return -ENOMEM;
-
-       i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
-       if (IS_ERR(i2c_dev->base))
-               return PTR_ERR(i2c_dev->base);
-
-       i2c_dev->irq = irq_of_parse_and_map(np, 0);
-       if (!i2c_dev->irq)
-               return -EINVAL;
-
-       err = devm_request_irq(&pdev->dev, i2c_dev->irq, wmt_i2c_isr,
-                              0, pdev->name, i2c_dev);
-       if (err)
-               return dev_err_probe(&pdev->dev, err,
-                               "failed to request irq %i\n", i2c_dev->irq);
-
-       i2c_dev->dev = &pdev->dev;
-       init_completion(&i2c_dev->complete);
-       platform_set_drvdata(pdev, i2c_dev);
-
-       *pi2c_dev = i2c_dev;
-       return 0;
-}
-
-static int wmt_i2c_reset_hardware(struct wmt_i2c_dev *i2c_dev)
-{
-       int err;
-
-       err = clk_prepare_enable(i2c_dev->clk);
-       if (err) {
-               dev_err(i2c_dev->dev, "failed to enable clock\n");
-               return err;
-       }
-
-       err = clk_set_rate(i2c_dev->clk, 20000000);
-       if (err) {
-               dev_err(i2c_dev->dev, "failed to set clock = 20Mhz\n");
-               clk_disable_unprepare(i2c_dev->clk);
-               return err;
-       }
-
-       writew(0, i2c_dev->base + REG_CR);
-       writew(MCR_APB_166M, i2c_dev->base + REG_MCR);
-       writew(ISR_WRITE_ALL, i2c_dev->base + REG_ISR);
-       writew(IMR_ENABLE_ALL, i2c_dev->base + REG_IMR);
-       writew(CR_ENABLE, i2c_dev->base + REG_CR);
-       readw(i2c_dev->base + REG_CSR);         /* read clear */
-       writew(ISR_WRITE_ALL, i2c_dev->base + REG_ISR);
-
-       if (i2c_dev->tcr == TCR_FAST_MODE)
-               writew(SCL_TIMEOUT(128) | TR_HS, i2c_dev->base + REG_TR);
-       else
-               writew(SCL_TIMEOUT(128) | TR_STD, i2c_dev->base + REG_TR);
-
-       return 0;
-}
-
-static int wmt_i2c_probe(struct platform_device *pdev)
-{
-       struct device_node *np = pdev->dev.of_node;
-       struct wmt_i2c_dev *i2c_dev;
-       struct i2c_adapter *adap;
-       int err;
-       u32 clk_rate;
-
-       err = wmt_i2c_init(pdev, &i2c_dev);
-       if (err)
-               return err;
-
-       i2c_dev->clk = of_clk_get(np, 0);
-       if (IS_ERR(i2c_dev->clk)) {
-               dev_err(&pdev->dev, "unable to request clock\n");
-               return PTR_ERR(i2c_dev->clk);
-       }
-
-       err = of_property_read_u32(np, "clock-frequency", &clk_rate);
-       if (!err && clk_rate == I2C_MAX_FAST_MODE_FREQ)
-               i2c_dev->tcr = TCR_FAST_MODE;
-
-       adap = &i2c_dev->adapter;
-       i2c_set_adapdata(adap, i2c_dev);
-       strscpy(adap->name, "WMT I2C adapter", sizeof(adap->name));
-       adap->owner = THIS_MODULE;
-       adap->algo = &wmt_i2c_algo;
-       adap->dev.parent = &pdev->dev;
-       adap->dev.of_node = pdev->dev.of_node;
-
-       err = wmt_i2c_reset_hardware(i2c_dev);
-       if (err) {
-               dev_err(&pdev->dev, "error initializing hardware\n");
-               return err;
-       }
-
-       err = i2c_add_adapter(adap);
-       if (err)
-               goto err_disable_clk;
-
-       return 0;
-
-err_disable_clk:
-       clk_disable_unprepare(i2c_dev->clk);
-       return err;
-}
-
-static void wmt_i2c_remove(struct platform_device *pdev)
-{
-       struct wmt_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
-
-       /* Disable interrupts, clock and delete adapter */
-       writew(0, i2c_dev->base + REG_IMR);
-       clk_disable_unprepare(i2c_dev->clk);
-       i2c_del_adapter(&i2c_dev->adapter);
-}
-
-static const struct of_device_id wmt_i2c_dt_ids[] = {
-       { .compatible = "wm,wm8505-i2c" },
-       { /* Sentinel */ },
-};
-
-static struct platform_driver wmt_i2c_driver = {
-       .probe          = wmt_i2c_probe,
-       .remove_new     = wmt_i2c_remove,
-       .driver         = {
-               .name   = "wmt-i2c",
-               .of_match_table = wmt_i2c_dt_ids,
-       },
-};
-
-module_platform_driver(wmt_i2c_driver);
-
-MODULE_DESCRIPTION("Wondermedia I2C master-mode bus adapter");
-MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(of, wmt_i2c_dt_ids);