Merge branch 'i2c/for-mergewindow' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Aug 2021 21:34:01 +0000 (14:34 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Aug 2021 21:34:01 +0000 (14:34 -0700)
Pull i2c updates from Wolfram Sang:
 "I2C has a smaller pull reuest this time:

   - new driver for I2C virtio

   - removal of PMC SMP driver because platform is already gone

   - IRQ probing and DMAENGINE API cleanups

   - add SI metric prefix definitions to units.h

   - beginning of i801 refactorization

   - a few driver improvements"

* 'i2c/for-mergewindow' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (28 commits)
  i2c: cadence: Implement save restore
  i2c: xlp9xx: fix main IRQ check
  i2c: mt65xx: fix IRQ check
  i2c: virtio: add a virtio i2c frontend driver
  i2c: hix5hd2: fix IRQ check
  i2c: s3c2410: fix IRQ check
  i2c: iop3xx: fix deferred probing
  i2c: synquacer: fix deferred probing
  i2c: sun6i-pw2i: Prefer strscpy over strlcpy
  i2c: remove dead PMC MSP TWI/SMBus/I2C driver
  i2c: dev: Use sysfs_emit() in "show" functions
  i2c: dev: Define pr_fmt() and drop duplication substrings
  i2c: designware: Fix indentation in the header
  i2c: designware: Use DIV_ROUND_CLOSEST() macro
  units: Add SI metric prefix definitions
  i2c: at91: mark PM ops as __maybe unused
  i2c: sh_mobile: : use proper DMAENGINE API for termination
  i2c: qup: : use proper DMAENGINE API for termination
  i2c: mxs: : use proper DMAENGINE API for termination
  i2c: imx: : use proper DMAENGINE API for termination
  ...

29 files changed:
MAINTAINERS
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-at91-core.c
drivers/i2c/busses/i2c-at91-master.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-designware-common.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-highlander.c
drivers/i2c/busses/i2c-hix5hd2.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-iop3xx.c
drivers/i2c/busses/i2c-mt65xx.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-parport.c
drivers/i2c/busses/i2c-pmcmsp.c [deleted file]
drivers/i2c/busses/i2c-qup.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/i2c/busses/i2c-sun6i-p2wi.c
drivers/i2c/busses/i2c-synquacer.c
drivers/i2c/busses/i2c-virtio.c [new file with mode: 0644]
drivers/i2c/busses/i2c-xlp9xx.c
drivers/i2c/i2c-dev.c
include/linux/units.h
include/uapi/linux/virtio_i2c.h [new file with mode: 0644]
include/uapi/linux/virtio_ids.h

index d592db0..629a011 100644 (file)
@@ -19736,6 +19736,15 @@ S:     Maintained
 F:     include/uapi/linux/virtio_snd.h
 F:     sound/virtio/*
 
+VIRTIO I2C DRIVER
+M:     Jie Deng <jie.deng@intel.com>
+M:     Viresh Kumar <viresh.kumar@linaro.org>
+L:     linux-i2c@vger.kernel.org
+L:     virtualization@lists.linux-foundation.org
+S:     Maintained
+F:     drivers/i2c/busses/i2c-virtio.c
+F:     include/uapi/linux/virtio_i2c.h
+
 VIRTUAL BOX GUEST DEVICE DRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
 M:     Arnd Bergmann <arnd@arndb.de>
index 10acece..e17790f 100644 (file)
@@ -866,15 +866,6 @@ config I2C_PCA_PLATFORM
          This driver can also be built as a module.  If so, the module
          will be called i2c-pca-platform.
 
-config I2C_PMCMSP
-       tristate "PMC MSP I2C TWI Controller"
-       depends on PMC_MSP || COMPILE_TEST
-       help
-         This driver supports the PMC TWI controller on MSP devices.
-
-         This driver can also be built as module. If so, the module
-         will be called i2c-pmcmsp.
-
 config I2C_PNX
        tristate "I2C bus support for Philips PNX and NXP LPC targets"
        depends on ARCH_LPC32XX || COMPILE_TEST
@@ -1402,4 +1393,15 @@ config I2C_FSI
          This driver can also be built as a module. If so, the module will be
          called as i2c-fsi.
 
+config I2C_VIRTIO
+        tristate "Virtio I2C Adapter"
+        select VIRTIO
+        help
+          If you say yes to this option, support will be included for the virtio
+          I2C adapter driver. The hardware can be emulated by any device model
+          software according to the virtio protocol.
+
+          This driver can also be built as a module. If so, the module
+          will be called i2c-virtio.
+
 endmenu
index 69e9963..1336b04 100644 (file)
@@ -86,7 +86,6 @@ obj-$(CONFIG_I2C_OMAP)                += i2c-omap.o
 obj-$(CONFIG_I2C_OWL)          += i2c-owl.o
 obj-$(CONFIG_I2C_PASEMI)       += i2c-pasemi.o
 obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
-obj-$(CONFIG_I2C_PMCMSP)       += i2c-pmcmsp.o
 obj-$(CONFIG_I2C_PNX)          += i2c-pnx.o
 obj-$(CONFIG_I2C_PXA)          += i2c-pxa.o
 obj-$(CONFIG_I2C_PXA_PCI)      += i2c-pxa-pci.o
@@ -146,5 +145,6 @@ obj-$(CONFIG_I2C_SIBYTE)    += i2c-sibyte.o
 obj-$(CONFIG_I2C_XGENE_SLIMPRO) += i2c-xgene-slimpro.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
 obj-$(CONFIG_I2C_FSI)          += i2c-fsi.o
+obj-$(CONFIG_I2C_VIRTIO)       += i2c-virtio.o
 
 ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
index e14edd2..2df9df5 100644 (file)
@@ -286,9 +286,7 @@ static int at91_twi_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-
-static int at91_twi_runtime_suspend(struct device *dev)
+static int __maybe_unused at91_twi_runtime_suspend(struct device *dev)
 {
        struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
 
@@ -299,7 +297,7 @@ static int at91_twi_runtime_suspend(struct device *dev)
        return 0;
 }
 
-static int at91_twi_runtime_resume(struct device *dev)
+static int __maybe_unused at91_twi_runtime_resume(struct device *dev)
 {
        struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
 
@@ -308,7 +306,7 @@ static int at91_twi_runtime_resume(struct device *dev)
        return clk_prepare_enable(twi_dev->clk);
 }
 
-static int at91_twi_suspend_noirq(struct device *dev)
+static int __maybe_unused at91_twi_suspend_noirq(struct device *dev)
 {
        if (!pm_runtime_status_suspended(dev))
                at91_twi_runtime_suspend(dev);
@@ -316,7 +314,7 @@ static int at91_twi_suspend_noirq(struct device *dev)
        return 0;
 }
 
-static int at91_twi_resume_noirq(struct device *dev)
+static int __maybe_unused at91_twi_resume_noirq(struct device *dev)
 {
        struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
        int ret;
@@ -335,18 +333,13 @@ static int at91_twi_resume_noirq(struct device *dev)
        return 0;
 }
 
-static const struct dev_pm_ops at91_twi_pm = {
+static const struct dev_pm_ops __maybe_unused at91_twi_pm = {
        .suspend_noirq  = at91_twi_suspend_noirq,
        .resume_noirq   = at91_twi_resume_noirq,
        .runtime_suspend        = at91_twi_runtime_suspend,
        .runtime_resume         = at91_twi_runtime_resume,
 };
 
-#define at91_twi_pm_ops (&at91_twi_pm)
-#else
-#define at91_twi_pm_ops NULL
-#endif
-
 static struct platform_driver at91_twi_driver = {
        .probe          = at91_twi_probe,
        .remove         = at91_twi_remove,
@@ -354,7 +347,7 @@ static struct platform_driver at91_twi_driver = {
        .driver         = {
                .name   = "at91_i2c",
                .of_match_table = of_match_ptr(atmel_twi_dt_ids),
-               .pm     = at91_twi_pm_ops,
+               .pm     = pm_ptr(&at91_twi_pm),
        },
 };
 
index 1cceb68..b0eae94 100644 (file)
@@ -138,9 +138,9 @@ static void at91_twi_dma_cleanup(struct at91_twi_dev *dev)
 
        if (dma->xfer_in_progress) {
                if (dma->direction == DMA_FROM_DEVICE)
-                       dmaengine_terminate_all(dma->chan_rx);
+                       dmaengine_terminate_sync(dma->chan_rx);
                else
-                       dmaengine_terminate_all(dma->chan_tx);
+                       dmaengine_terminate_sync(dma->chan_tx);
                dma->xfer_in_progress = false;
        }
        if (dma->buf_mapped) {
index 20aa339..805c771 100644 (file)
@@ -178,6 +178,7 @@ enum cdns_i2c_slave_state {
  * @clk:               Pointer to struct clk
  * @clk_rate_change_nb:        Notifier block for clock rate changes
  * @quirks:            flag for broken hold bit usage in r1p10
+ * @ctrl_reg:          Cached value of the control register.
  * @ctrl_reg_diva_divb: value of fields DIV_A and DIV_B from CR register
  * @slave:             Registered slave instance.
  * @dev_mode:          I2C operating role(master/slave).
@@ -202,6 +203,7 @@ struct cdns_i2c {
        struct clk *clk;
        struct notifier_block clk_rate_change_nb;
        u32 quirks;
+       u32 ctrl_reg;
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
        u16 ctrl_reg_diva_divb;
        struct i2c_client *slave;
@@ -1071,10 +1073,11 @@ static int cdns_i2c_setclk(unsigned long clk_in, struct cdns_i2c *id)
        if (ret)
                return ret;
 
-       ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET);
+       ctrl_reg = id->ctrl_reg;
        ctrl_reg &= ~(CDNS_I2C_CR_DIVA_MASK | CDNS_I2C_CR_DIVB_MASK);
        ctrl_reg |= ((div_a << CDNS_I2C_CR_DIVA_SHIFT) |
                        (div_b << CDNS_I2C_CR_DIVB_SHIFT));
+       id->ctrl_reg = ctrl_reg;
        cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
        id->ctrl_reg_diva_divb = ctrl_reg & (CDNS_I2C_CR_DIVA_MASK |
@@ -1162,6 +1165,26 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
        return 0;
 }
 
+/**
+ * cdns_i2c_init -  Controller initialisation
+ * @id:                Device private data structure
+ *
+ * Initialise the i2c controller.
+ *
+ */
+static void cdns_i2c_init(struct cdns_i2c *id)
+{
+       cdns_i2c_writereg(id->ctrl_reg, CDNS_I2C_CR_OFFSET);
+       /*
+        * Cadence I2C controller has a bug wherein it generates
+        * invalid read transaction after HW timeout in master receiver mode.
+        * HW timeout is not used by this driver and the interrupt is disabled.
+        * But the feature itself cannot be disabled. Hence maximum value
+        * is written to this register to reduce the chances of error.
+        */
+       cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
+}
+
 /**
  * cdns_i2c_runtime_resume - Runtime resume
  * @dev:       Address of the platform_device structure
@@ -1180,6 +1203,7 @@ static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev)
                dev_err(dev, "Cannot enable clock.\n");
                return ret;
        }
+       cdns_i2c_init(xi2c);
 
        return 0;
 }
@@ -1279,7 +1303,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)
        id->dev_mode = CDNS_I2C_MODE_MASTER;
        id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE;
 #endif
-       cdns_i2c_writereg(CDNS_I2C_CR_MASTER_EN_MASK, CDNS_I2C_CR_OFFSET);
+       id->ctrl_reg = CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS;
 
        ret = cdns_i2c_setclk(id->input_clk, id);
        if (ret) {
@@ -1294,15 +1318,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
                goto err_clk_dis;
        }
-
-       /*
-        * Cadence I2C controller has a bug wherein it generates
-        * invalid read transaction after HW timeout in master receiver mode.
-        * HW timeout is not used by this driver and the interrupt is disabled.
-        * But the feature itself cannot be disabled. Hence maximum value
-        * is written to this register to reduce the chances of error.
-        */
-       cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
+       cdns_i2c_init(id);
 
        ret = i2c_add_adapter(&id->adap);
        if (ret < 0)
index fdc34d9..bf2a492 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/regmap.h>
 #include <linux/swab.h>
 #include <linux/types.h>
+#include <linux/units.h>
 
 #include "i2c-designware-core.h"
 
@@ -350,7 +351,7 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
                 *
                 * If your hardware is free from tHD;STA issue, try this one.
                 */
-               return (ic_clk * tSYMBOL + 500000) / 1000000 - 8 + offset;
+               return DIV_ROUND_CLOSEST(ic_clk * tSYMBOL, MICRO) - 8 + offset;
        else
                /*
                 * Conditional expression:
@@ -366,8 +367,7 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
                 * The reason why we need to take into account "tf" here,
                 * is the same as described in i2c_dw_scl_lcnt().
                 */
-               return (ic_clk * (tSYMBOL + tf) + 500000) / 1000000
-                       - 3 + offset;
+               return DIV_ROUND_CLOSEST(ic_clk * (tSYMBOL + tf), MICRO) - 3 + offset;
 }
 
 u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
@@ -383,7 +383,7 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
         * account the fall time of SCL signal (tf).  Default tf value
         * should be 0.3 us, for safety.
         */
-       return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset;
+       return DIV_ROUND_CLOSEST(ic_clk * (tLOW + tf), MICRO) - 1 + offset;
 }
 
 int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
index 6a53f75..60a2e75 100644 (file)
 
 #define DW_IC_ERR_TX_ABRT      0x1
 
-#define DW_IC_TAR_10BITADDR_MASTER BIT(12)
+#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)
@@ -245,7 +245,7 @@ struct dw_i2c_dev {
        struct clk              *clk;
        struct clk              *pclk;
        struct reset_control    *rst;
-       struct i2c_client               *slave;
+       struct i2c_client       *slave;
        u32                     (*get_clk_rate_khz) (struct dw_i2c_dev *dev);
        int                     cmd_err;
        struct i2c_msg          *msgs;
index 4b37f28..2111366 100644 (file)
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
+#include <linux/units.h>
 
 #include "i2c-designware-core.h"
 
 static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
 {
-       return clk_get_rate(dev->clk)/1000;
+       return clk_get_rate(dev->clk) / KILO;
 }
 
 #ifdef CONFIG_ACPI
@@ -270,7 +271,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
 
                if (!dev->sda_hold_time && t->sda_hold_ns)
                        dev->sda_hold_time =
-                               div_u64(clk_khz * t->sda_hold_ns + 500000, 1000000);
+                               DIV_S64_ROUND_CLOSEST(clk_khz * t->sda_hold_ns, MICRO);
        }
 
        adap = &dev->adapter;
index 803dad7..a2add12 100644 (file)
@@ -379,7 +379,7 @@ static int highlander_i2c_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, dev);
 
        dev->irq = platform_get_irq(pdev, 0);
-       if (iic_force_poll)
+       if (dev->irq < 0 || iic_force_poll)
                dev->irq = 0;
 
        if (dev->irq) {
index aa00ba8..61ae58f 100644 (file)
@@ -413,7 +413,7 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
                return PTR_ERR(priv->regs);
 
        irq = platform_get_irq(pdev, 0);
-       if (irq <= 0)
+       if (irq < 0)
                return irq;
 
        priv->clk = devm_clk_get(&pdev->dev, NULL);
index aa3f60e..89ae78e 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/platform_data/itco_wdt.h>
 #include <linux/pm_runtime.h>
+#include <linux/mutex.h>
 
 #if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
 #include <linux/gpio/machine.h>
@@ -503,19 +504,16 @@ static int i801_transaction(struct i801_priv *priv, int xact)
 
 static int i801_block_transaction_by_block(struct i801_priv *priv,
                                           union i2c_smbus_data *data,
-                                          char read_write, int command,
-                                          int hwpec)
+                                          char read_write, int command)
 {
-       int i, len;
-       int status;
-       int xact = hwpec ? SMBHSTCNT_PEC_EN : 0;
+       int i, len, status, xact;
 
        switch (command) {
        case I2C_SMBUS_BLOCK_PROC_CALL:
-               xact |= I801_BLOCK_PROC_CALL;
+               xact = I801_BLOCK_PROC_CALL;
                break;
        case I2C_SMBUS_BLOCK_DATA:
-               xact |= I801_BLOCK_DATA;
+               xact = I801_BLOCK_DATA;
                break;
        default:
                return -EOPNOTSUPP;
@@ -561,10 +559,6 @@ static void i801_isr_byte_done(struct i801_priv *priv)
                                        priv->len);
                                /* FIXME: Recover */
                                priv->len = I2C_SMBUS_BLOCK_MAX;
-                       } else {
-                               dev_dbg(&priv->pci_dev->dev,
-                                       "SMBus block read size is %d\n",
-                                       priv->len);
                        }
                        priv->data[-1] = priv->len;
                }
@@ -665,8 +659,7 @@ static irqreturn_t i801_isr(int irq, void *dev_id)
  */
 static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
                                               union i2c_smbus_data *data,
-                                              char read_write, int command,
-                                              int hwpec)
+                                              char read_write, int command)
 {
        int i, len;
        int smbcmd;
@@ -764,9 +757,8 @@ static int i801_set_block_buffer_mode(struct i801_priv *priv)
 }
 
 /* Block transaction function */
-static int i801_block_transaction(struct i801_priv *priv,
-                                 union i2c_smbus_data *data, char read_write,
-                                 int command, int hwpec)
+static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data,
+                                 char read_write, int command)
 {
        int result = 0;
        unsigned char hostc;
@@ -802,11 +794,11 @@ static int i801_block_transaction(struct i801_priv *priv,
         && i801_set_block_buffer_mode(priv) == 0)
                result = i801_block_transaction_by_block(priv, data,
                                                         read_write,
-                                                        command, hwpec);
+                                                        command);
        else
                result = i801_block_transaction_byte_by_byte(priv, data,
                                                             read_write,
-                                                            command, hwpec);
+                                                            command);
 
        if (command == I2C_SMBUS_I2C_BLOCK_DATA
         && read_write == I2C_SMBUS_WRITE) {
@@ -917,8 +909,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
                       SMBAUXCTL(priv));
 
        if (block)
-               ret = i801_block_transaction(priv, data, read_write, size,
-                                            hwpec);
+               ret = i801_block_transaction(priv, data, read_write, size);
        else
                ret = i801_transaction(priv, xact);
 
@@ -1498,12 +1489,11 @@ static const struct itco_wdt_platform_data spt_tco_platform_data = {
        .version = 4,
 };
 
-static DEFINE_SPINLOCK(p2sb_spinlock);
-
 static struct platform_device *
 i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
                 struct resource *tco_res)
 {
+       static DEFINE_MUTEX(p2sb_mutex);
        struct resource *res;
        unsigned int devfn;
        u64 base64_addr;
@@ -1516,7 +1506,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
         * enumerated by the PCI subsystem, so we need to unhide/hide it
         * to lookup the P2SB BAR.
         */
-       spin_lock(&p2sb_spinlock);
+       mutex_lock(&p2sb_mutex);
 
        devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 1);
 
@@ -1534,7 +1524,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
        /* Hide the P2SB device, if it was hidden before */
        if (hidden)
                pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden);
-       spin_unlock(&p2sb_spinlock);
+       mutex_unlock(&p2sb_mutex);
 
        res = &tco_res[1];
        if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS)
@@ -1634,7 +1624,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
                 * BIOS is accessing the host controller so prevent it from
                 * suspending automatically from now on.
                 */
-               pm_runtime_get_sync(&pdev->dev);
+               pm_runtime_set_autosuspend_delay(&pdev->dev, -1);
        }
 
        if ((function & ACPI_IO_MASK) == ACPI_READ)
@@ -1674,11 +1664,6 @@ static void i801_acpi_remove(struct i801_priv *priv)
 
        acpi_remove_address_space_handler(adev->handle,
                ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler);
-
-       mutex_lock(&priv->acpi_lock);
-       if (priv->acpi_reserved)
-               pm_runtime_put(&priv->pci_dev->dev);
-       mutex_unlock(&priv->acpi_lock);
 }
 #else
 static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; }
@@ -1690,6 +1675,7 @@ static void i801_setup_hstcfg(struct i801_priv *priv)
        unsigned char hstcfg = priv->original_hstcfg;
 
        hstcfg &= ~SMBHSTCFG_I2C_EN;    /* SMBus timing */
+       hstcfg &= ~SMBHSTCNT_PEC_EN;    /* Disable software PEC */
        hstcfg |= SMBHSTCFG_HST_EN;
        pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg);
 }
index d5b5f08..3576b63 100644 (file)
@@ -423,7 +423,7 @@ static int i2c_imx_dma_xfer(struct imx_i2c_struct *i2c_imx,
        return 0;
 
 err_submit:
-       dmaengine_terminate_all(dma->chan_using);
+       dmaengine_terminate_sync(dma->chan_using);
 err_desc:
        dma_unmap_single(chan_dev, dma->dma_buf,
                        dma->dma_len, dma->dma_data_dir);
@@ -894,7 +894,7 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
                                &i2c_imx->dma->cmd_complete,
                                msecs_to_jiffies(DMA_TIMEOUT));
        if (time_left == 0) {
-               dmaengine_terminate_all(dma->chan_using);
+               dmaengine_terminate_sync(dma->chan_using);
                return -ETIMEDOUT;
        }
 
@@ -949,7 +949,7 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
                                &i2c_imx->dma->cmd_complete,
                                msecs_to_jiffies(DMA_TIMEOUT));
        if (time_left == 0) {
-               dmaengine_terminate_all(dma->chan_using);
+               dmaengine_terminate_sync(dma->chan_using);
                return -ETIMEDOUT;
        }
 
index cfecaf1..4a6ff54 100644 (file)
@@ -469,16 +469,14 @@ iop3xx_i2c_probe(struct platform_device *pdev)
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
-               ret = -ENXIO;
+               ret = irq;
                goto unmap;
        }
        ret = request_irq(irq, iop3xx_i2c_irq_handler, 0,
                                pdev->name, adapter_data);
 
-       if (ret) {
-               ret = -EIO;
+       if (ret)
                goto unmap;
-       }
 
        memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
        new_adapter->owner = THIS_MODULE;
index 4ca716e..477480d 100644 (file)
@@ -1211,7 +1211,7 @@ static int mtk_i2c_probe(struct platform_device *pdev)
                return PTR_ERR(i2c->pdmabase);
 
        irq = platform_get_irq(pdev, 0);
-       if (irq <= 0)
+       if (irq < 0)
                return irq;
 
        init_completion(&i2c->msg_complete);
index f97243f..864a3f1 100644 (file)
@@ -290,14 +290,14 @@ read_init_dma_fail:
 select_init_dma_fail:
        dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
 select_init_pio_fail:
-       dmaengine_terminate_all(i2c->dmach);
+       dmaengine_terminate_sync(i2c->dmach);
        return -EINVAL;
 
 /* Write failpath. */
 write_init_dma_fail:
        dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
 write_init_pio_fail:
-       dmaengine_terminate_all(i2c->dmach);
+       dmaengine_terminate_sync(i2c->dmach);
        return -EINVAL;
 }
 
index a535889..231145c 100644 (file)
@@ -267,6 +267,16 @@ static void i2c_parport_attach(struct parport *port)
        int i;
        struct pardev_cb i2c_parport_cb;
 
+       if (type < 0) {
+               pr_warn("adapter type unspecified\n");
+               return;
+       }
+
+       if (type >= ARRAY_SIZE(adapter_parm)) {
+               pr_warn("invalid type (%d)\n", type);
+               return;
+       }
+
        for (i = 0; i < MAX_DEVICE; i++) {
                if (parport[i] == -1)
                        continue;
@@ -392,32 +402,8 @@ static struct parport_driver i2c_parport_driver = {
        .detach = i2c_parport_detach,
        .devmodel = true,
 };
-
-/* ----- Module loading, unloading and information ------------------------ */
-
-static int __init i2c_parport_init(void)
-{
-       if (type < 0) {
-               pr_warn("adapter type unspecified\n");
-               return -ENODEV;
-       }
-
-       if (type >= ARRAY_SIZE(adapter_parm)) {
-               pr_warn("invalid type (%d)\n", type);
-               return -ENODEV;
-       }
-
-       return parport_register_driver(&i2c_parport_driver);
-}
-
-static void __exit i2c_parport_exit(void)
-{
-       parport_unregister_driver(&i2c_parport_driver);
-}
+module_parport_driver(i2c_parport_driver);
 
 MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
 MODULE_DESCRIPTION("I2C bus over parallel port");
 MODULE_LICENSE("GPL");
-
-module_init(i2c_parport_init);
-module_exit(i2c_parport_exit);
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
deleted file mode 100644 (file)
index 5d89c7c..0000000
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * Specific bus support for PMC-TWI compliant implementation on MSP71xx.
- *
- * Copyright 2005-2007 PMC-Sierra, Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/completion.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#define DRV_NAME       "pmcmsptwi"
-
-#define MSP_TWI_SF_CLK_REG_OFFSET      0x00
-#define MSP_TWI_HS_CLK_REG_OFFSET      0x04
-#define MSP_TWI_CFG_REG_OFFSET         0x08
-#define MSP_TWI_CMD_REG_OFFSET         0x0c
-#define MSP_TWI_ADD_REG_OFFSET         0x10
-#define MSP_TWI_DAT_0_REG_OFFSET       0x14
-#define MSP_TWI_DAT_1_REG_OFFSET       0x18
-#define MSP_TWI_INT_STS_REG_OFFSET     0x1c
-#define MSP_TWI_INT_MSK_REG_OFFSET     0x20
-#define MSP_TWI_BUSY_REG_OFFSET                0x24
-
-#define MSP_TWI_INT_STS_DONE                   (1 << 0)
-#define MSP_TWI_INT_STS_LOST_ARBITRATION       (1 << 1)
-#define MSP_TWI_INT_STS_NO_RESPONSE            (1 << 2)
-#define MSP_TWI_INT_STS_DATA_COLLISION         (1 << 3)
-#define MSP_TWI_INT_STS_BUSY                   (1 << 4)
-#define MSP_TWI_INT_STS_ALL                    0x1f
-
-#define MSP_MAX_BYTES_PER_RW           8
-#define MSP_MAX_POLL                   5
-#define MSP_POLL_DELAY                 10
-#define MSP_IRQ_TIMEOUT                        (MSP_MAX_POLL * MSP_POLL_DELAY)
-
-/* IO Operation macros */
-#define pmcmsptwi_readl                __raw_readl
-#define pmcmsptwi_writel       __raw_writel
-
-/* TWI command type */
-enum pmcmsptwi_cmd_type {
-       MSP_TWI_CMD_WRITE       = 0,    /* Write only */
-       MSP_TWI_CMD_READ        = 1,    /* Read only */
-       MSP_TWI_CMD_WRITE_READ  = 2,    /* Write then Read */
-};
-
-/* The possible results of the xferCmd */
-enum pmcmsptwi_xfer_result {
-       MSP_TWI_XFER_OK = 0,
-       MSP_TWI_XFER_TIMEOUT,
-       MSP_TWI_XFER_BUSY,
-       MSP_TWI_XFER_DATA_COLLISION,
-       MSP_TWI_XFER_NO_RESPONSE,
-       MSP_TWI_XFER_LOST_ARBITRATION,
-};
-
-/* Corresponds to a PMCTWI clock configuration register */
-struct pmcmsptwi_clock {
-       u8 filter;      /* Bits 15:12,  default = 0x03 */
-       u16 clock;      /* Bits 9:0,    default = 0x001f */
-};
-
-struct pmcmsptwi_clockcfg {
-       struct pmcmsptwi_clock standard;  /* The standard/fast clock config */
-       struct pmcmsptwi_clock highspeed; /* The highspeed clock config */
-};
-
-/* Corresponds to the main TWI configuration register */
-struct pmcmsptwi_cfg {
-       u8 arbf;        /* Bits 15:12,  default=0x03 */
-       u8 nak;         /* Bits 11:8,   default=0x03 */
-       u8 add10;       /* Bit 7,       default=0x00 */
-       u8 mst_code;    /* Bits 6:4,    default=0x00 */
-       u8 arb;         /* Bit 1,       default=0x01 */
-       u8 highspeed;   /* Bit 0,       default=0x00 */
-};
-
-/* A single pmctwi command to issue */
-struct pmcmsptwi_cmd {
-       u16 addr;       /* The slave address (7 or 10 bits) */
-       enum pmcmsptwi_cmd_type type;   /* The command type */
-       u8 write_len;   /* Number of bytes in the write buffer */
-       u8 read_len;    /* Number of bytes in the read buffer */
-       u8 *write_data; /* Buffer of characters to send */
-       u8 *read_data;  /* Buffer to fill with incoming data */
-};
-
-/* The private data */
-struct pmcmsptwi_data {
-       void __iomem *iobase;                   /* iomapped base for IO */
-       int irq;                                /* IRQ to use (0 disables) */
-       struct completion wait;                 /* Completion for xfer */
-       struct mutex lock;                      /* Used for threadsafeness */
-       enum pmcmsptwi_xfer_result last_result; /* result of last xfer */
-};
-
-/* The default settings */
-static const struct pmcmsptwi_clockcfg pmcmsptwi_defclockcfg = {
-       .standard = {
-               .filter = 0x3,
-               .clock  = 0x1f,
-       },
-       .highspeed = {
-               .filter = 0x3,
-               .clock  = 0x1f,
-       },
-};
-
-static const struct pmcmsptwi_cfg pmcmsptwi_defcfg = {
-       .arbf           = 0x03,
-       .nak            = 0x03,
-       .add10          = 0x00,
-       .mst_code       = 0x00,
-       .arb            = 0x01,
-       .highspeed      = 0x00,
-};
-
-static struct pmcmsptwi_data pmcmsptwi_data;
-
-static struct i2c_adapter pmcmsptwi_adapter;
-
-/* inline helper functions */
-static inline u32 pmcmsptwi_clock_to_reg(
-                       const struct pmcmsptwi_clock *clock)
-{
-       return ((clock->filter & 0xf) << 12) | (clock->clock & 0x03ff);
-}
-
-static inline u32 pmcmsptwi_cfg_to_reg(const struct pmcmsptwi_cfg *cfg)
-{
-       return ((cfg->arbf & 0xf) << 12) |
-               ((cfg->nak & 0xf) << 8) |
-               ((cfg->add10 & 0x1) << 7) |
-               ((cfg->mst_code & 0x7) << 4) |
-               ((cfg->arb & 0x1) << 1) |
-               (cfg->highspeed & 0x1);
-}
-
-static inline void pmcmsptwi_reg_to_cfg(u32 reg, struct pmcmsptwi_cfg *cfg)
-{
-       cfg->arbf = (reg >> 12) & 0xf;
-       cfg->nak = (reg >> 8) & 0xf;
-       cfg->add10 = (reg >> 7) & 0x1;
-       cfg->mst_code = (reg >> 4) & 0x7;
-       cfg->arb = (reg >> 1) & 0x1;
-       cfg->highspeed = reg & 0x1;
-}
-
-/*
- * Sets the current clock configuration
- */
-static void pmcmsptwi_set_clock_config(const struct pmcmsptwi_clockcfg *cfg,
-                                       struct pmcmsptwi_data *data)
-{
-       mutex_lock(&data->lock);
-       pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->standard),
-                               data->iobase + MSP_TWI_SF_CLK_REG_OFFSET);
-       pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->highspeed),
-                               data->iobase + MSP_TWI_HS_CLK_REG_OFFSET);
-       mutex_unlock(&data->lock);
-}
-
-/*
- * Gets the current TWI bus configuration
- */
-static void pmcmsptwi_get_twi_config(struct pmcmsptwi_cfg *cfg,
-                                       struct pmcmsptwi_data *data)
-{
-       mutex_lock(&data->lock);
-       pmcmsptwi_reg_to_cfg(pmcmsptwi_readl(
-                               data->iobase + MSP_TWI_CFG_REG_OFFSET), cfg);
-       mutex_unlock(&data->lock);
-}
-
-/*
- * Sets the current TWI bus configuration
- */
-static void pmcmsptwi_set_twi_config(const struct pmcmsptwi_cfg *cfg,
-                                       struct pmcmsptwi_data *data)
-{
-       mutex_lock(&data->lock);
-       pmcmsptwi_writel(pmcmsptwi_cfg_to_reg(cfg),
-                               data->iobase + MSP_TWI_CFG_REG_OFFSET);
-       mutex_unlock(&data->lock);
-}
-
-/*
- * Parses the 'int_sts' register and returns a well-defined error code
- */
-static enum pmcmsptwi_xfer_result pmcmsptwi_get_result(u32 reg)
-{
-       if (reg & MSP_TWI_INT_STS_LOST_ARBITRATION) {
-               dev_dbg(&pmcmsptwi_adapter.dev,
-                       "Result: Lost arbitration\n");
-               return MSP_TWI_XFER_LOST_ARBITRATION;
-       } else if (reg & MSP_TWI_INT_STS_NO_RESPONSE) {
-               dev_dbg(&pmcmsptwi_adapter.dev,
-                       "Result: No response\n");
-               return MSP_TWI_XFER_NO_RESPONSE;
-       } else if (reg & MSP_TWI_INT_STS_DATA_COLLISION) {
-               dev_dbg(&pmcmsptwi_adapter.dev,
-                       "Result: Data collision\n");
-               return MSP_TWI_XFER_DATA_COLLISION;
-       } else if (reg & MSP_TWI_INT_STS_BUSY) {
-               dev_dbg(&pmcmsptwi_adapter.dev,
-                       "Result: Bus busy\n");
-               return MSP_TWI_XFER_BUSY;
-       }
-
-       dev_dbg(&pmcmsptwi_adapter.dev, "Result: Operation succeeded\n");
-       return MSP_TWI_XFER_OK;
-}
-
-/*
- * In interrupt mode, handle the interrupt.
- * NOTE: Assumes data->lock is held.
- */
-static irqreturn_t pmcmsptwi_interrupt(int irq, void *ptr)
-{
-       struct pmcmsptwi_data *data = ptr;
-
-       u32 reason = pmcmsptwi_readl(data->iobase +
-                                       MSP_TWI_INT_STS_REG_OFFSET);
-       pmcmsptwi_writel(reason, data->iobase + MSP_TWI_INT_STS_REG_OFFSET);
-
-       dev_dbg(&pmcmsptwi_adapter.dev, "Got interrupt 0x%08x\n", reason);
-       if (!(reason & MSP_TWI_INT_STS_DONE))
-               return IRQ_NONE;
-
-       data->last_result = pmcmsptwi_get_result(reason);
-       complete(&data->wait);
-
-       return IRQ_HANDLED;
-}
-
-/*
- * Probe for and register the device and return 0 if there is one.
- */
-static int pmcmsptwi_probe(struct platform_device *pldev)
-{
-       struct resource *res;
-       int rc = -ENODEV;
-
-       /* get the static platform resources */
-       res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pldev->dev, "IOMEM resource not found\n");
-               goto ret_err;
-       }
-
-       /* reserve the memory region */
-       if (!request_mem_region(res->start, resource_size(res),
-                               pldev->name)) {
-               dev_err(&pldev->dev,
-                       "Unable to get memory/io address region %pap\n",
-                       &res->start);
-               rc = -EBUSY;
-               goto ret_err;
-       }
-
-       /* remap the memory */
-       pmcmsptwi_data.iobase = ioremap(res->start,
-                                               resource_size(res));
-       if (!pmcmsptwi_data.iobase) {
-               dev_err(&pldev->dev,
-                       "Unable to ioremap address %pap\n", &res->start);
-               rc = -EIO;
-               goto ret_unreserve;
-       }
-
-       /* request the irq */
-       pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
-       if (pmcmsptwi_data.irq) {
-               rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
-                                IRQF_SHARED, pldev->name, &pmcmsptwi_data);
-               if (rc == 0) {
-                       /*
-                        * Enable 'DONE' interrupt only.
-                        *
-                        * If you enable all interrupts, you will get one on
-                        * error and another when the operation completes.
-                        * This way you only have to handle one interrupt,
-                        * but you can still check all result flags.
-                        */
-                       pmcmsptwi_writel(MSP_TWI_INT_STS_DONE,
-                                       pmcmsptwi_data.iobase +
-                                       MSP_TWI_INT_MSK_REG_OFFSET);
-               } else {
-                       dev_warn(&pldev->dev,
-                               "Could not assign TWI IRQ handler "
-                               "to irq %d (continuing with poll)\n",
-                               pmcmsptwi_data.irq);
-                       pmcmsptwi_data.irq = 0;
-               }
-       }
-
-       init_completion(&pmcmsptwi_data.wait);
-       mutex_init(&pmcmsptwi_data.lock);
-
-       pmcmsptwi_set_clock_config(&pmcmsptwi_defclockcfg, &pmcmsptwi_data);
-       pmcmsptwi_set_twi_config(&pmcmsptwi_defcfg, &pmcmsptwi_data);
-
-       printk(KERN_INFO DRV_NAME ": Registering MSP71xx I2C adapter\n");
-
-       pmcmsptwi_adapter.dev.parent = &pldev->dev;
-       platform_set_drvdata(pldev, &pmcmsptwi_adapter);
-       i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data);
-
-       rc = i2c_add_adapter(&pmcmsptwi_adapter);
-       if (rc)
-               goto ret_unmap;
-
-       return 0;
-
-ret_unmap:
-       if (pmcmsptwi_data.irq) {
-               pmcmsptwi_writel(0,
-                       pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET);
-               free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data);
-       }
-
-       iounmap(pmcmsptwi_data.iobase);
-
-ret_unreserve:
-       release_mem_region(res->start, resource_size(res));
-
-ret_err:
-       return rc;
-}
-
-/*
- * Release the device and return 0 if there is one.
- */
-static int pmcmsptwi_remove(struct platform_device *pldev)
-{
-       struct resource *res;
-
-       i2c_del_adapter(&pmcmsptwi_adapter);
-
-       if (pmcmsptwi_data.irq) {
-               pmcmsptwi_writel(0,
-                       pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET);
-               free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data);
-       }
-
-       iounmap(pmcmsptwi_data.iobase);
-
-       res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, resource_size(res));
-
-       return 0;
-}
-
-/*
- * Polls the 'busy' register until the command is complete.
- * NOTE: Assumes data->lock is held.
- */
-static void pmcmsptwi_poll_complete(struct pmcmsptwi_data *data)
-{
-       int i;
-
-       for (i = 0; i < MSP_MAX_POLL; i++) {
-               u32 val = pmcmsptwi_readl(data->iobase +
-                                               MSP_TWI_BUSY_REG_OFFSET);
-               if (val == 0) {
-                       u32 reason = pmcmsptwi_readl(data->iobase +
-                                               MSP_TWI_INT_STS_REG_OFFSET);
-                       pmcmsptwi_writel(reason, data->iobase +
-                                               MSP_TWI_INT_STS_REG_OFFSET);
-                       data->last_result = pmcmsptwi_get_result(reason);
-                       return;
-               }
-               udelay(MSP_POLL_DELAY);
-       }
-
-       dev_dbg(&pmcmsptwi_adapter.dev, "Result: Poll timeout\n");
-       data->last_result = MSP_TWI_XFER_TIMEOUT;
-}
-
-/*
- * Do the transfer (low level):
- *   May use interrupt-driven or polling, depending on if an IRQ is
- *   presently registered.
- * NOTE: Assumes data->lock is held.
- */
-static enum pmcmsptwi_xfer_result pmcmsptwi_do_xfer(
-                       u32 reg, struct pmcmsptwi_data *data)
-{
-       dev_dbg(&pmcmsptwi_adapter.dev, "Writing cmd reg 0x%08x\n", reg);
-       pmcmsptwi_writel(reg, data->iobase + MSP_TWI_CMD_REG_OFFSET);
-       if (data->irq) {
-               unsigned long timeleft = wait_for_completion_timeout(
-                                               &data->wait, MSP_IRQ_TIMEOUT);
-               if (timeleft == 0) {
-                       dev_dbg(&pmcmsptwi_adapter.dev,
-                               "Result: IRQ timeout\n");
-                       complete(&data->wait);
-                       data->last_result = MSP_TWI_XFER_TIMEOUT;
-               }
-       } else
-               pmcmsptwi_poll_complete(data);
-
-       return data->last_result;
-}
-
-/*
- * Helper routine, converts 'pmctwi_cmd' struct to register format
- */
-static inline u32 pmcmsptwi_cmd_to_reg(const struct pmcmsptwi_cmd *cmd)
-{
-       return ((cmd->type & 0x3) << 8) |
-               (((cmd->write_len - 1) & 0x7) << 4) |
-               ((cmd->read_len - 1) & 0x7);
-}
-
-/*
- * Do the transfer (high level)
- */
-static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
-                       struct pmcmsptwi_cmd *cmd,
-                       struct pmcmsptwi_data *data)
-{
-       enum pmcmsptwi_xfer_result retval;
-
-       mutex_lock(&data->lock);
-       dev_dbg(&pmcmsptwi_adapter.dev,
-               "Setting address to 0x%04x\n", cmd->addr);
-       pmcmsptwi_writel(cmd->addr, data->iobase + MSP_TWI_ADD_REG_OFFSET);
-
-       if (cmd->type == MSP_TWI_CMD_WRITE ||
-           cmd->type == MSP_TWI_CMD_WRITE_READ) {
-               u64 tmp = be64_to_cpup((__be64 *)cmd->write_data);
-               tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8;
-               dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp);
-               pmcmsptwi_writel(tmp & 0x00000000ffffffffLL,
-                               data->iobase + MSP_TWI_DAT_0_REG_OFFSET);
-               if (cmd->write_len > 4)
-                       pmcmsptwi_writel(tmp >> 32,
-                               data->iobase + MSP_TWI_DAT_1_REG_OFFSET);
-       }
-
-       retval = pmcmsptwi_do_xfer(pmcmsptwi_cmd_to_reg(cmd), data);
-       if (retval != MSP_TWI_XFER_OK)
-               goto xfer_err;
-
-       if (cmd->type == MSP_TWI_CMD_READ ||
-           cmd->type == MSP_TWI_CMD_WRITE_READ) {
-               int i;
-               u64 rmsk = ~(0xffffffffffffffffLL << (cmd->read_len * 8));
-               u64 tmp = (u64)pmcmsptwi_readl(data->iobase +
-                                       MSP_TWI_DAT_0_REG_OFFSET);
-               if (cmd->read_len > 4)
-                       tmp |= (u64)pmcmsptwi_readl(data->iobase +
-                                       MSP_TWI_DAT_1_REG_OFFSET) << 32;
-               tmp &= rmsk;
-               dev_dbg(&pmcmsptwi_adapter.dev, "Read 0x%016llx\n", tmp);
-
-               for (i = 0; i < cmd->read_len; i++)
-                       cmd->read_data[i] = tmp >> i;
-       }
-
-xfer_err:
-       mutex_unlock(&data->lock);
-
-       return retval;
-}
-
-/* -- Algorithm functions -- */
-
-/*
- * Sends an i2c command out on the adapter
- */
-static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
-                               struct i2c_msg *msg, int num)
-{
-       struct pmcmsptwi_data *data = i2c_get_adapdata(adap);
-       struct pmcmsptwi_cmd cmd;
-       struct pmcmsptwi_cfg oldcfg, newcfg;
-       int ret;
-
-       if (num == 2) {
-               struct i2c_msg *nextmsg = msg + 1;
-
-               cmd.type = MSP_TWI_CMD_WRITE_READ;
-               cmd.write_len = msg->len;
-               cmd.write_data = msg->buf;
-               cmd.read_len = nextmsg->len;
-               cmd.read_data = nextmsg->buf;
-       } else if (msg->flags & I2C_M_RD) {
-               cmd.type = MSP_TWI_CMD_READ;
-               cmd.read_len = msg->len;
-               cmd.read_data = msg->buf;
-               cmd.write_len = 0;
-               cmd.write_data = NULL;
-       } else {
-               cmd.type = MSP_TWI_CMD_WRITE;
-               cmd.read_len = 0;
-               cmd.read_data = NULL;
-               cmd.write_len = msg->len;
-               cmd.write_data = msg->buf;
-       }
-
-       cmd.addr = msg->addr;
-
-       if (msg->flags & I2C_M_TEN) {
-               pmcmsptwi_get_twi_config(&newcfg, data);
-               memcpy(&oldcfg, &newcfg, sizeof(oldcfg));
-
-               /* Set the special 10-bit address flag */
-               newcfg.add10 = 1;
-
-               pmcmsptwi_set_twi_config(&newcfg, data);
-       }
-
-       /* Execute the command */
-       ret = pmcmsptwi_xfer_cmd(&cmd, data);
-
-       if (msg->flags & I2C_M_TEN)
-               pmcmsptwi_set_twi_config(&oldcfg, data);
-
-       dev_dbg(&adap->dev, "I2C %s of %d bytes %s\n",
-               (msg->flags & I2C_M_RD) ? "read" : "write", msg->len,
-               (ret == MSP_TWI_XFER_OK) ? "succeeded" : "failed");
-
-       if (ret != MSP_TWI_XFER_OK) {
-               /*
-                * TODO: We could potentially loop and retry in the case
-                * of MSP_TWI_XFER_TIMEOUT.
-                */
-               return -EIO;
-       }
-
-       return num;
-}
-
-static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
-{
-       return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR |
-               I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
-               I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL;
-}
-
-static const struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = {
-       .flags = I2C_AQ_COMB_WRITE_THEN_READ | I2C_AQ_NO_ZERO_LEN,
-       .max_write_len = MSP_MAX_BYTES_PER_RW,
-       .max_read_len = MSP_MAX_BYTES_PER_RW,
-       .max_comb_1st_msg_len = MSP_MAX_BYTES_PER_RW,
-       .max_comb_2nd_msg_len = MSP_MAX_BYTES_PER_RW,
-};
-
-/* -- Initialization -- */
-
-static const struct i2c_algorithm pmcmsptwi_algo = {
-       .master_xfer    = pmcmsptwi_master_xfer,
-       .functionality  = pmcmsptwi_i2c_func,
-};
-
-static struct i2c_adapter pmcmsptwi_adapter = {
-       .owner          = THIS_MODULE,
-       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
-       .algo           = &pmcmsptwi_algo,
-       .quirks         = &pmcmsptwi_i2c_quirks,
-       .name           = DRV_NAME,
-};
-
-static struct platform_driver pmcmsptwi_driver = {
-       .probe  = pmcmsptwi_probe,
-       .remove = pmcmsptwi_remove,
-       .driver = {
-               .name   = DRV_NAME,
-       },
-};
-
-module_platform_driver(pmcmsptwi_driver);
-
-MODULE_DESCRIPTION("PMC MSP TWI/SMBus/I2C driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
index 61dc20f..fcd35e8 100644 (file)
@@ -778,7 +778,7 @@ static int qup_i2c_bam_schedule_desc(struct qup_i2c_dev *qup)
                        ret = -EINVAL;
 
                        /* abort TX descriptors */
-                       dmaengine_terminate_all(qup->btx.dma);
+                       dmaengine_terminate_sync(qup->btx.dma);
                        goto desc_err;
                }
 
index 4d82761..b49a1b1 100644 (file)
@@ -1137,7 +1137,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
         */
        if (!(i2c->quirks & QUIRK_POLL)) {
                i2c->irq = ret = platform_get_irq(pdev, 0);
-               if (ret <= 0) {
+               if (ret < 0) {
                        dev_err(&pdev->dev, "cannot find IRQ\n");
                        clk_unprepare(i2c->clk);
                        return ret;
index 2d2e630..db8fa41 100644 (file)
@@ -458,9 +458,9 @@ static void sh_mobile_i2c_cleanup_dma(struct sh_mobile_i2c_data *pd)
        if (pd->dma_direction == DMA_NONE)
                return;
        else if (pd->dma_direction == DMA_FROM_DEVICE)
-               dmaengine_terminate_all(pd->dma_rx);
+               dmaengine_terminate_sync(pd->dma_rx);
        else if (pd->dma_direction == DMA_TO_DEVICE)
-               dmaengine_terminate_all(pd->dma_tx);
+               dmaengine_terminate_sync(pd->dma_tx);
 
        sh_mobile_i2c_dma_unmap(pd);
 }
index 2f6f646..9e3483f 100644 (file)
@@ -234,7 +234,7 @@ static int p2wi_probe(struct platform_device *pdev)
        if (IS_ERR(p2wi->regs))
                return PTR_ERR(p2wi->regs);
 
-       strlcpy(p2wi->adapter.name, pdev->name, sizeof(p2wi->adapter.name));
+       strscpy(p2wi->adapter.name, pdev->name, sizeof(p2wi->adapter.name));
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
                return irq;
index 31be181..e4026c5 100644 (file)
@@ -578,7 +578,7 @@ static int synquacer_i2c_probe(struct platform_device *pdev)
 
        i2c->irq = platform_get_irq(pdev, 0);
        if (i2c->irq < 0)
-               return -ENODEV;
+               return i2c->irq;
 
        ret = devm_request_irq(&pdev->dev, i2c->irq, synquacer_i2c_isr,
                               0, dev_name(&pdev->dev), i2c);
diff --git a/drivers/i2c/busses/i2c-virtio.c b/drivers/i2c/busses/i2c-virtio.c
new file mode 100644 (file)
index 0000000..f10a603
--- /dev/null
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Virtio I2C Bus Driver
+ *
+ * The Virtio I2C Specification:
+ * https://raw.githubusercontent.com/oasis-tcs/virtio-spec/master/virtio-i2c.tex
+ *
+ * Copyright (c) 2021 Intel Corporation. All rights reserved.
+ */
+
+#include <linux/acpi.h>
+#include <linux/completion.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_i2c.h>
+
+/**
+ * struct virtio_i2c - virtio I2C data
+ * @vdev: virtio device for this controller
+ * @completion: completion of virtio I2C message
+ * @adap: I2C adapter for this controller
+ * @vq: the virtio virtqueue for communication
+ */
+struct virtio_i2c {
+       struct virtio_device *vdev;
+       struct completion completion;
+       struct i2c_adapter adap;
+       struct virtqueue *vq;
+};
+
+/**
+ * struct virtio_i2c_req - the virtio I2C request structure
+ * @out_hdr: the OUT header of the virtio I2C message
+ * @buf: the buffer into which data is read, or from which it's written
+ * @in_hdr: the IN header of the virtio I2C message
+ */
+struct virtio_i2c_req {
+       struct virtio_i2c_out_hdr out_hdr       ____cacheline_aligned;
+       uint8_t *buf                            ____cacheline_aligned;
+       struct virtio_i2c_in_hdr in_hdr         ____cacheline_aligned;
+};
+
+static void virtio_i2c_msg_done(struct virtqueue *vq)
+{
+       struct virtio_i2c *vi = vq->vdev->priv;
+
+       complete(&vi->completion);
+}
+
+static int virtio_i2c_prepare_reqs(struct virtqueue *vq,
+                                  struct virtio_i2c_req *reqs,
+                                  struct i2c_msg *msgs, int num)
+{
+       struct scatterlist *sgs[3], out_hdr, msg_buf, in_hdr;
+       int i;
+
+       for (i = 0; i < num; i++) {
+               int outcnt = 0, incnt = 0;
+
+               /*
+                * We don't support 0 length messages and so filter out
+                * 0 length transfers by using i2c_adapter_quirks.
+                */
+               if (!msgs[i].len)
+                       break;
+
+               /*
+                * Only 7-bit mode supported for this moment. For the address
+                * format, Please check the Virtio I2C Specification.
+                */
+               reqs[i].out_hdr.addr = cpu_to_le16(msgs[i].addr << 1);
+
+               if (i != num - 1)
+                       reqs[i].out_hdr.flags = cpu_to_le32(VIRTIO_I2C_FLAGS_FAIL_NEXT);
+
+               sg_init_one(&out_hdr, &reqs[i].out_hdr, sizeof(reqs[i].out_hdr));
+               sgs[outcnt++] = &out_hdr;
+
+               reqs[i].buf = i2c_get_dma_safe_msg_buf(&msgs[i], 1);
+               if (!reqs[i].buf)
+                       break;
+
+               sg_init_one(&msg_buf, reqs[i].buf, msgs[i].len);
+
+               if (msgs[i].flags & I2C_M_RD)
+                       sgs[outcnt + incnt++] = &msg_buf;
+               else
+                       sgs[outcnt++] = &msg_buf;
+
+               sg_init_one(&in_hdr, &reqs[i].in_hdr, sizeof(reqs[i].in_hdr));
+               sgs[outcnt + incnt++] = &in_hdr;
+
+               if (virtqueue_add_sgs(vq, sgs, outcnt, incnt, &reqs[i], GFP_KERNEL)) {
+                       i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], false);
+                       break;
+               }
+       }
+
+       return i;
+}
+
+static int virtio_i2c_complete_reqs(struct virtqueue *vq,
+                                   struct virtio_i2c_req *reqs,
+                                   struct i2c_msg *msgs, int num,
+                                   bool timedout)
+{
+       struct virtio_i2c_req *req;
+       bool failed = timedout;
+       unsigned int len;
+       int i, j = 0;
+
+       for (i = 0; i < num; i++) {
+               /* Detach the ith request from the vq */
+               req = virtqueue_get_buf(vq, &len);
+
+               /*
+                * Condition req == &reqs[i] should always meet since we have
+                * total num requests in the vq. reqs[i] can never be NULL here.
+                */
+               if (!failed && (WARN_ON(req != &reqs[i]) ||
+                               req->in_hdr.status != VIRTIO_I2C_MSG_OK))
+                       failed = true;
+
+               i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed);
+
+               if (!failed)
+                       j++;
+       }
+
+       return timedout ? -ETIMEDOUT : j;
+}
+
+static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+                          int num)
+{
+       struct virtio_i2c *vi = i2c_get_adapdata(adap);
+       struct virtqueue *vq = vi->vq;
+       struct virtio_i2c_req *reqs;
+       unsigned long time_left;
+       int count;
+
+       reqs = kcalloc(num, sizeof(*reqs), GFP_KERNEL);
+       if (!reqs)
+               return -ENOMEM;
+
+       count = virtio_i2c_prepare_reqs(vq, reqs, msgs, num);
+       if (!count)
+               goto err_free;
+
+       /*
+        * For the case where count < num, i.e. we weren't able to queue all the
+        * msgs, ideally we should abort right away and return early, but some
+        * of the messages are already sent to the remote I2C controller and the
+        * virtqueue will be left in undefined state in that case. We kick the
+        * remote here to clear the virtqueue, so we can try another set of
+        * messages later on.
+        */
+
+       reinit_completion(&vi->completion);
+       virtqueue_kick(vq);
+
+       time_left = wait_for_completion_timeout(&vi->completion, adap->timeout);
+       if (!time_left)
+               dev_err(&adap->dev, "virtio i2c backend timeout.\n");
+
+       count = virtio_i2c_complete_reqs(vq, reqs, msgs, count, !time_left);
+
+err_free:
+       kfree(reqs);
+       return count;
+}
+
+static void virtio_i2c_del_vqs(struct virtio_device *vdev)
+{
+       vdev->config->reset(vdev);
+       vdev->config->del_vqs(vdev);
+}
+
+static int virtio_i2c_setup_vqs(struct virtio_i2c *vi)
+{
+       struct virtio_device *vdev = vi->vdev;
+
+       vi->vq = virtio_find_single_vq(vdev, virtio_i2c_msg_done, "msg");
+       return PTR_ERR_OR_ZERO(vi->vq);
+}
+
+static u32 virtio_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+}
+
+static struct i2c_algorithm virtio_algorithm = {
+       .master_xfer = virtio_i2c_xfer,
+       .functionality = virtio_i2c_func,
+};
+
+static const struct i2c_adapter_quirks virtio_i2c_quirks = {
+       .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
+static int virtio_i2c_probe(struct virtio_device *vdev)
+{
+       struct virtio_i2c *vi;
+       int ret;
+
+       vi = devm_kzalloc(&vdev->dev, sizeof(*vi), GFP_KERNEL);
+       if (!vi)
+               return -ENOMEM;
+
+       vdev->priv = vi;
+       vi->vdev = vdev;
+
+       init_completion(&vi->completion);
+
+       ret = virtio_i2c_setup_vqs(vi);
+       if (ret)
+               return ret;
+
+       vi->adap.owner = THIS_MODULE;
+       snprintf(vi->adap.name, sizeof(vi->adap.name),
+                "i2c_virtio at virtio bus %d", vdev->index);
+       vi->adap.algo = &virtio_algorithm;
+       vi->adap.quirks = &virtio_i2c_quirks;
+       vi->adap.dev.parent = &vdev->dev;
+       vi->adap.dev.of_node = vdev->dev.of_node;
+       i2c_set_adapdata(&vi->adap, vi);
+
+       /*
+        * Setup ACPI node for controlled devices which will be probed through
+        * ACPI.
+        */
+       ACPI_COMPANION_SET(&vi->adap.dev, ACPI_COMPANION(vdev->dev.parent));
+
+       ret = i2c_add_adapter(&vi->adap);
+       if (ret)
+               virtio_i2c_del_vqs(vdev);
+
+       return ret;
+}
+
+static void virtio_i2c_remove(struct virtio_device *vdev)
+{
+       struct virtio_i2c *vi = vdev->priv;
+
+       i2c_del_adapter(&vi->adap);
+       virtio_i2c_del_vqs(vdev);
+}
+
+static struct virtio_device_id id_table[] = {
+       { VIRTIO_ID_I2C_ADAPTER, VIRTIO_DEV_ANY_ID },
+       {}
+};
+MODULE_DEVICE_TABLE(virtio, id_table);
+
+#ifdef CONFIG_PM_SLEEP
+static int virtio_i2c_freeze(struct virtio_device *vdev)
+{
+       virtio_i2c_del_vqs(vdev);
+       return 0;
+}
+
+static int virtio_i2c_restore(struct virtio_device *vdev)
+{
+       return virtio_i2c_setup_vqs(vdev->priv);
+}
+#endif
+
+static struct virtio_driver virtio_i2c_driver = {
+       .id_table       = id_table,
+       .probe          = virtio_i2c_probe,
+       .remove         = virtio_i2c_remove,
+       .driver = {
+               .name   = "i2c_virtio",
+       },
+#ifdef CONFIG_PM_SLEEP
+       .freeze = virtio_i2c_freeze,
+       .restore = virtio_i2c_restore,
+#endif
+};
+module_virtio_driver(virtio_i2c_driver);
+
+MODULE_AUTHOR("Jie Deng <jie.deng@intel.com>");
+MODULE_AUTHOR("Conghui Chen <conghui.chen@intel.com>");
+MODULE_DESCRIPTION("Virtio i2c bus driver");
+MODULE_LICENSE("GPL");
index f2241ce..6d24dc3 100644 (file)
@@ -517,7 +517,7 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
                return PTR_ERR(priv->base);
 
        priv->irq = platform_get_irq(pdev, 0);
-       if (priv->irq <= 0)
+       if (priv->irq < 0)
                return priv->irq;
        /* SMBAlert irq */
        priv->alert_data.irq = platform_get_irq(pdev, 1);
index 77f576e..bce0e8b 100644 (file)
@@ -14,6 +14,8 @@
 
 /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
 
+#define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
+
 #include <linux/cdev.h>
 #include <linux/compat.h>
 #include <linux/device.h>
@@ -68,8 +70,7 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
        struct i2c_dev *i2c_dev;
 
        if (adap->nr >= I2C_MINORS) {
-               printk(KERN_ERR "i2c-dev: Out of device minors (%d)\n",
-                      adap->nr);
+               pr_err("Out of device minors (%d)\n", adap->nr);
                return ERR_PTR(-ENODEV);
        }
 
@@ -101,7 +102,7 @@ static ssize_t name_show(struct device *dev,
 
        if (!i2c_dev)
                return -ENODEV;
-       return sprintf(buf, "%s\n", i2c_dev->adap->name);
+       return sysfs_emit(buf, "%s\n", i2c_dev->adap->name);
 }
 static DEVICE_ATTR_RO(name);
 
@@ -145,8 +146,7 @@ static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count,
        if (tmp == NULL)
                return -ENOMEM;
 
-       pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n",
-               iminor(file_inode(file)), count);
+       pr_debug("i2c-%d reading %zu bytes.\n", iminor(file_inode(file)), count);
 
        ret = i2c_master_recv(client, tmp, count);
        if (ret >= 0)
@@ -170,8 +170,7 @@ static ssize_t i2cdev_write(struct file *file, const char __user *buf,
        if (IS_ERR(tmp))
                return PTR_ERR(tmp);
 
-       pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n",
-               iminor(file_inode(file)), count);
+       pr_debug("i2c-%d writing %zu bytes.\n", iminor(file_inode(file)), count);
 
        ret = i2c_master_send(client, tmp, count);
        kfree(tmp);
@@ -674,8 +673,7 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
                return res;
        }
 
-       pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
-                adap->name, adap->nr);
+       pr_debug("adapter [%s] registered as minor %d\n", adap->name, adap->nr);
        return 0;
 }
 
@@ -694,7 +692,7 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
 
        put_i2c_dev(i2c_dev, true);
 
-       pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
+       pr_debug("adapter [%s] unregistered\n", adap->name);
        return 0;
 }
 
@@ -727,7 +725,7 @@ static int __init i2c_dev_init(void)
 {
        int res;
 
-       printk(KERN_INFO "i2c /dev entries driver\n");
+       pr_info("i2c /dev entries driver\n");
 
        res = register_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS, "i2c");
        if (res)
@@ -755,7 +753,7 @@ out_unreg_class:
 out_unreg_chrdev:
        unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
 out:
-       printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);
+       pr_err("Driver Initialisation failed\n");
        return res;
 }
 
index dcc30a5..4a25e0c 100644 (file)
@@ -4,6 +4,22 @@
 
 #include <linux/math.h>
 
+/* Metric prefixes in accordance with Système international (d'unités) */
+#define PETA   1000000000000000ULL
+#define TERA   1000000000000ULL
+#define GIGA   1000000000UL
+#define MEGA   1000000UL
+#define KILO   1000UL
+#define HECTO  100UL
+#define DECA   10UL
+#define DECI   10UL
+#define CENTI  100UL
+#define MILLI  1000UL
+#define MICRO  1000000UL
+#define NANO   1000000000UL
+#define PICO   1000000000000ULL
+#define FEMTO  1000000000000000ULL
+
 #define MILLIWATT_PER_WATT     1000L
 #define MICROWATT_PER_MILLIWATT        1000L
 #define MICROWATT_PER_WATT     1000000L
diff --git a/include/uapi/linux/virtio_i2c.h b/include/uapi/linux/virtio_i2c.h
new file mode 100644 (file)
index 0000000..7c6a6fc
--- /dev/null
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */
+/*
+ * Definitions for virtio I2C Adpter
+ *
+ * Copyright (c) 2021 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _UAPI_LINUX_VIRTIO_I2C_H
+#define _UAPI_LINUX_VIRTIO_I2C_H
+
+#include <linux/const.h>
+#include <linux/types.h>
+
+/* The bit 0 of the @virtio_i2c_out_hdr.@flags, used to group the requests */
+#define VIRTIO_I2C_FLAGS_FAIL_NEXT     _BITUL(0)
+
+/**
+ * struct virtio_i2c_out_hdr - the virtio I2C message OUT header
+ * @addr: the controlled device address
+ * @padding: used to pad to full dword
+ * @flags: used for feature extensibility
+ */
+struct virtio_i2c_out_hdr {
+       __le16 addr;
+       __le16 padding;
+       __le32 flags;
+};
+
+/**
+ * struct virtio_i2c_in_hdr - the virtio I2C message IN header
+ * @status: the processing result from the backend
+ */
+struct virtio_i2c_in_hdr {
+       __u8 status;
+};
+
+/* The final status written by the device */
+#define VIRTIO_I2C_MSG_OK      0
+#define VIRTIO_I2C_MSG_ERR     1
+
+#endif /* _UAPI_LINUX_VIRTIO_I2C_H */
index 70a8057..99aa27b 100644 (file)
@@ -55,6 +55,7 @@
 #define VIRTIO_ID_FS                   26 /* virtio filesystem */
 #define VIRTIO_ID_PMEM                 27 /* virtio pmem */
 #define VIRTIO_ID_MAC80211_HWSIM       29 /* virtio mac80211-hwsim */
+#define VIRTIO_ID_I2C_ADAPTER          34 /* virtio i2c adapter */
 #define VIRTIO_ID_BT                   40 /* virtio bluetooth */
 
 /*