All of lore.kernel.org
 help / color / mirror / Atom feed
* Questions for submitting driver to I2C subsystem
@ 2009-04-15 14:23 Wang, Wen W
       [not found] ` <0A882F4D99BBF6449D58E61AAFD7EDD610424EB0-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Wang, Wen W @ 2009-04-15 14:23 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA

Hi all,

I'm Wen working on Linux driver for Intel MID platform. I have a couple of questions on submitting drivers into I2C tree. Can you please help on that?

I'm writing Linux I2C controller driver for Intel low power platform of MID. It has been accepted by Moblin and I'm planning to submit this driver to upstream.

1. Is it ok if I submit this I2C driver with specific platform codes in driver?
2. How should I submit this I2C driver if it is dependent on another device driver which is also out of kernel tree?

I can send the driver patch for your preview if it is ok.

Thanks
Wen

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Questions for submitting driver to I2C subsystem
       [not found] ` <0A882F4D99BBF6449D58E61AAFD7EDD610424EB0-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2009-04-16  9:14   ` Jean Delvare
       [not found]     ` <20090416111436.296cdd12-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
                       ` (2 more replies)
  0 siblings, 3 replies; 26+ messages in thread
From: Jean Delvare @ 2009-04-16  9:14 UTC (permalink / raw)
  To: Wang, Wen W; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

Hi Wen,

On Wed, 15 Apr 2009 22:23:39 +0800, Wang, Wen W wrote:
> Hi all,
> 
> I'm Wen working on Linux driver for Intel MID platform. I have a couple of questions on submitting drivers into I2C tree. Can you please help on that?
> 
> I'm writing Linux I2C controller driver for Intel low power platform of MID. It has been accepted by Moblin and I'm planning to submit this driver to upstream.
> 
> 1. Is it ok if I submit this I2C driver with specific platform codes in driver?

I'm not sure exactly what you mean by "specific platform codes".
Probably the best is that you post your code and we'll see what code
this is.

> 2. How should I submit this I2C driver if it is dependent on another device driver which is also out of kernel tree?

You can always post your code early even if it can't be used
immediately. Just make sure you tell what the dependencies are.

After your code has been reviewed, when it is finally ready to be
merged, then of course we will ask you to first push all the
dependencies upstream, before we (most likely Ben) can push your code to
Linus.

> I can send the driver patch for your preview if it is ok.

Please do.

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]     ` <20090416111436.296cdd12-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2009-04-23  9:00       ` Wang, Wen W
       [not found]         ` <0A882F4D99BBF6449D58E61AAFD7EDD6136779F1-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Wang, Wen W @ 2009-04-23  9:00 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

Hi Jean,

This is a description for the patch:
1. Patch for I2C controller driver for Intel low power platform "Moorestown".
2. The driver depends on a GPIO driver for Intel Moorestown platform.
3. The patch will:
	a. Add i2c_mrst.c and i2c_mrst.h to kernel directory "drivers/i2c/busses"
	b. Add items into kernel files "drivers/i2c/busses/Kconfig" and "drivers/i2c/Makefile".
	c. Modify i2c-boardinfo.c to export i2c_register_board_info() function and add code to detect if a device is already in i2c_board_list.

Thanks
Wen

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/1] I2C: I2C controller driver for Intel Moorestown platform
  2009-04-16  9:14   ` Jean Delvare
       [not found]     ` <20090416111436.296cdd12-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2009-04-23  9:04     ` Wang, Wen W
  2009-04-23 10:19     ` [PATCH 0/2] " Wang, Wen W
  2 siblings, 0 replies; 26+ messages in thread
From: Wang, Wen W @ 2009-04-23  9:04 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Wang, Wen W

From a173c9ea843a85d83e003894c03a9378c20d6862 Mon Sep 17 00:00:00 2001
From: Wen Wang <wen.w.wang@intel.com>
Date: Thu, 23 Apr 2009 16:16:25 +0800
Subject: [PATCH] Moorestown I2C controller driver
 Signed-off-by: Wen Wang <wen.w.wang@intel.com>

---
 drivers/i2c/busses/Kconfig    |   10 +
 drivers/i2c/busses/Makefile   |    1 +
 drivers/i2c/busses/i2c-mrst.c |  973 +++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/busses/i2c-mrst.h |  279 ++++++++++++
 drivers/i2c/i2c-boardinfo.c   |   36 +-
 5 files changed, 1288 insertions(+), 11 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-mrst.c
 create mode 100755 drivers/i2c/busses/i2c-mrst.h

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index a48c8ae..cfd3528 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -738,4 +738,14 @@ config SCx200_ACB
          This support is also available as a module.  If so, the module
          will be called scx200_acb.

+config I2C_MRST
+       tristate "Intel Moorestown I2C Controller"
+       depends on PCI && GPIOLIB
+       default y
+       help
+         If you say yes to this option, support will be included for the Intel
+         Moorestown chipset I2C controller.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-mrst.
+
 endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 776acb6..e11fd0f 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_I2C_SIBYTE)      += i2c-sibyte.o
 obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
+obj-$(CONFIG_I2C_MRST)         += i2c-mrst.o

 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/busses/i2c-mrst.c b/drivers/i2c/busses/i2c-mrst.c
new file mode 100644
index 0000000..c93ff30
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mrst.c
@@ -0,0 +1,973 @@
+/*
+ * Support for Moorestown I2C controller
+ *
+ * Copyright (c) 2009 Intel Corporation.
+ * Copyright (c) 2009 Synopsys. Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License, version
+ * 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+
+#include <linux/io.h>
+
+#include "i2c-mrst.h"
+
+#define MAX_T_POLL_COUNT       4000    /* FIXME */
+#define DEF_BAR                0
+#define VERSION                "Version 0.5"
+
+#define mrst_i2c_read(reg)             __raw_readl(reg)
+#define mrst_i2c_write(reg, val)       __raw_writel((val), (reg))
+
+static int speed_mode = STANDARD;
+module_param(speed_mode, int, S_IRUGO);
+
+/**
+ * mrst_i2c_register_board_info - Register I2C device info
+ * @dev: struct pointer to pci_dev
+ * @busnum: Bus number to register
+ *
+ * Return Value:
+ * 0           success
+ * -ENOMEM     if fail to allocate memory
+ * -ENODEV     if fail to detect the address of I2C device info table
+ *
+ * Moorestown I2C device info table is initialized by firmware and the address
+ * pointer is filled into I2C controller PCI config space BAR 1.
+ *
+ * Driver will read this table from memory and register this device table into
+ * I2C core.
+ */
+static int mrst_i2c_register_board_info(struct pci_dev *dev, int busnum)
+{
+       struct mrst_i2c_private *mrst = (struct mrst_i2c_private *)
+                                       pci_get_drvdata(dev);
+       int err;
+       unsigned short addr, irq, host;
+       char *name = NULL;
+       struct i2c_board_info *info = NULL;
+       unsigned int addr_off, irq_off, name_off, data_off, host_off;
+       unsigned int table_len, block_num, block = 0;
+       int i, j;
+       unsigned int start, len;
+       void __iomem *base = NULL, *ptr = NULL;
+
+       /* Determine the address of the I2C device info table area */
+       start = pci_resource_start(dev, 1);
+       len = pci_resource_len(dev, 1);
+       if (!start || len <= 0) {
+               err = -ENODEV;
+               return err;
+       }
+
+       err = pci_request_region(dev, 1, "mrst_i2c");
+       if (err) {
+               dev_err(&dev->dev, "Failed to request I2C region "
+                       "0x%1x-0x%Lx\n", start,
+                       (unsigned long long)pci_resource_end(dev, 1));
+               return err;
+       }
+
+       ptr = ioremap(start, len);
+       if (!ptr) {
+               dev_err(&dev->dev, "I/O memory remapping failed\n");
+               err = -ENOMEM;
+               goto err0;
+       }
+
+       /*
+        * Detect if an old firmware is used.
+        * Newer firmware is using two levels pointer to the device info table
+        */
+       if (len == 8) {
+               start = ioread32(ptr);
+               len = ioread32(ptr + 4);
+               iounmap(ptr);
+               base = ioremap(start, len);
+       } else
+               base = ptr;
+
+       /* Initialization */
+       name = kzalloc(sizeof(char) * NAME_LENGTH, GFP_KERNEL);
+       if (name == NULL) {
+               err = -ENOMEM;
+               goto err1;
+       }
+
+       info = kzalloc(sizeof(struct i2c_board_info), GFP_KERNEL);
+       if (info == NULL) {
+               dev_err(&dev->dev,
+                       "Can't allocate interface for i2c_board_info\n");
+               err = -ENOMEM;
+               goto err2;
+       }
+
+       /* Get I2C info table length */
+       table_len = ioread32(base + I2C_INFO_TABLE_LENGTH);
+
+       /* Calculate the number of I2C device */
+       block_num = (table_len - HEAD_LENGTH)/BLOCK_LENGTH;
+       if (!block_num)
+               /* No I2C device info */
+               goto err3;
+
+       /* Initialize mrst_i2c_info array */
+       mrst->mrst_i2c_info = kzalloc(sizeof(struct i2c_board_info) *
+                                     block_num, GFP_KERNEL);
+       if (mrst->mrst_i2c_info == NULL) {
+               dev_err(&dev->dev,
+                       "Can't allocate interface for i2c_board_info\n");
+               err = -ENOMEM;
+               goto err3;
+       }
+
+       mrst->data = kzalloc(sizeof(*mrst->data) * block_num, GFP_KERNEL);
+       if (mrst->data == NULL) {
+               dev_err(&dev->dev,
+                       "Can't allocate interface for per device data\n");
+               err = -ENOMEM;
+               goto err4;
+       }
+
+       for (i = 0; i < block_num; i++) {
+               /* I2C device info block offsets */
+               host_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i;
+               addr_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i + I2C_DEV_ADDR;
+               irq_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i + I2C_DEV_IRQ;
+               name_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i + I2C_DEV_NAME;
+               data_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i + I2C_DEV_INFO;
+
+               /* Read PCI config table */
+               host = ioread16(base + host_off);
+               if (host != busnum)
+                       continue;
+               addr = ioread16(base + addr_off);
+               irq = ioread16(base + irq_off);
+               for (j = 0; j < NAME_LENGTH; j++)
+                       name[j] = ioread8(base + name_off + j);
+
+               for (j = 0; j < INFO_LENGTH; j++)
+                       mrst->data[i][j] = ioread8(base + data_off + j);
+               dev_dbg(&dev->dev, "I2C device info table: name = %s, address ="
+                       " %x\n", name, addr);
+
+               /* Fill in i2c_board_info struct */
+               memcpy(info->type, name, NAME_LENGTH);
+               info->platform_data = mrst->data[i];
+               info->addr = addr;
+               info->irq = irq;
+
+               /* Add to mrst_i2c_info array */
+               memcpy(mrst->mrst_i2c_info + block, info,
+                      sizeof(struct i2c_board_info));
+               block++;
+       }
+
+       /* Register i2c board info */
+       err = i2c_register_board_info(busnum, mrst->mrst_i2c_info, block);
+       goto err3;
+
+/* Clean up */
+err4:
+       kfree(mrst->mrst_i2c_info);
+err3:
+       kfree(info);
+err2:
+       kfree(name);
+err1:
+       iounmap(base);
+err0:
+       pci_release_region(dev, 1);
+       return err;
+}
+
+/**
+ * mrst_i2c_disable - Disable I2C controller
+ * @adap: struct pointer to i2c_adapter
+ *
+ * Return Value:
+ * 0           success
+ * -EBUSY      if device is busy
+ * -ETIMEOUT   if i2c cannot be disabled within the given time
+ *
+ * I2C bus state should be checked prior to disabling the hardware. If bus is
+ * not in idle state, an errno is returned. Write "0" to IC_ENABLE to disable
+ * I2C controller.
+ */
+static int mrst_i2c_disable(struct i2c_adapter *adap)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)i2c_get_adapdata(adap);
+
+       int count = 0;
+
+       /* Check if device is busy */
+       dev_dbg(&adap->dev, "mrst i2c disable\n");
+       while (mrst_i2c_read(i2c->base + IC_STATUS) & 0x1) {
+               dev_dbg(&adap->dev, "i2c is busy, count is %d\n", count);
+               if (count++ > 10000)
+                       return -EBUSY;
+       }
+
+       /* Set IC_ENABLE to 0 */
+       mrst_i2c_write(i2c->base + IC_ENABLE, 0);
+
+       /* Disable all interupts */
+       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
+
+       /* Clear all interrupts */
+       mrst_i2c_read(i2c->base + IC_CLR_INTR);
+
+       return 0;
+}
+
+/**
+ * mrst_i2c_hwinit - Initiate the I2C hardware registers. This function will
+ * be called in mrst_i2c_probe() before device registration.
+ * @dev: pci device struct pointer
+ *
+ * Return Values:
+ * 0           success
+ * -EBUSY      i2c cannot be disabled
+ * -ETIMEDOUT  i2c cannot be disabled
+ * -EFAULT     If APB data width is not 32-bit wide
+ *
+ * I2C should be disabled prior to other register operation. If failed, an
+ * errno is returned. Mask and Clear all interrpts, this should be done at
+ * first.  Set common registers which will not be modified during normal
+ * transfers, including: controll register, FIFO threshold and clock freq.
+ * Check APB data width at last.
+ */
+static int  __devinit mrst_i2c_hwinit(struct pci_dev *dev)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)pci_get_drvdata(dev);
+       int err = 0;
+
+       /* Disable i2c first */
+       err = mrst_i2c_disable(i2c->adap);
+       if (err)
+               return err;
+
+       /* Disable all interupts */
+       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
+
+       /* Clear all interrupts */
+       mrst_i2c_read(i2c->base + IC_CLR_INTR);
+
+       /*
+        * Setup clock frequency and speed mode
+        * Enable restart condition,
+        * enable master FSM, disable slave FSM,
+        * use target address when initiating transfer
+        */
+       switch (speed_mode) {
+       case STANDARD:
+               mrst_i2c_write(i2c->base + IC_CON,
+                              SLV_DIS | RESTART | STANDARD_MODE | MASTER_EN);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x75);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x7c);
+               break;
+       case FAST:
+               mrst_i2c_write(i2c->base + IC_CON,
+                              SLV_DIS | RESTART | FAST_MODE | MASTER_EN);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x15);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x21);
+               break;
+       case HIGH:
+               mrst_i2c_write(i2c->base + IC_CON,
+                              SLV_DIS | RESTART | HIGH_MODE | MASTER_EN);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x7);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0xE);
+               break;
+       default:
+               ;
+       }
+
+       /* Set tranmit & receive FIFO threshold to zero */
+       mrst_i2c_write(i2c->base + IC_RX_TL, 0x3);
+       mrst_i2c_write(i2c->base + IC_TX_TL, 0x3);
+
+       mrst_i2c_write(i2c->base + IC_ENABLE, 1);
+
+       return err;
+}
+
+/**
+ * mrst_i2c_func - Return the supported three I2C operations.
+ * @adapter: i2c_adapter struct pointer
+ */
+static u32 mrst_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
+}
+
+/**
+ * mrst_i2c_invalid_address - To check if the address in i2c message is
+ * correct.
+ * @p: i2c_msg struct pointer
+ *
+ * Return Values:
+ * 0   if the address is valid
+ * 1   if the address is invalid
+ */
+static inline int mrst_i2c_invalid_address(const struct i2c_msg *p)
+{
+       int ret = ((p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN)
+                                        && (p->addr > 0x7f)));
+       return ret;
+}
+
+/**
+ * mrst_i2c_address_neq - To check if the addresses for different i2c messages
+ * are equal.
+ * @p1: first i2c_msg
+ * @p2: second i2c_msg
+ *
+ * Return Values:
+ * 0    if addresse are equal
+ * 1    if not equal
+ *
+ * Within a single transfer, I2C client may need to send its address more
+ * than one time. So a check for the address equation is needed.
+ */
+static inline int mrst_i2c_address_neq(const struct i2c_msg *p1,
+                                      const struct i2c_msg *p2)
+{
+       int ret = ((p1->addr != p2->addr) || ((p1->flags & (I2C_M_TEN))
+                                             != ((p2->flags) & (I2C_M_TEN))));
+       return ret;
+}
+
+/**
+ * mrst_i2c_abort - To handle transfer abortions and print error messages.
+ * @adap: i2c_adapter struct pointer
+ *
+ * By reading register IC_TX_ABRT_SOURCE, various transfer errors can be
+ * distingushed. At present, no circumstances have been found out that
+ * multiple errors would be occured simutaneously, so we simply use the
+ * register value directly.
+ *
+ * At last the error bits are cleared. (Note clear ABRT_SBYTE_NORSTRT bit need
+ * a few extra steps)
+ */
+static void mrst_i2c_abort(struct i2c_adapter *adap)
+{
+       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
+           i2c_get_adapdata(adap);
+
+       /* Read about source register */
+       int abort = mrst_i2c_read(i2c->base + IC_TX_ABRT_SOURCE);
+
+       dev_dbg(&adap->dev, "Abort: ");
+
+       /* Single transfer error check:
+        * According to databook, TX/RX FIFOs would be flushed when
+        * the abort interrupt occured.
+        */
+       switch (abort) {
+       case (ABRT_MASTER_DIS):
+               dev_err(&adap->dev,
+                       "initiate Master operation with Master mode"
+                       "disabled.\n");
+
+               break;
+       case (ABRT_10B_RD_NORSTRT):
+               dev_err(&adap->dev,
+                       "RESTART disabled and master sends READ cmd in 10-BIT"
+                       "addressing.\n");
+               break;
+       case (ABRT_SBYTE_NORSTRT):
+               dev_err(&adap->dev,
+                       "RESTART disabled and user is trying to send START"
+                       "byte.\n");
+               /* Page 141 data book */
+               mrst_i2c_write(i2c->base + IC_TX_ABRT_SOURCE,
+                              !(ABRT_SBYTE_NORSTRT));
+               mrst_i2c_write(i2c->base + IC_CON, RESTART);
+               mrst_i2c_write(i2c->base + IC_TAR, !(IC_TAR_SPECIAL));
+               break;
+       case (ABRT_SBYTE_ACKDET):
+               dev_err(&adap->dev,
+                       "START byte was acknowledged.\n");
+               break;
+       case (ABRT_TXDATA_NOACK):
+               dev_err(&adap->dev,
+                       "No acknowledge received from slave.\n");
+               break;
+       case (ABRT_10ADDR2_NOACK):
+               dev_err(&adap->dev,
+                       "The 2nd address byte of 10-bit address not"
+                       "acknowledged.\n");
+               break;
+       case (ABRT_10ADDR1_NOACK):
+               dev_dbg(&adap->dev,
+                       "The 1st address byte of 10-bit address not"
+                       "acknowledged.\n");
+               break;
+       case (ABRT_7B_ADDR_NOACK):
+               dev_err(&adap->dev,
+                       "7-bit address not acknowledged.\n");
+               break;
+       default:
+               ;;
+       }
+
+       /* Clear TX_ABRT bit */
+       mrst_i2c_read(i2c->base + IC_CLR_TX_ABRT);
+}
+
+/**
+ * xfer_read - Internal function to implement master read transfer.
+ * @adap: i2c_adapter struct pointer
+ * @buf: buffer in i2c_msg
+ * @length: number of bytes to be read
+ *
+ * Return Values:
+ * 0           if the read transfer succeeds
+ * -ETIMEDOUT  if cannot read the "raw" interrupt register
+ * -EINVAL     if transfer abort occured
+ *
+ * For every byte, a "READ" command will be loaded into IC_DATA_CMD prior to
+ * data transfer. The actual "read" operation will be performed if the RX_FULL
+ * interrupt is occured.
+ *
+ * Note there may be two interrupt signals captured, one should read
+ * IC_RAW_INTR_STAT to seperate between errors and actual data.
+ */
+static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
+           i2c_get_adapdata(adap);
+       uint32_t reg_val;
+       int i = length;
+       unsigned count = 0;
+       uint32_t bit_get = 1 << 3; /* receive fifo not empty */
+
+       while (i--)
+               mrst_i2c_write(i2c->base + IC_DATA_CMD, (uint16_t)0x100);
+
+       i = length;
+       while (i--) {
+               count = 0;
+               reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+               while ((reg_val & bit_get) == 0) {
+                       reg_val = mrst_i2c_read(i2c->base + IC_RAW_INTR_STAT);
+                       if ((reg_val & 0x40) == 0x40)
+                               goto read_abrt;
+                       reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+                       if (count++ > MAX_T_POLL_COUNT)
+                               goto read_loop;
+               }
+
+               reg_val = mrst_i2c_read(i2c->base + IC_DATA_CMD);
+               *buf++ = reg_val;
+       }
+
+       return 0;
+
+read_loop:
+       dev_err(&adap->dev, "Time out in read\n");
+       return -ETIMEDOUT;
+read_abrt:
+       dev_err(&adap->dev, "Abort from read\n");
+       mrst_i2c_abort(adap);
+       return -EINVAL;
+}
+
+/**
+ * xfer_write - Internal function to implement master write transfer.
+ * @adap: i2c_adapter struct pointer
+ * @buf: buffer in i2c_msg
+ * @length: number of bytes to be read
+ *
+ * Return Values:
+ * 0   if the read transfer succeeds
+ * -ETIMEDOUT  if cannot read the "raw" interrupt register
+ * -EINVAL     if transfer abort occured
+ *
+ * For every byte, a "WRITE" command will be loaded into IC_DATA_CMD prior to
+ * data transfer. The actual "write" operation will be performed if the
+ * RX_FULL interrupt siganal is occured.
+ *
+ * Note there may be two interrupt signals captured, one should read
+ * IC_RAW_INTR_STAT to seperate between errors and actual data.
+ */
+static int xfer_write(struct i2c_adapter *adap,
+                     unsigned char *buf, int length)
+{
+       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
+           i2c_get_adapdata(adap);
+
+       int i;
+       uint32_t reg_val;
+       unsigned count = 0;
+       uint32_t bit_get = 1 << 2; /* transmit fifo completely empty */
+
+       for (i = 0; i < length; i++)
+               mrst_i2c_write(i2c->base + IC_DATA_CMD,
+                              (uint16_t)(*(buf + i)));
+
+       reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+       while ((reg_val & bit_get) == 0) {
+               if (count++ > MAX_T_POLL_COUNT)
+                       goto write_loop;
+               reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+       }
+
+       udelay(100);
+       reg_val = mrst_i2c_read(i2c->base + IC_RAW_INTR_STAT);
+       if ((reg_val & 0x40) == 0x40)
+               goto write_abrt;
+
+       return 0;
+
+write_loop:
+       dev_err(&adap->dev, "Time out in write\n");
+       return -ETIMEDOUT;
+write_abrt:
+       dev_err(&adap->dev, "Abort from write\n");
+       mrst_i2c_abort(adap);
+       return -EINVAL;
+}
+
+static int mrst_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)i2c_get_adapdata(adap);
+       int err;
+       uint32_t reg_val;
+       uint32_t bit_mask;
+
+       /* Disable device first */
+       err = mrst_i2c_disable(adap);
+       if (err) {
+               dev_err(&adap->dev,
+                       "Cannot disable i2c controller, timeout!\n");
+               return -ETIMEDOUT;
+       }
+
+
+       reg_val = mrst_i2c_read(i2c->base + IC_ENABLE);
+       if (reg_val & 0x1) {
+               dev_dbg(&adap->dev, "i2c busy, can't setup\n");
+               return -EINVAL;
+       }
+
+       /* set the speed mode to standard */
+       reg_val = mrst_i2c_read(i2c->base + IC_CON);
+       if ((reg_val & (1<<1 | 1<<2)) != 1<<1) {
+               dev_dbg(&adap->dev, "set standard mode\n");
+               mrst_i2c_write(i2c->base + IC_CON, (reg_val & (~0x6)) | 1<<1);
+       }
+
+       reg_val = mrst_i2c_read(i2c->base + IC_CON);
+       /* use 7-bit addressing */
+       if ((reg_val & (1<<4)) != 0x0) {
+               dev_dbg(&adap->dev, "set i2c 7 bit address mode\n");
+               mrst_i2c_write(i2c->base + IC_CON, reg_val & (~(1<<4)));
+       }
+
+       /*enable restart conditions */
+       reg_val = mrst_i2c_read(i2c->base + IC_CON);
+       if ((reg_val & (1<<5)) != 1<<5) {
+               dev_dbg(&adap->dev, "enable restart conditions\n");
+               mrst_i2c_write(i2c->base + IC_CON, (reg_val & (~(1 << 5)))
+                              | 1 << 5);
+       }
+
+       /* enable master FSM */
+       reg_val = mrst_i2c_read(i2c->base + IC_CON);
+       dev_dbg(&adap->dev, "ic_con reg_val is 0x%x\n", reg_val);
+       if ((reg_val & (1<<6)) != 1<<6) {
+               dev_dbg(&adap->dev, "enable master FSM\n");
+               mrst_i2c_write(i2c->base + IC_CON, (reg_val & (~(1 << 6)))
+                              | 1<<6);
+               dev_dbg(&adap->dev, "ic_con reg_val is 0x%x\n", reg_val);
+       }
+
+       /* use target address when initiating transfer */
+       reg_val = mrst_i2c_read(i2c->base + IC_TAR);
+       bit_mask = 1 << 11 | 1 << 10;
+
+       if ((reg_val & bit_mask) != 0x0) {
+               dev_dbg(&adap->dev, "WR: use target address when intiating"
+                       "transfer, i2c_tx_target\n");
+               mrst_i2c_write(i2c->base + IC_TAR, reg_val & ~bit_mask);
+       }
+
+       /* set target address to the I2C slave address */
+       dev_dbg(&adap->dev, "set target address to the I2C slave address,"
+               "addr is %x\n", pmsg->addr);
+       mrst_i2c_write(i2c->base + IC_TAR, pmsg->addr
+                      | (pmsg->flags & I2C_M_TEN ? IC_TAR_10BIT_ADDR : 0));
+
+       /* Enable I2C controller */
+       mrst_i2c_write(i2c->base + IC_ENABLE, ENABLE);
+
+       reg_val = mrst_i2c_read(i2c->base + IC_CON);
+
+       return 0;
+}
+
+/**
+ * mrst_i2c_xfer - Main master transfer routine.
+ * @adap: i2c_adapter struct pointer
+ * @pmsg: i2c_msg struct pointer
+ * @num: number of i2c_msg
+ *
+ * Return Values:
+ * +           number of messages transfered
+ * -ETIMEDOUT  If cannot disable I2C controller or read IC_STATUS
+ * -EINVAL     If the address in i2c_msg is invalid
+ *
+ * This function will be registered in i2c-core and exposed to external
+ * I2C clients.
+ * 1. Disable I2C controller
+ * 2. Unmask three interrupts: RX_FULL, TX_EMPTY, TX_ABRT
+ * 3. Check if address in i2c_msg is valid
+ * 4. Enable I2C controller
+ * 5. Perform real transfer (call xfer_read or xfer_write)
+ * 6. Wait until the current transfer is finished(check bus state)
+ * 7. Mask and clear all interrupts
+ */
+static int mrst_i2c_xfer(struct i2c_adapter *adap,
+                        struct i2c_msg *pmsg,
+                        int num)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)i2c_get_adapdata(adap);
+       int i, err;
+
+       dev_dbg(&adap->dev, "mrst_i2c_xfer, process %d msg(s)\n", num);
+       dev_dbg(&adap->dev, KERN_INFO "slave address is %x\n", pmsg->addr);
+
+       /* if number of messages equal 0*/
+       if (num == 0)
+               return 0;
+
+       /* Checked the sanity of passed messages. */
+       if (unlikely(mrst_i2c_invalid_address(&pmsg[0]))) {
+               dev_err(&adap->dev, "Invalid address 0x%03x (%d-bit)\n",
+                       pmsg[0].addr, pmsg[0].flags & I2C_M_TEN ? 10 : 7);
+               return -EINVAL;
+       }
+       for (i = 0; i < num; i++) {
+               /* Message address equal? */
+               if (unlikely(mrst_i2c_address_neq(&pmsg[0], &pmsg[i]))) {
+                       dev_err(&adap->dev, "Invalid address in msg[%d]\n", i);
+                       return -EINVAL;
+               }
+       }
+
+       if (mrst_i2c_setup(adap, pmsg))
+               return -EINVAL;
+
+       for (i = 0; i < num; i++) {
+               dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
+                       pmsg->flags & I2C_M_RD ? "read" : "writ",
+                       pmsg->len, pmsg->len > 1 ? "s" : "",
+                       pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
+
+
+               /* Read or Write */
+               if (pmsg->len && pmsg->buf) {
+                       if (pmsg->flags & I2C_M_RD) {
+                               dev_dbg(&adap->dev, "I2C_M_RD\n");
+                               err = xfer_read(adap, pmsg->buf, pmsg->len);
+                       } else {
+                               dev_dbg(&adap->dev, "I2C_M_WR\n");
+                               err = xfer_write(adap, pmsg->buf, pmsg->len);
+                       }
+                       if (err < 0)
+                               goto err_1;
+               }
+               dev_dbg(&adap->dev, "msg[%d] transfer complete\n", i);
+               pmsg++;         /* next message */
+       }
+       goto exit;
+
+err_1:
+       i = err;
+exit:
+       /* Mask interrupts */
+       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
+       /* Clear all interrupts */
+       mrst_i2c_read(i2c->base + IC_CLR_INTR);
+
+       return i;
+}
+
+static int mrst_gpio_init(int sda, int scl)
+{
+       if (gpio_request(sda, "I2C_SDA"))
+               goto err_sda;
+
+       if (gpio_request(scl, "I2C_SCL"))
+               goto err_scl;
+
+       /* TODO: Wait for Moorestown GPIO driver into upstream to uncomment */
+       /*gpio_alt_func(sda, 1);*/
+       /*gpio_alt_func(scl, 1);*/
+
+       return 0;
+err_scl:
+       gpio_free(sda);
+err_sda:
+       return -1;
+}
+
+static struct pci_device_id mrst_i2c_ids[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0802)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0803)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0804)},
+       {0,}
+};
+MODULE_DEVICE_TABLE(pci, mrst_i2c_ids);
+
+static struct i2c_algorithm mrst_i2c_algorithm = {
+       .master_xfer    = mrst_i2c_xfer,
+       .functionality  = mrst_i2c_func,
+};
+
+static struct pci_driver mrst_i2c_driver = {
+       .name           = "mrst_i2c",
+       .id_table       = mrst_i2c_ids,
+       .probe          = mrst_i2c_probe,
+       .remove         = __devexit_p(mrst_i2c_remove),
+       .suspend        = NULL,
+       .resume         = NULL,
+};
+
+/**
+ * mrst_i2c_probe - I2C controller initialization routine
+ * @dev: pci device
+ * @id: device id
+ *
+ * Return Values:
+ * 0           success
+ * -ENODEV     If cannot allocate pci resource
+ * -ENOMEM     If the register base remapping failed, or
+ *             if kzalloc failed
+ *
+ * Initialization steps:
+ * 1. Request for PCI resource
+ * 2. Remap the start address of PCI resource to register base
+ * 3. Request for device memory region
+ * 4. Fill in the struct members of mrst_i2c_private
+ * 5. Call mrst_i2c_hwinit() for hardware initialization
+ * 6. Read I2C device info table from memory and register into core
+ * 7. Register I2C adapter in i2c-core
+ */
+static int __devinit mrst_i2c_probe(struct pci_dev *dev,
+                                   const struct pci_device_id *id)
+{
+       struct mrst_i2c_private *mrst;
+       struct i2c_adapter *adap;
+       unsigned int start, len;
+       int err, busnum = 0;
+       void __iomem *base = NULL;
+       int gpio_sda = 0, gpio_scl = 0;
+
+       err = pci_enable_device(dev);
+       if (err) {
+               dev_err(&dev->dev, "Failed to enable I2C PCI device (%d)\n",
+                       err);
+               goto exit;
+       }
+
+       /* Determine the address of the I2C area */
+       start = pci_resource_start(dev, DEF_BAR);
+       len = pci_resource_len(dev, DEF_BAR);
+       if (!start || len <= 0) {
+               dev_err(&dev->dev, "Base address initialization failed\n");
+               err = -ENODEV;
+               goto exit;
+       }
+       dev_dbg(&dev->dev, "mrst i2c resource start %x, len=%d\n",
+               start, len);
+       err = pci_request_region(dev, DEF_BAR, mrst_i2c_driver.name);
+       if (err) {
+               dev_err(&dev->dev, "Failed to request I2C region "
+                       "0x%1x-0x%Lx\n", start,
+                       (unsigned long long)pci_resource_end(dev, DEF_BAR));
+               goto exit;
+       }
+
+       base = ioremap_nocache(start, len);
+       if (!base) {
+               dev_err(&dev->dev, "I/O memory remapping failed\n");
+               err = -ENOMEM;
+               goto fail0;
+       }
+
+       /* Allocate the per-device data structure, mrst_i2c_private */
+       mrst = kzalloc(sizeof(struct mrst_i2c_private), GFP_KERNEL);
+       if (mrst == NULL) {
+               dev_err(&dev->dev, "Can't allocate interface!\n");
+               err = -ENOMEM;
+               goto fail1;
+       }
+
+       adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+       if (adap == NULL) {
+               dev_err(&dev->dev, "Can't allocate interface!\n");
+               err = -ENOMEM;
+               goto fail2;
+       }
+
+       /* Initialize struct members */
+       snprintf(adap->name, sizeof(adap->name), "mrst_i2c");
+       adap->owner = THIS_MODULE;
+       adap->algo = &mrst_i2c_algorithm;
+       adap->class = I2C_CLASS_HWMON;
+       adap->dev.parent = &dev->dev;
+       mrst->adap = adap;
+       mrst->base = base;
+       mrst->speed = speed_mode;
+
+       pci_set_drvdata(dev, mrst);
+       i2c_set_adapdata(adap, mrst);
+
+       /* Initialize i2c controller */
+       err = mrst_i2c_hwinit(dev);
+       if (err < 0) {
+               dev_err(&dev->dev, "I2C interface initialization failed\n");
+               goto fail3;
+       }
+
+       switch (id->device) {
+       case 0x0802:
+               dev_dbg(&adap->dev, KERN_INFO "I2C0\n");
+               gpio_sda = GPIO_I2C_0_SDA;
+               gpio_scl = GPIO_I2C_0_SCL;
+               adap->nr = busnum = 0;
+               break;
+       case 0x0803:
+               dev_dbg(&adap->dev, KERN_INFO "I2C1\n");
+               gpio_sda = GPIO_I2C_1_SDA;
+               gpio_scl = GPIO_I2C_1_SCL;
+               adap->nr = busnum = 1;
+               break;
+       case 0x0804:
+               dev_dbg(&adap->dev, KERN_INFO "I2C2\n");
+               gpio_sda = GPIO_I2C_2_SDA;
+               gpio_scl = GPIO_I2C_2_SCL;
+               adap->nr = busnum = 2;
+               break;
+       default:
+               ;
+       }
+
+       /* Config GPIO pin for I2C */
+       err = mrst_gpio_init(gpio_sda, gpio_scl);
+       if (err) {
+               dev_err(&dev->dev, "GPIO %s registration failed\n",
+                       adap->name);
+               goto fail3;
+       }
+
+       /* Register i2c board info */
+       mrst_i2c_register_board_info(dev, busnum);
+
+       /* Adapter registration */
+       err = i2c_add_numbered_adapter(adap);
+       if (err) {
+               dev_err(&dev->dev, "Adapter %s registration failed\n",
+                       adap->name);
+               goto fail3;
+       }
+
+       dev_dbg(&dev->dev, "MRST I2C bus %d driver bind success.\n", busnum);
+       return 0;
+
+fail3:
+       i2c_set_adapdata(adap, NULL);
+       pci_set_drvdata(dev, NULL);
+       kfree(adap);
+fail2:
+       kfree(mrst);
+fail1:
+       iounmap(base);
+fail0:
+       pci_release_region(dev, DEF_BAR);
+exit:
+       return err;
+}
+
+static void __devexit mrst_i2c_remove(struct pci_dev *dev)
+{
+       struct mrst_i2c_private *mrst = (struct mrst_i2c_private *)
+                                       pci_get_drvdata(dev);
+       if (i2c_del_adapter(mrst->adap))
+               dev_err(&dev->dev, "Failed to delete i2c adapter");
+
+       kfree(mrst->mrst_i2c_info);
+       kfree(mrst->data);
+
+       switch (dev->device) {
+       case 0x0802:
+               gpio_free(GPIO_I2C_0_SDA);
+               gpio_free(GPIO_I2C_0_SCL);
+               break;
+       case 0x0803:
+               gpio_free(GPIO_I2C_1_SDA);
+               gpio_free(GPIO_I2C_1_SCL);
+               break;
+       case 0x0804:
+               gpio_free(GPIO_I2C_2_SDA);
+               gpio_free(GPIO_I2C_2_SCL);
+               break;
+       default:
+               break;
+       }
+
+       pci_set_drvdata(dev, NULL);
+       iounmap(mrst->base);
+       kfree(mrst);
+       pci_release_region(dev, DEF_BAR);
+}
+
+static int __init mrst_i2c_init(void)
+{
+       printk(KERN_NOTICE "Moorestown I2C driver %s\n", VERSION);
+       return pci_register_driver(&mrst_i2c_driver);
+}
+
+static void __exit mrst_i2c_exit(void)
+{
+       pci_unregister_driver(&mrst_i2c_driver);
+}
+
+module_init(mrst_i2c_init);
+module_exit(mrst_i2c_exit);
+
+MODULE_AUTHOR("Ba Zheng <zheng.ba@intel.com>");
+MODULE_DESCRIPTION("I2C driver for Moorestown Platform");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(VERSION);
diff --git a/drivers/i2c/busses/i2c-mrst.h b/drivers/i2c/busses/i2c-mrst.h
new file mode 100755
index 0000000..3a51bd2
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mrst.h
@@ -0,0 +1,279 @@
+#ifndef __I2C_MRST_H
+#define __I2C_MRST_H
+
+#include <linux/i2c.h>
+
+/* Update for 2.6.27 kernel by Wen */
+
+/* PCI config table macros */
+/* Offests */
+#define I2C_INFO_TABLE_LENGTH          4
+#define I2C_INFO_DEV_BLOCK             10
+#define I2C_DEV_ADDR                   2
+#define I2C_DEV_IRQ                    4
+#define I2C_DEV_NAME                   6
+#define I2C_DEV_INFO                   22
+/* Length */
+#define HEAD_LENGTH                    10
+#define BLOCK_LENGTH                   32
+#define ADDR_LENGTH                    2
+#define IRQ_LENGTH                     2
+#define NAME_LENGTH                    16
+#define INFO_LENGTH                    10
+
+struct mrst_i2c_private {
+       struct i2c_adapter *adap;
+       /* Register base address */
+       void __iomem *base;
+       /* Speed mode */
+       int speed;
+       struct i2c_board_info *mrst_i2c_info;
+       char (*data)[INFO_LENGTH];
+};
+
+/* Speed mode macros */
+#define STANDARD       100
+#define FAST           25
+#define        HIGH            3
+
+/* Control register */
+#define IC_CON                 0x00
+#define SLV_DIS                        (1 << 6)        /* Disable slave mode */
+#define RESTART                        (1 << 5)        /* Send a Restart condition */
+#define        ADDR_10BIT              (1 << 4)        /* 10-bit addressing */
+#define        STANDARD_MODE           (1 << 1)        /* standard mode */
+#define FAST_MODE              (2 << 1)        /* fast mode */
+#define HIGH_MODE              (3 << 1)        /* high speed mode */
+#define        MASTER_EN               (1 << 0)        /* Master mode */
+
+/* Target address register */
+#define IC_TAR                 0x04
+#define IC_TAR_10BIT_ADDR      (1 << 12)       /* 10-bit addressing */
+#define IC_TAR_SPECIAL         (1 << 11)       /* Perform special I2C cmd */
+#define IC_TAR_GC_OR_START     (1 << 10)       /* 0: Gerneral Call Address */
+                                               /* 1: START BYTE */
+
+/* Slave Address Register */
+#define IC_SAR                 0x08            /* Not used in Master mode */
+
+/* High Speed Master Mode Code Address Register */
+#define IC_HS_MADDR            0x0c
+
+/* Rx/Tx Data Buffer and Command Register */
+#define IC_DATA_CMD            0x10
+#define IC_RD                  (1 << 8)        /* 1: Read 0: Write */
+
+/* Standard Speed Clock SCL High Count Register */
+#define IC_SS_SCL_HCNT         0x14
+
+/* Standard Speed Clock SCL Low Count Register */
+#define IC_SS_SCL_LCNT         0x18
+
+/* Fast Speed Clock SCL High Count Register */
+#define IC_FS_SCL_HCNT         0x1c
+
+/* Fast Spedd Clock SCL Low Count Register */
+#define IC_FS_SCL_LCNT         0x20
+
+/* High Speed Clock SCL High Count Register */
+#define IC_HS_SCL_HCNT         0x24
+
+/* High Speed Clock SCL Low Count Register */
+#define IC_HS_SCL_LCNT         0x28
+
+/* Interrupt Status Register */
+#define IC_INTR_STAT           0x2c            /* Read only */
+#define R_GEN_CALL             (1 << 11)
+#define R_START_DET            (1 << 10)
+#define R_STOP_DET             (1 << 9)
+#define R_ACTIVITY             (1 << 8)
+#define R_RX_DONE              (1 << 7)
+#define        R_TX_ABRT               (1 << 6)
+#define R_RD_REQ               (1 << 5)
+#define R_TX_EMPTY             (1 << 4)
+#define R_TX_OVER              (1 << 3)
+#define        R_RX_FULL               (1 << 2)
+#define        R_RX_OVER               (1 << 1)
+#define R_RX_UNDER             (1 << 0)
+
+/* Interrupt Mask Register */
+#define IC_INTR_MASK           0x30            /* Read and Write */
+#define M_GEN_CALL             (1 << 11)
+#define M_START_DET            (1 << 10)
+#define M_STOP_DET             (1 << 9)
+#define M_ACTIVITY             (1 << 8)
+#define M_RX_DONE              (1 << 7)
+#define        M_TX_ABRT               (1 << 6)
+#define M_RD_REQ               (1 << 5)
+#define M_TX_EMPTY             (1 << 4)
+#define M_TX_OVER              (1 << 3)
+#define        M_RX_FULL               (1 << 2)
+#define        M_RX_OVER               (1 << 1)
+#define M_RX_UNDER             (1 << 0)
+
+/* Raw Interrupt Status Register */
+#define IC_RAW_INTR_STAT       0x34            /* Read Only */
+#define GEN_CALL               (1 << 11)       /* General call */
+#define START_DET              (1 << 10)       /* (RE)START occured */
+#define STOP_DET               (1 << 9)        /* STOP occured */
+#define ACTIVITY               (1 << 8)        /* Bus busy */
+#define RX_DONE                        (1 << 7)        /* Not used in Master mode */
+#define        TX_ABRT                 (1 << 6)        /* Transmit Abort */
+#define RD_REQ                 (1 << 5)        /* Not used in Master mode */
+#define TX_EMPTY               (1 << 4)        /* TX FIFO <= threshold */
+#define TX_OVER                        (1 << 3)        /* TX FIFO overflow */
+#define        RX_FULL                 (1 << 2)        /* RX FIFO >= threshold */
+#define        RX_OVER                 (1 << 1)        /* RX FIFO overflow */
+#define RX_UNDER               (1 << 0)        /* RX FIFO empty */
+
+/* Receive FIFO Threshold Register */
+#define IC_RX_TL               0x38
+
+/* Transmit FIFO Treshold Register */
+#define IC_TX_TL               0x3c
+
+/* Clear Combined and Individual Interrupt Register */
+#define IC_CLR_INTR            0x40
+#define CLR_INTR               (1 << 0)
+
+/* Clear RX_UNDER Interrupt Register */
+#define IC_CLR_RX_UNDER                0x44
+#define CLR_RX_UNDER           (1 << 0)
+
+/* Clear RX_OVER Interrupt Register */
+#define IC_CLR_RX_OVER         0x48
+#define CLR_RX_OVER            (1 << 0)
+
+/* Clear TX_OVER Interrupt Register */
+#define IC_CLR_TX_OVER         0x4c
+#define CLR_TX_OVER            (1 << 0)
+
+#define IC_CLR_RD_REQ          0x50
+
+/* Clear TX_ABRT Interrupt Register */
+#define IC_CLR_TX_ABRT         0x54
+#define CLR_TX_ABRT            (1 << 0)
+
+#define IC_CLR_RX_DONE         0x58
+
+
+/* Clear ACTIVITY Interrupt Register */
+#define IC_CLR_ACTIVITY                0x5c
+#define CLR_ACTIVITY           (1 << 0)
+
+/* Clear STOP_DET Interrupt Register */
+#define IC_CLR_STOP_DET                0x60
+#define CLR_STOP_DET           (1 << 0)
+
+/* Clear START_DET Interrupt Register */
+#define IC_CLR_START_DET       0x64
+#define CLR_START_DET          (1 << 0)
+
+/* Clear GEN_CALL Interrupt Register */
+#define IC_CLR_GEN_CALL                0x68
+#define CLR_GEN_CALL           (1 << 0)
+
+/* Enable Register */
+#define IC_ENABLE              0x6c
+#define ENABLE                 (1 << 0)
+
+/* Status Register */
+#define IC_STATUS              0x70            /* Read Only */
+#define STAT_SLV_ACTIVITY      (1 << 6)        /* Slave not in idle */
+#define STAT_MST_ACTIVITY      (1 << 5)        /* Master not in idle */
+#define STAT_RFF               (1 << 4)        /* RX FIFO Full */
+#define STAT_RFNE              (1 << 3)        /* RX FIFO Not Empty */
+#define STAT_TFE               (1 << 2)        /* TX FIFO Empty */
+#define STAT_TFNF              (1 << 1)        /* TX FIFO Not Full */
+#define STAT_ACTIVITY          (1 << 0)        /* Activity Status */
+
+/* Transmit FIFO Level Register */
+#define IC_TXFLR               0x74            /* Read Only */
+#define TXFLR                  (1 << 0)        /* TX FIFO level */
+
+/* Receive FIFO Level Register */
+#define IC_RXFLR               0x78            /* Read Only */
+#define RXFLR                  (1 << 0)        /* RX FIFO level */
+
+/* Transmit Abort Source Register */
+#define IC_TX_ABRT_SOURCE      0x80
+#define ABRT_SLVRD_INTX                (1 << 15)
+#define ABRT_SLV_ARBLOST       (1 << 14)
+#define ABRT_SLVFLUSH_TXFIFO   (1 << 13)
+#define        ARB_LOST                (1 << 12)
+#define ABRT_MASTER_DIS                (1 << 11)
+#define ABRT_10B_RD_NORSTRT    (1 << 10)
+#define ABRT_SBYTE_NORSTRT     (1 << 9)
+#define ABRT_HS_NORSTRT                (1 << 8)
+#define ABRT_SBYTE_ACKDET      (1 << 7)
+#define ABRT_HS_ACKDET         (1 << 6)
+#define ABRT_GCALL_READ                (1 << 5)
+#define ABRT_GCALL_NOACK       (1 << 4)
+#define ABRT_TXDATA_NOACK      (1 << 3)
+#define ABRT_10ADDR2_NOACK     (1 << 2)
+#define ABRT_10ADDR1_NOACK     (1 << 1)
+#define ABRT_7B_ADDR_NOACK     (1 << 0)
+
+/* Enable Status Register */
+#define IC_ENABLE_STATUS       0x9c
+#define IC_EN                  (1 << 0)        /* I2C in an enabled state */
+
+/* Component Parameter Register 1*/
+#define IC_COMP_PARAM_1                0xf4
+#define APB_DATA_WIDTH         (0x3 << 0)
+
+/* GPIO_PINS */
+#define GPIO_I2C_0_SDA         56
+#define GPIO_I2C_0_SCL         57
+
+#define GPIO_I2C_1_SDA         54
+#define GPIO_I2C_1_SCL         55
+
+#define GPIO_I2C_2_SDA         52
+#define GPIO_I2C_2_SCL         53
+
+/* added by xiaolin --begin */
+#define SS_MIN_SCL_HIGH         4000
+#define SS_MIN_SCL_LOW          4700
+#define FS_MIN_SCL_HIGH         600
+#define FS_MIN_SCL_LOW          1300
+#define HS_MIN_SCL_HIGH_100PF   60
+#define HS_MIN_SCL_LOW_100PF    120
+
+enum mrst_i2c_irq {
+    i2c_irq_none = 0x000,
+    i2c_irq_rx_under = 0x001,
+    i2c_irq_rx_over = 0x002,
+    i2c_irq_rx_full = 0x004,
+    i2c_irq_tx_over = 0x008,
+    i2c_irq_tx_empty = 0x010,
+    i2c_irq_rd_req = 0x020,
+    i2c_irq_tx_abrt = 0x040,
+    i2c_irq_rx_done = 0x080,
+    i2c_irq_activity = 0x100,
+    i2c_irq_stop_det = 0x200,
+    i2c_irq_start_det = 0x400,
+    i2c_irq_gen_call = 0x800,
+    i2c_irq_all = 0xfff
+};
+
+/* Function declarations */
+static int mrst_i2c_disable(struct i2c_adapter *);
+static int __devinit mrst_i2c_hwinit(struct pci_dev *);
+static u32 mrst_i2c_func(struct i2c_adapter *);
+static inline int mrst_i2c_invalid_address(const struct i2c_msg *);
+static inline int mrst_i2c_address_neq(const struct i2c_msg *,
+                                      const struct i2c_msg *);
+static int mrst_i2c_xfer(struct i2c_adapter *,
+                        struct i2c_msg *,
+                        int);
+static int __devinit mrst_i2c_probe(struct pci_dev *,
+                                   const struct pci_device_id *);
+static void __devexit mrst_i2c_remove(struct pci_dev *);
+static int __init mrst_i2c_init(void);
+static void __exit mrst_i2c_exit(void);
+static int xfer_read(struct i2c_adapter *,
+                    unsigned char *, int);
+static int xfer_write(struct i2c_adapter *,
+                     unsigned char *, int);
+#endif /* __I2C_MRST_H */
diff --git a/drivers/i2c/i2c-boardinfo.c b/drivers/i2c/i2c-boardinfo.c
index ffb35f0..72bde31 100644
--- a/drivers/i2c/i2c-boardinfo.c
+++ b/drivers/i2c/i2c-boardinfo.c
@@ -57,11 +57,13 @@ EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num);
  * The board info passed can safely be __initdata, but be careful of embedded
  * pointers (for platform_data, functions, etc) since that won't be copied.
  */
-int __init
+int
 i2c_register_board_info(int busnum,
        struct i2c_board_info const *info, unsigned len)
 {
        int status;
+       int flag = 0;
+       struct i2c_devinfo      *devinfo;

        mutex_lock(&__i2c_board_lock);

@@ -69,22 +71,34 @@ i2c_register_board_info(int busnum,
        if (busnum >= __i2c_first_dynamic_bus_num)
                __i2c_first_dynamic_bus_num = busnum + 1;

+       /* Detect if the device is already in i2c_board_list */
        for (status = 0; len; len--, info++) {
-               struct i2c_devinfo      *devinfo;
-
-               devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
-               if (!devinfo) {
-                       pr_debug("i2c-core: can't register boardinfo!\n");
-                       status = -ENOMEM;
-                       break;
+               list_for_each_entry(devinfo, &__i2c_board_list, list) {
+                       if (devinfo->busnum == busnum
+                           && devinfo->board_info.addr == info->addr) {
+                               flag = 1;
+                               break;
+                       }
                }
+               if (flag != 1) {
+                       struct i2c_devinfo      *dev;
+                       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+                       if (!dev) {
+                               pr_debug("i2c-core: can't register"
+                                        "boardinfo!\n");
+                               status = -ENOMEM;
+                               break;
+                       }

-               devinfo->busnum = busnum;
-               devinfo->board_info = *info;
-               list_add_tail(&devinfo->list, &__i2c_board_list);
+                       dev->busnum = busnum;
+                       dev->board_info = *info;
+                       list_add_tail(&dev->list, &__i2c_board_list);
+               }
+               flag = 0;
        }

        mutex_unlock(&__i2c_board_lock);

        return status;
 }
+EXPORT_SYMBOL_GPL(i2c_register_board_info);
--
1.5.5.1


-----Original Message-----
From: Wang, Wen W
Sent: 2009年4月23日 17:01
To: 'Jean Delvare'
Cc: linux-i2c@vger.kernel.org
Subject: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform

Hi Jean,

This is a description for the patch:
1. Patch for I2C controller driver for Intel low power platform "Moorestown".
2. The driver depends on a GPIO driver for Intel Moorestown platform.
3. The patch will:
        a. Add i2c_mrst.c and i2c_mrst.h to kernel directory "drivers/i2c/busses"
        b. Add items into kernel files "drivers/i2c/busses/Kconfig" and "drivers/i2c/Makefile".
        c. Modify i2c-boardinfo.c to export i2c_register_board_info() function and add code to detect if a device is already in i2c_board_list.

Thanks
Wen

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]         ` <0A882F4D99BBF6449D58E61AAFD7EDD6136779F1-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2009-04-23  9:29           ` Jean Delvare
       [not found]             ` <20090423112935.306ba11a-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Jean Delvare @ 2009-04-23  9:29 UTC (permalink / raw)
  To: Wang, Wen W; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

Hi Wen,

On Thu, 23 Apr 2009 17:00:56 +0800, Wang, Wen W wrote:
> Hi Jean,
> 
> This is a description for the patch:
> 1. Patch for I2C controller driver for Intel low power platform "Moorestown".
> 2. The driver depends on a GPIO driver for Intel Moorestown platform.
> 3. The patch will:
> 	a. Add i2c_mrst.c and i2c_mrst.h to kernel directory "drivers/i2c/busses"

Why such a cryptic name? You know, this isn't MS-DOS, names can be
longer than 8 characters ;)

> 	b. Add items into kernel files "drivers/i2c/busses/Kconfig" and "drivers/i2c/Makefile".
> 	c. Modify i2c-boardinfo.c to export i2c_register_board_info() function and add code to detect if a device is already in i2c_board_list.

This last item should go to a separate patch, so that it can be
discussed. It is not clear to me why you would need to export functions
nobody else needed to export. It will be easier to review and merge
your code if the bus driver itself is in one patch and any required
integration changes are in another.

Thanks,
-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]             ` <20090423112935.306ba11a-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2009-04-23  9:55               ` Wang, Wen W
       [not found]                 ` <0A882F4D99BBF6449D58E61AAFD7EDD613677A5B-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Wang, Wen W @ 2009-04-23  9:55 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

Hi Jean,

>-----Original Message-----
>From: Jean Delvare [mailto:khali@linux-fr.org]
>Sent: 2009年4月23日 17:30
>To: Wang, Wen W
>Cc: linux-i2c@vger.kernel.org
>Subject: Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
>
>Hi Wen,
>
>On Thu, 23 Apr 2009 17:00:56 +0800, Wang, Wen W wrote:
>> Hi Jean,
>>
>> This is a description for the patch:
>> 1. Patch for I2C controller driver for Intel low power platform "Moorestown".
>> 2. The driver depends on a GPIO driver for Intel Moorestown platform.
>> 3. The patch will:
>> 	a. Add i2c_mrst.c and i2c_mrst.h to kernel directory "drivers/i2c/busses"
>
>Why such a cryptic name? You know, this isn't MS-DOS, names can be
>longer than 8 characters ;)

:-) I can change the name to i2c_moorestown.c

>> 	b. Add items into kernel files "drivers/i2c/busses/Kconfig" and
>"drivers/i2c/Makefile".
>> 	c. Modify i2c-boardinfo.c to export i2c_register_board_info() function and add
>code to detect if a device is already in i2c_board_list.
>
>This last item should go to a separate patch, so that it can be

I will separate the patch into two.

>discussed. It is not clear to me why you would need to export functions
>nobody else needed to export. It will be easier to review and merge
>your code if the bus driver itself is in one patch and any required
>integration changes are in another.

This is because:
1. The I2C driver need to call i2c_register_board_info() to register I2C device info table when loaded.
2. To support loadable module, I made such change to i2c_register_board_info().

I know it’s quite ugly there, but I really can't find a way to do so. Please feel free to teach me. 

>Thanks,
>--
>Jean Delvare

BRs
Wen

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 0/2] I2C: I2C controller driver for Intel Moorestown platform
  2009-04-16  9:14   ` Jean Delvare
       [not found]     ` <20090416111436.296cdd12-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  2009-04-23  9:04     ` [PATCH 1/1] " Wang, Wen W
@ 2009-04-23 10:19     ` Wang, Wen W
       [not found]       ` <0A882F4D99BBF6449D58E61AAFD7EDD613677A65-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2 siblings, 1 reply; 26+ messages in thread
From: Wang, Wen W @ 2009-04-23 10:19 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Wang, Wen W

Hi Jean,

This is a description for the patches:
1. Patches for I2C controller driver for Intel low power platform "Moorestown".
2. The driver depends on a GPIO driver for Intel Moorestown platform.
3. Patch 1 will:
	a. Add "i2c_moorestown.c" and "i2c_moorestown.h" to kernel directory drivers/i2c/busses"
	b. Add items into kernel files "drivers/i2c/busses/Kconfig" and "drivers/i2c/Makefile".
4. Patch 2 will:
	a. Modify i2c-boardinfo.c to export i2c_register_board_info() function and add code to detect if a device is already in i2c_board_list.

Thanks
Wen

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/2] I2C: I2C controller driver for Intel Moorestown platform
       [not found]       ` <0A882F4D99BBF6449D58E61AAFD7EDD613677A65-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2009-04-23 10:22         ` Wang, Wen W
       [not found]           ` <0A882F4D99BBF6449D58E61AAFD7EDD613677A69-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2009-05-14  7:35         ` [PATCH 0/1] " Wang, Wen W
  1 sibling, 1 reply; 26+ messages in thread
From: Wang, Wen W @ 2009-04-23 10:22 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Wang, Wen W

From 6c5a5c1ae1977deefa181f883ecfc4efa7c8555b Mon Sep 17 00:00:00 2001
From: Wen Wang <wen.w.wang@intel.com>
Date: Thu, 23 Apr 2009 18:11:33 +0800
Subject: [PATCH] I2C controller driver for Intel Moorestown platform
 Signed-off-by: Wen Wang <wen.w.wang@intel.com>

---
 drivers/i2c/busses/Kconfig          |   10 +
 drivers/i2c/busses/Makefile         |    1 +
 drivers/i2c/busses/i2c-moorestown.c |  973 +++++++++++++++++++++++++++++++++++
 drivers/i2c/busses/i2c-moorestown.h |  279 ++++++++++
 4 files changed, 1263 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-moorestown.c
 create mode 100755 drivers/i2c/busses/i2c-moorestown.h

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index a48c8ae..cf84038 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -738,4 +738,14 @@ config SCx200_ACB
          This support is also available as a module.  If so, the module
          will be called scx200_acb.

+config I2C_MOORESTOWN
+       tristate "Intel Moorestown I2C Controller"
+       depends on PCI && GPIOLIB
+       default y
+       help
+         If you say yes to this option, support will be included for the Intel
+         Moorestown chipset I2C controller.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-moorestown.
+
 endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 776acb6..9d5f89c 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_I2C_SIBYTE)      += i2c-sibyte.o
 obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
+obj-$(CONFIG_I2C_MOORESTOWN)   += i2c-moorestown.o

 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/busses/i2c-moorestown.c b/drivers/i2c/busses/i2c-moorestown.c
new file mode 100644
index 0000000..1c314ca
--- /dev/null
+++ b/drivers/i2c/busses/i2c-moorestown.c
@@ -0,0 +1,973 @@
+/*
+ * Support for Moorestown I2C controller
+ *
+ * Copyright (c) 2009 Intel Corporation.
+ * Copyright (c) 2009 Synopsys. Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License, version
+ * 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+
+#include <linux/io.h>
+
+#include "i2c-moorestown.h"
+
+#define MAX_T_POLL_COUNT       4000    /* FIXME */
+#define DEF_BAR                0
+#define VERSION                "Version 0.5"
+
+#define mrst_i2c_read(reg)             __raw_readl(reg)
+#define mrst_i2c_write(reg, val)       __raw_writel((val), (reg))
+
+static int speed_mode = STANDARD;
+module_param(speed_mode, int, S_IRUGO);
+
+/**
+ * mrst_i2c_register_board_info - Register I2C device info
+ * @dev: struct pointer to pci_dev
+ * @busnum: Bus number to register
+ *
+ * Return Value:
+ * 0           success
+ * -ENOMEM     if fail to allocate memory
+ * -ENODEV     if fail to detect the address of I2C device info table
+ *
+ * Moorestown I2C device info table is initialized by firmware and the address
+ * pointer is filled into I2C controller PCI config space BAR 1.
+ *
+ * Driver will read this table from memory and register this device table into
+ * I2C core.
+ */
+static int mrst_i2c_register_board_info(struct pci_dev *dev, int busnum)
+{
+       struct mrst_i2c_private *mrst = (struct mrst_i2c_private *)
+                                       pci_get_drvdata(dev);
+       int err;
+       unsigned short addr, irq, host;
+       char *name = NULL;
+       struct i2c_board_info *info = NULL;
+       unsigned int addr_off, irq_off, name_off, data_off, host_off;
+       unsigned int table_len, block_num, block = 0;
+       int i, j;
+       unsigned int start, len;
+       void __iomem *base = NULL, *ptr = NULL;
+
+       /* Determine the address of the I2C device info table area */
+       start = pci_resource_start(dev, 1);
+       len = pci_resource_len(dev, 1);
+       if (!start || len <= 0) {
+               err = -ENODEV;
+               return err;
+       }
+
+       err = pci_request_region(dev, 1, "mrst_i2c");
+       if (err) {
+               dev_err(&dev->dev, "Failed to request I2C region "
+                       "0x%1x-0x%Lx\n", start,
+                       (unsigned long long)pci_resource_end(dev, 1));
+               return err;
+       }
+
+       ptr = ioremap(start, len);
+       if (!ptr) {
+               dev_err(&dev->dev, "I/O memory remapping failed\n");
+               err = -ENOMEM;
+               goto err0;
+       }
+
+       /*
+        * Detect if an old firmware is used.
+        * Newer firmware is using two levels pointer to the device info table
+        */
+       if (len == 8) {
+               start = ioread32(ptr);
+               len = ioread32(ptr + 4);
+               iounmap(ptr);
+               base = ioremap(start, len);
+       } else
+               base = ptr;
+
+       /* Initialization */
+       name = kzalloc(sizeof(char) * NAME_LENGTH, GFP_KERNEL);
+       if (name == NULL) {
+               err = -ENOMEM;
+               goto err1;
+       }
+
+       info = kzalloc(sizeof(struct i2c_board_info), GFP_KERNEL);
+       if (info == NULL) {
+               dev_err(&dev->dev,
+                       "Can't allocate interface for i2c_board_info\n");
+               err = -ENOMEM;
+               goto err2;
+       }
+
+       /* Get I2C info table length */
+       table_len = ioread32(base + I2C_INFO_TABLE_LENGTH);
+
+       /* Calculate the number of I2C device */
+       block_num = (table_len - HEAD_LENGTH)/BLOCK_LENGTH;
+       if (!block_num)
+               /* No I2C device info */
+               goto err3;
+
+       /* Initialize mrst_i2c_info array */
+       mrst->mrst_i2c_info = kzalloc(sizeof(struct i2c_board_info) *
+                                     block_num, GFP_KERNEL);
+       if (mrst->mrst_i2c_info == NULL) {
+               dev_err(&dev->dev,
+                       "Can't allocate interface for i2c_board_info\n");
+               err = -ENOMEM;
+               goto err3;
+       }
+
+       mrst->data = kzalloc(sizeof(*mrst->data) * block_num, GFP_KERNEL);
+       if (mrst->data == NULL) {
+               dev_err(&dev->dev,
+                       "Can't allocate interface for per device data\n");
+               err = -ENOMEM;
+               goto err4;
+       }
+
+       for (i = 0; i < block_num; i++) {
+               /* I2C device info block offsets */
+               host_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i;
+               addr_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i + I2C_DEV_ADDR;
+               irq_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i + I2C_DEV_IRQ;
+               name_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i + I2C_DEV_NAME;
+               data_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i + I2C_DEV_INFO;
+
+               /* Read PCI config table */
+               host = ioread16(base + host_off);
+               if (host != busnum)
+                       continue;
+               addr = ioread16(base + addr_off);
+               irq = ioread16(base + irq_off);
+               for (j = 0; j < NAME_LENGTH; j++)
+                       name[j] = ioread8(base + name_off + j);
+
+               for (j = 0; j < INFO_LENGTH; j++)
+                       mrst->data[i][j] = ioread8(base + data_off + j);
+               dev_dbg(&dev->dev, "I2C device info table: name = %s, address ="
+                       " %x\n", name, addr);
+
+               /* Fill in i2c_board_info struct */
+               memcpy(info->type, name, NAME_LENGTH);
+               info->platform_data = mrst->data[i];
+               info->addr = addr;
+               info->irq = irq;
+
+               /* Add to mrst_i2c_info array */
+               memcpy(mrst->mrst_i2c_info + block, info,
+                      sizeof(struct i2c_board_info));
+               block++;
+       }
+
+       /* Register i2c board info */
+       err = i2c_register_board_info(busnum, mrst->mrst_i2c_info, block);
+       goto err3;
+
+/* Clean up */
+err4:
+       kfree(mrst->mrst_i2c_info);
+err3:
+       kfree(info);
+err2:
+       kfree(name);
+err1:
+       iounmap(base);
+err0:
+       pci_release_region(dev, 1);
+       return err;
+}
+
+/**
+ * mrst_i2c_disable - Disable I2C controller
+ * @adap: struct pointer to i2c_adapter
+ *
+ * Return Value:
+ * 0           success
+ * -EBUSY      if device is busy
+ * -ETIMEOUT   if i2c cannot be disabled within the given time
+ *
+ * I2C bus state should be checked prior to disabling the hardware. If bus is
+ * not in idle state, an errno is returned. Write "0" to IC_ENABLE to disable
+ * I2C controller.
+ */
+static int mrst_i2c_disable(struct i2c_adapter *adap)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)i2c_get_adapdata(adap);
+
+       int count = 0;
+
+       /* Check if device is busy */
+       dev_dbg(&adap->dev, "mrst i2c disable\n");
+       while (mrst_i2c_read(i2c->base + IC_STATUS) & 0x1) {
+               dev_dbg(&adap->dev, "i2c is busy, count is %d\n", count);
+               if (count++ > 10000)
+                       return -EBUSY;
+       }
+
+       /* Set IC_ENABLE to 0 */
+       mrst_i2c_write(i2c->base + IC_ENABLE, 0);
+
+       /* Disable all interupts */
+       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
+
+       /* Clear all interrupts */
+       mrst_i2c_read(i2c->base + IC_CLR_INTR);
+
+       return 0;
+}
+
+/**
+ * mrst_i2c_hwinit - Initiate the I2C hardware registers. This function will
+ * be called in mrst_i2c_probe() before device registration.
+ * @dev: pci device struct pointer
+ *
+ * Return Values:
+ * 0           success
+ * -EBUSY      i2c cannot be disabled
+ * -ETIMEDOUT  i2c cannot be disabled
+ * -EFAULT     If APB data width is not 32-bit wide
+ *
+ * I2C should be disabled prior to other register operation. If failed, an
+ * errno is returned. Mask and Clear all interrpts, this should be done at
+ * first.  Set common registers which will not be modified during normal
+ * transfers, including: controll register, FIFO threshold and clock freq.
+ * Check APB data width at last.
+ */
+static int  __devinit mrst_i2c_hwinit(struct pci_dev *dev)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)pci_get_drvdata(dev);
+       int err = 0;
+
+       /* Disable i2c first */
+       err = mrst_i2c_disable(i2c->adap);
+       if (err)
+               return err;
+
+       /* Disable all interupts */
+       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
+
+       /* Clear all interrupts */
+       mrst_i2c_read(i2c->base + IC_CLR_INTR);
+
+       /*
+        * Setup clock frequency and speed mode
+        * Enable restart condition,
+        * enable master FSM, disable slave FSM,
+        * use target address when initiating transfer
+        */
+       switch (speed_mode) {
+       case STANDARD:
+               mrst_i2c_write(i2c->base + IC_CON,
+                              SLV_DIS | RESTART | STANDARD_MODE | MASTER_EN);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x75);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x7c);
+               break;
+       case FAST:
+               mrst_i2c_write(i2c->base + IC_CON,
+                              SLV_DIS | RESTART | FAST_MODE | MASTER_EN);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x15);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x21);
+               break;
+       case HIGH:
+               mrst_i2c_write(i2c->base + IC_CON,
+                              SLV_DIS | RESTART | HIGH_MODE | MASTER_EN);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x7);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0xE);
+               break;
+       default:
+               ;
+       }
+
+       /* Set tranmit & receive FIFO threshold to zero */
+       mrst_i2c_write(i2c->base + IC_RX_TL, 0x3);
+       mrst_i2c_write(i2c->base + IC_TX_TL, 0x3);
+
+       mrst_i2c_write(i2c->base + IC_ENABLE, 1);
+
+       return err;
+}
+
+/**
+ * mrst_i2c_func - Return the supported three I2C operations.
+ * @adapter: i2c_adapter struct pointer
+ */
+static u32 mrst_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
+}
+
+/**
+ * mrst_i2c_invalid_address - To check if the address in i2c message is
+ * correct.
+ * @p: i2c_msg struct pointer
+ *
+ * Return Values:
+ * 0   if the address is valid
+ * 1   if the address is invalid
+ */
+static inline int mrst_i2c_invalid_address(const struct i2c_msg *p)
+{
+       int ret = ((p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN)
+                                        && (p->addr > 0x7f)));
+       return ret;
+}
+
+/**
+ * mrst_i2c_address_neq - To check if the addresses for different i2c messages
+ * are equal.
+ * @p1: first i2c_msg
+ * @p2: second i2c_msg
+ *
+ * Return Values:
+ * 0    if addresse are equal
+ * 1    if not equal
+ *
+ * Within a single transfer, I2C client may need to send its address more
+ * than one time. So a check for the address equation is needed.
+ */
+static inline int mrst_i2c_address_neq(const struct i2c_msg *p1,
+                                      const struct i2c_msg *p2)
+{
+       int ret = ((p1->addr != p2->addr) || ((p1->flags & (I2C_M_TEN))
+                                             != ((p2->flags) & (I2C_M_TEN))));
+       return ret;
+}
+
+/**
+ * mrst_i2c_abort - To handle transfer abortions and print error messages.
+ * @adap: i2c_adapter struct pointer
+ *
+ * By reading register IC_TX_ABRT_SOURCE, various transfer errors can be
+ * distingushed. At present, no circumstances have been found out that
+ * multiple errors would be occured simutaneously, so we simply use the
+ * register value directly.
+ *
+ * At last the error bits are cleared. (Note clear ABRT_SBYTE_NORSTRT bit need
+ * a few extra steps)
+ */
+static void mrst_i2c_abort(struct i2c_adapter *adap)
+{
+       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
+           i2c_get_adapdata(adap);
+
+       /* Read about source register */
+       int abort = mrst_i2c_read(i2c->base + IC_TX_ABRT_SOURCE);
+
+       dev_dbg(&adap->dev, "Abort: ");
+
+       /* Single transfer error check:
+        * According to databook, TX/RX FIFOs would be flushed when
+        * the abort interrupt occured.
+        */
+       switch (abort) {
+       case (ABRT_MASTER_DIS):
+               dev_err(&adap->dev,
+                       "initiate Master operation with Master mode"
+                       "disabled.\n");
+
+               break;
+       case (ABRT_10B_RD_NORSTRT):
+               dev_err(&adap->dev,
+                       "RESTART disabled and master sends READ cmd in 10-BIT"
+                       "addressing.\n");
+               break;
+       case (ABRT_SBYTE_NORSTRT):
+               dev_err(&adap->dev,
+                       "RESTART disabled and user is trying to send START"
+                       "byte.\n");
+               /* Page 141 data book */
+               mrst_i2c_write(i2c->base + IC_TX_ABRT_SOURCE,
+                              !(ABRT_SBYTE_NORSTRT));
+               mrst_i2c_write(i2c->base + IC_CON, RESTART);
+               mrst_i2c_write(i2c->base + IC_TAR, !(IC_TAR_SPECIAL));
+               break;
+       case (ABRT_SBYTE_ACKDET):
+               dev_err(&adap->dev,
+                       "START byte was acknowledged.\n");
+               break;
+       case (ABRT_TXDATA_NOACK):
+               dev_err(&adap->dev,
+                       "No acknowledge received from slave.\n");
+               break;
+       case (ABRT_10ADDR2_NOACK):
+               dev_err(&adap->dev,
+                       "The 2nd address byte of 10-bit address not"
+                       "acknowledged.\n");
+               break;
+       case (ABRT_10ADDR1_NOACK):
+               dev_dbg(&adap->dev,
+                       "The 1st address byte of 10-bit address not"
+                       "acknowledged.\n");
+               break;
+       case (ABRT_7B_ADDR_NOACK):
+               dev_err(&adap->dev,
+                       "7-bit address not acknowledged.\n");
+               break;
+       default:
+               ;;
+       }
+
+       /* Clear TX_ABRT bit */
+       mrst_i2c_read(i2c->base + IC_CLR_TX_ABRT);
+}
+
+/**
+ * xfer_read - Internal function to implement master read transfer.
+ * @adap: i2c_adapter struct pointer
+ * @buf: buffer in i2c_msg
+ * @length: number of bytes to be read
+ *
+ * Return Values:
+ * 0           if the read transfer succeeds
+ * -ETIMEDOUT  if cannot read the "raw" interrupt register
+ * -EINVAL     if transfer abort occured
+ *
+ * For every byte, a "READ" command will be loaded into IC_DATA_CMD prior to
+ * data transfer. The actual "read" operation will be performed if the RX_FULL
+ * interrupt is occured.
+ *
+ * Note there may be two interrupt signals captured, one should read
+ * IC_RAW_INTR_STAT to seperate between errors and actual data.
+ */
+static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
+           i2c_get_adapdata(adap);
+       uint32_t reg_val;
+       int i = length;
+       unsigned count = 0;
+       uint32_t bit_get = 1 << 3; /* receive fifo not empty */
+
+       while (i--)
+               mrst_i2c_write(i2c->base + IC_DATA_CMD, (uint16_t)0x100);
+
+       i = length;
+       while (i--) {
+               count = 0;
+               reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+               while ((reg_val & bit_get) == 0) {
+                       reg_val = mrst_i2c_read(i2c->base + IC_RAW_INTR_STAT);
+                       if ((reg_val & 0x40) == 0x40)
+                               goto read_abrt;
+                       reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+                       if (count++ > MAX_T_POLL_COUNT)
+                               goto read_loop;
+               }
+
+               reg_val = mrst_i2c_read(i2c->base + IC_DATA_CMD);
+               *buf++ = reg_val;
+       }
+
+       return 0;
+
+read_loop:
+       dev_err(&adap->dev, "Time out in read\n");
+       return -ETIMEDOUT;
+read_abrt:
+       dev_err(&adap->dev, "Abort from read\n");
+       mrst_i2c_abort(adap);
+       return -EINVAL;
+}
+
+/**
+ * xfer_write - Internal function to implement master write transfer.
+ * @adap: i2c_adapter struct pointer
+ * @buf: buffer in i2c_msg
+ * @length: number of bytes to be read
+ *
+ * Return Values:
+ * 0   if the read transfer succeeds
+ * -ETIMEDOUT  if cannot read the "raw" interrupt register
+ * -EINVAL     if transfer abort occured
+ *
+ * For every byte, a "WRITE" command will be loaded into IC_DATA_CMD prior to
+ * data transfer. The actual "write" operation will be performed if the
+ * RX_FULL interrupt siganal is occured.
+ *
+ * Note there may be two interrupt signals captured, one should read
+ * IC_RAW_INTR_STAT to seperate between errors and actual data.
+ */
+static int xfer_write(struct i2c_adapter *adap,
+                     unsigned char *buf, int length)
+{
+       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
+           i2c_get_adapdata(adap);
+
+       int i;
+       uint32_t reg_val;
+       unsigned count = 0;
+       uint32_t bit_get = 1 << 2; /* transmit fifo completely empty */
+
+       for (i = 0; i < length; i++)
+               mrst_i2c_write(i2c->base + IC_DATA_CMD,
+                              (uint16_t)(*(buf + i)));
+
+       reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+       while ((reg_val & bit_get) == 0) {
+               if (count++ > MAX_T_POLL_COUNT)
+                       goto write_loop;
+               reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+       }
+
+       udelay(100);
+       reg_val = mrst_i2c_read(i2c->base + IC_RAW_INTR_STAT);
+       if ((reg_val & 0x40) == 0x40)
+               goto write_abrt;
+
+       return 0;
+
+write_loop:
+       dev_err(&adap->dev, "Time out in write\n");
+       return -ETIMEDOUT;
+write_abrt:
+       dev_err(&adap->dev, "Abort from write\n");
+       mrst_i2c_abort(adap);
+       return -EINVAL;
+}
+
+static int mrst_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)i2c_get_adapdata(adap);
+       int err;
+       uint32_t reg_val;
+       uint32_t bit_mask;
+
+       /* Disable device first */
+       err = mrst_i2c_disable(adap);
+       if (err) {
+               dev_err(&adap->dev,
+                       "Cannot disable i2c controller, timeout!\n");
+               return -ETIMEDOUT;
+       }
+
+
+       reg_val = mrst_i2c_read(i2c->base + IC_ENABLE);
+       if (reg_val & 0x1) {
+               dev_dbg(&adap->dev, "i2c busy, can't setup\n");
+               return -EINVAL;
+       }
+
+       /* set the speed mode to standard */
+       reg_val = mrst_i2c_read(i2c->base + IC_CON);
+       if ((reg_val & (1<<1 | 1<<2)) != 1<<1) {
+               dev_dbg(&adap->dev, "set standard mode\n");
+               mrst_i2c_write(i2c->base + IC_CON, (reg_val & (~0x6)) | 1<<1);
+       }
+
+       reg_val = mrst_i2c_read(i2c->base + IC_CON);
+       /* use 7-bit addressing */
+       if ((reg_val & (1<<4)) != 0x0) {
+               dev_dbg(&adap->dev, "set i2c 7 bit address mode\n");
+               mrst_i2c_write(i2c->base + IC_CON, reg_val & (~(1<<4)));
+       }
+
+       /*enable restart conditions */
+       reg_val = mrst_i2c_read(i2c->base + IC_CON);
+       if ((reg_val & (1<<5)) != 1<<5) {
+               dev_dbg(&adap->dev, "enable restart conditions\n");
+               mrst_i2c_write(i2c->base + IC_CON, (reg_val & (~(1 << 5)))
+                              | 1 << 5);
+       }
+
+       /* enable master FSM */
+       reg_val = mrst_i2c_read(i2c->base + IC_CON);
+       dev_dbg(&adap->dev, "ic_con reg_val is 0x%x\n", reg_val);
+       if ((reg_val & (1<<6)) != 1<<6) {
+               dev_dbg(&adap->dev, "enable master FSM\n");
+               mrst_i2c_write(i2c->base + IC_CON, (reg_val & (~(1 << 6)))
+                              | 1<<6);
+               dev_dbg(&adap->dev, "ic_con reg_val is 0x%x\n", reg_val);
+       }
+
+       /* use target address when initiating transfer */
+       reg_val = mrst_i2c_read(i2c->base + IC_TAR);
+       bit_mask = 1 << 11 | 1 << 10;
+
+       if ((reg_val & bit_mask) != 0x0) {
+               dev_dbg(&adap->dev, "WR: use target address when intiating"
+                       "transfer, i2c_tx_target\n");
+               mrst_i2c_write(i2c->base + IC_TAR, reg_val & ~bit_mask);
+       }
+
+       /* set target address to the I2C slave address */
+       dev_dbg(&adap->dev, "set target address to the I2C slave address,"
+               "addr is %x\n", pmsg->addr);
+       mrst_i2c_write(i2c->base + IC_TAR, pmsg->addr
+                      | (pmsg->flags & I2C_M_TEN ? IC_TAR_10BIT_ADDR : 0));
+
+       /* Enable I2C controller */
+       mrst_i2c_write(i2c->base + IC_ENABLE, ENABLE);
+
+       reg_val = mrst_i2c_read(i2c->base + IC_CON);
+
+       return 0;
+}
+
+/**
+ * mrst_i2c_xfer - Main master transfer routine.
+ * @adap: i2c_adapter struct pointer
+ * @pmsg: i2c_msg struct pointer
+ * @num: number of i2c_msg
+ *
+ * Return Values:
+ * +           number of messages transfered
+ * -ETIMEDOUT  If cannot disable I2C controller or read IC_STATUS
+ * -EINVAL     If the address in i2c_msg is invalid
+ *
+ * This function will be registered in i2c-core and exposed to external
+ * I2C clients.
+ * 1. Disable I2C controller
+ * 2. Unmask three interrupts: RX_FULL, TX_EMPTY, TX_ABRT
+ * 3. Check if address in i2c_msg is valid
+ * 4. Enable I2C controller
+ * 5. Perform real transfer (call xfer_read or xfer_write)
+ * 6. Wait until the current transfer is finished(check bus state)
+ * 7. Mask and clear all interrupts
+ */
+static int mrst_i2c_xfer(struct i2c_adapter *adap,
+                        struct i2c_msg *pmsg,
+                        int num)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)i2c_get_adapdata(adap);
+       int i, err;
+
+       dev_dbg(&adap->dev, "mrst_i2c_xfer, process %d msg(s)\n", num);
+       dev_dbg(&adap->dev, KERN_INFO "slave address is %x\n", pmsg->addr);
+
+       /* if number of messages equal 0*/
+       if (num == 0)
+               return 0;
+
+       /* Checked the sanity of passed messages. */
+       if (unlikely(mrst_i2c_invalid_address(&pmsg[0]))) {
+               dev_err(&adap->dev, "Invalid address 0x%03x (%d-bit)\n",
+                       pmsg[0].addr, pmsg[0].flags & I2C_M_TEN ? 10 : 7);
+               return -EINVAL;
+       }
+       for (i = 0; i < num; i++) {
+               /* Message address equal? */
+               if (unlikely(mrst_i2c_address_neq(&pmsg[0], &pmsg[i]))) {
+                       dev_err(&adap->dev, "Invalid address in msg[%d]\n", i);
+                       return -EINVAL;
+               }
+       }
+
+       if (mrst_i2c_setup(adap, pmsg))
+               return -EINVAL;
+
+       for (i = 0; i < num; i++) {
+               dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
+                       pmsg->flags & I2C_M_RD ? "read" : "writ",
+                       pmsg->len, pmsg->len > 1 ? "s" : "",
+                       pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
+
+
+               /* Read or Write */
+               if (pmsg->len && pmsg->buf) {
+                       if (pmsg->flags & I2C_M_RD) {
+                               dev_dbg(&adap->dev, "I2C_M_RD\n");
+                               err = xfer_read(adap, pmsg->buf, pmsg->len);
+                       } else {
+                               dev_dbg(&adap->dev, "I2C_M_WR\n");
+                               err = xfer_write(adap, pmsg->buf, pmsg->len);
+                       }
+                       if (err < 0)
+                               goto err_1;
+               }
+               dev_dbg(&adap->dev, "msg[%d] transfer complete\n", i);
+               pmsg++;         /* next message */
+       }
+       goto exit;
+
+err_1:
+       i = err;
+exit:
+       /* Mask interrupts */
+       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
+       /* Clear all interrupts */
+       mrst_i2c_read(i2c->base + IC_CLR_INTR);
+
+       return i;
+}
+
+static int mrst_gpio_init(int sda, int scl)
+{
+       if (gpio_request(sda, "I2C_SDA"))
+               goto err_sda;
+
+       if (gpio_request(scl, "I2C_SCL"))
+               goto err_scl;
+
+       /* TODO: Wait for Moorestown GPIO driver into upstream to uncomment */
+       /*gpio_alt_func(sda, 1);*/
+       /*gpio_alt_func(scl, 1);*/
+
+       return 0;
+err_scl:
+       gpio_free(sda);
+err_sda:
+       return -1;
+}
+
+static struct pci_device_id mrst_i2c_ids[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0802)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0803)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0804)},
+       {0,}
+};
+MODULE_DEVICE_TABLE(pci, mrst_i2c_ids);
+
+static struct i2c_algorithm mrst_i2c_algorithm = {
+       .master_xfer    = mrst_i2c_xfer,
+       .functionality  = mrst_i2c_func,
+};
+
+static struct pci_driver mrst_i2c_driver = {
+       .name           = "mrst_i2c",
+       .id_table       = mrst_i2c_ids,
+       .probe          = mrst_i2c_probe,
+       .remove         = __devexit_p(mrst_i2c_remove),
+       .suspend        = NULL,
+       .resume         = NULL,
+};
+
+/**
+ * mrst_i2c_probe - I2C controller initialization routine
+ * @dev: pci device
+ * @id: device id
+ *
+ * Return Values:
+ * 0           success
+ * -ENODEV     If cannot allocate pci resource
+ * -ENOMEM     If the register base remapping failed, or
+ *             if kzalloc failed
+ *
+ * Initialization steps:
+ * 1. Request for PCI resource
+ * 2. Remap the start address of PCI resource to register base
+ * 3. Request for device memory region
+ * 4. Fill in the struct members of mrst_i2c_private
+ * 5. Call mrst_i2c_hwinit() for hardware initialization
+ * 6. Read I2C device info table from memory and register into core
+ * 7. Register I2C adapter in i2c-core
+ */
+static int __devinit mrst_i2c_probe(struct pci_dev *dev,
+                                   const struct pci_device_id *id)
+{
+       struct mrst_i2c_private *mrst;
+       struct i2c_adapter *adap;
+       unsigned int start, len;
+       int err, busnum = 0;
+       void __iomem *base = NULL;
+       int gpio_sda = 0, gpio_scl = 0;
+
+       err = pci_enable_device(dev);
+       if (err) {
+               dev_err(&dev->dev, "Failed to enable I2C PCI device (%d)\n",
+                       err);
+               goto exit;
+       }
+
+       /* Determine the address of the I2C area */
+       start = pci_resource_start(dev, DEF_BAR);
+       len = pci_resource_len(dev, DEF_BAR);
+       if (!start || len <= 0) {
+               dev_err(&dev->dev, "Base address initialization failed\n");
+               err = -ENODEV;
+               goto exit;
+       }
+       dev_dbg(&dev->dev, "mrst i2c resource start %x, len=%d\n",
+               start, len);
+       err = pci_request_region(dev, DEF_BAR, mrst_i2c_driver.name);
+       if (err) {
+               dev_err(&dev->dev, "Failed to request I2C region "
+                       "0x%1x-0x%Lx\n", start,
+                       (unsigned long long)pci_resource_end(dev, DEF_BAR));
+               goto exit;
+       }
+
+       base = ioremap_nocache(start, len);
+       if (!base) {
+               dev_err(&dev->dev, "I/O memory remapping failed\n");
+               err = -ENOMEM;
+               goto fail0;
+       }
+
+       /* Allocate the per-device data structure, mrst_i2c_private */
+       mrst = kzalloc(sizeof(struct mrst_i2c_private), GFP_KERNEL);
+       if (mrst == NULL) {
+               dev_err(&dev->dev, "Can't allocate interface!\n");
+               err = -ENOMEM;
+               goto fail1;
+       }
+
+       adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+       if (adap == NULL) {
+               dev_err(&dev->dev, "Can't allocate interface!\n");
+               err = -ENOMEM;
+               goto fail2;
+       }
+
+       /* Initialize struct members */
+       snprintf(adap->name, sizeof(adap->name), "mrst_i2c");
+       adap->owner = THIS_MODULE;
+       adap->algo = &mrst_i2c_algorithm;
+       adap->class = I2C_CLASS_HWMON;
+       adap->dev.parent = &dev->dev;
+       mrst->adap = adap;
+       mrst->base = base;
+       mrst->speed = speed_mode;
+
+       pci_set_drvdata(dev, mrst);
+       i2c_set_adapdata(adap, mrst);
+
+       /* Initialize i2c controller */
+       err = mrst_i2c_hwinit(dev);
+       if (err < 0) {
+               dev_err(&dev->dev, "I2C interface initialization failed\n");
+               goto fail3;
+       }
+
+       switch (id->device) {
+       case 0x0802:
+               dev_dbg(&adap->dev, KERN_INFO "I2C0\n");
+               gpio_sda = GPIO_I2C_0_SDA;
+               gpio_scl = GPIO_I2C_0_SCL;
+               adap->nr = busnum = 0;
+               break;
+       case 0x0803:
+               dev_dbg(&adap->dev, KERN_INFO "I2C1\n");
+               gpio_sda = GPIO_I2C_1_SDA;
+               gpio_scl = GPIO_I2C_1_SCL;
+               adap->nr = busnum = 1;
+               break;
+       case 0x0804:
+               dev_dbg(&adap->dev, KERN_INFO "I2C2\n");
+               gpio_sda = GPIO_I2C_2_SDA;
+               gpio_scl = GPIO_I2C_2_SCL;
+               adap->nr = busnum = 2;
+               break;
+       default:
+               ;
+       }
+
+       /* Config GPIO pin for I2C */
+       err = mrst_gpio_init(gpio_sda, gpio_scl);
+       if (err) {
+               dev_err(&dev->dev, "GPIO %s registration failed\n",
+                       adap->name);
+               goto fail3;
+       }
+
+       /* Register i2c board info */
+       mrst_i2c_register_board_info(dev, busnum);
+
+       /* Adapter registration */
+       err = i2c_add_numbered_adapter(adap);
+       if (err) {
+               dev_err(&dev->dev, "Adapter %s registration failed\n",
+                       adap->name);
+               goto fail3;
+       }
+
+       dev_dbg(&dev->dev, "MRST I2C bus %d driver bind success.\n", busnum);
+       return 0;
+
+fail3:
+       i2c_set_adapdata(adap, NULL);
+       pci_set_drvdata(dev, NULL);
+       kfree(adap);
+fail2:
+       kfree(mrst);
+fail1:
+       iounmap(base);
+fail0:
+       pci_release_region(dev, DEF_BAR);
+exit:
+       return err;
+}
+
+static void __devexit mrst_i2c_remove(struct pci_dev *dev)
+{
+       struct mrst_i2c_private *mrst = (struct mrst_i2c_private *)
+                                       pci_get_drvdata(dev);
+       if (i2c_del_adapter(mrst->adap))
+               dev_err(&dev->dev, "Failed to delete i2c adapter");
+
+       kfree(mrst->mrst_i2c_info);
+       kfree(mrst->data);
+
+       switch (dev->device) {
+       case 0x0802:
+               gpio_free(GPIO_I2C_0_SDA);
+               gpio_free(GPIO_I2C_0_SCL);
+               break;
+       case 0x0803:
+               gpio_free(GPIO_I2C_1_SDA);
+               gpio_free(GPIO_I2C_1_SCL);
+               break;
+       case 0x0804:
+               gpio_free(GPIO_I2C_2_SDA);
+               gpio_free(GPIO_I2C_2_SCL);
+               break;
+       default:
+               break;
+       }
+
+       pci_set_drvdata(dev, NULL);
+       iounmap(mrst->base);
+       kfree(mrst);
+       pci_release_region(dev, DEF_BAR);
+}
+
+static int __init mrst_i2c_init(void)
+{
+       printk(KERN_NOTICE "Moorestown I2C driver %s\n", VERSION);
+       return pci_register_driver(&mrst_i2c_driver);
+}
+
+static void __exit mrst_i2c_exit(void)
+{
+       pci_unregister_driver(&mrst_i2c_driver);
+}
+
+module_init(mrst_i2c_init);
+module_exit(mrst_i2c_exit);
+
+MODULE_AUTHOR("Ba Zheng <zheng.ba@intel.com>");
+MODULE_DESCRIPTION("I2C driver for Moorestown Platform");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(VERSION);
diff --git a/drivers/i2c/busses/i2c-moorestown.h b/drivers/i2c/busses/i2c-moorestown.h
new file mode 100755
index 0000000..3a51bd2
--- /dev/null
+++ b/drivers/i2c/busses/i2c-moorestown.h
@@ -0,0 +1,279 @@
+#ifndef __I2C_MRST_H
+#define __I2C_MRST_H
+
+#include <linux/i2c.h>
+
+/* Update for 2.6.27 kernel by Wen */
+
+/* PCI config table macros */
+/* Offests */
+#define I2C_INFO_TABLE_LENGTH          4
+#define I2C_INFO_DEV_BLOCK             10
+#define I2C_DEV_ADDR                   2
+#define I2C_DEV_IRQ                    4
+#define I2C_DEV_NAME                   6
+#define I2C_DEV_INFO                   22
+/* Length */
+#define HEAD_LENGTH                    10
+#define BLOCK_LENGTH                   32
+#define ADDR_LENGTH                    2
+#define IRQ_LENGTH                     2
+#define NAME_LENGTH                    16
+#define INFO_LENGTH                    10
+
+struct mrst_i2c_private {
+       struct i2c_adapter *adap;
+       /* Register base address */
+       void __iomem *base;
+       /* Speed mode */
+       int speed;
+       struct i2c_board_info *mrst_i2c_info;
+       char (*data)[INFO_LENGTH];
+};
+
+/* Speed mode macros */
+#define STANDARD       100
+#define FAST           25
+#define        HIGH            3
+
+/* Control register */
+#define IC_CON                 0x00
+#define SLV_DIS                        (1 << 6)        /* Disable slave mode */
+#define RESTART                        (1 << 5)        /* Send a Restart condition */
+#define        ADDR_10BIT              (1 << 4)        /* 10-bit addressing */
+#define        STANDARD_MODE           (1 << 1)        /* standard mode */
+#define FAST_MODE              (2 << 1)        /* fast mode */
+#define HIGH_MODE              (3 << 1)        /* high speed mode */
+#define        MASTER_EN               (1 << 0)        /* Master mode */
+
+/* Target address register */
+#define IC_TAR                 0x04
+#define IC_TAR_10BIT_ADDR      (1 << 12)       /* 10-bit addressing */
+#define IC_TAR_SPECIAL         (1 << 11)       /* Perform special I2C cmd */
+#define IC_TAR_GC_OR_START     (1 << 10)       /* 0: Gerneral Call Address */
+                                               /* 1: START BYTE */
+
+/* Slave Address Register */
+#define IC_SAR                 0x08            /* Not used in Master mode */
+
+/* High Speed Master Mode Code Address Register */
+#define IC_HS_MADDR            0x0c
+
+/* Rx/Tx Data Buffer and Command Register */
+#define IC_DATA_CMD            0x10
+#define IC_RD                  (1 << 8)        /* 1: Read 0: Write */
+
+/* Standard Speed Clock SCL High Count Register */
+#define IC_SS_SCL_HCNT         0x14
+
+/* Standard Speed Clock SCL Low Count Register */
+#define IC_SS_SCL_LCNT         0x18
+
+/* Fast Speed Clock SCL High Count Register */
+#define IC_FS_SCL_HCNT         0x1c
+
+/* Fast Spedd Clock SCL Low Count Register */
+#define IC_FS_SCL_LCNT         0x20
+
+/* High Speed Clock SCL High Count Register */
+#define IC_HS_SCL_HCNT         0x24
+
+/* High Speed Clock SCL Low Count Register */
+#define IC_HS_SCL_LCNT         0x28
+
+/* Interrupt Status Register */
+#define IC_INTR_STAT           0x2c            /* Read only */
+#define R_GEN_CALL             (1 << 11)
+#define R_START_DET            (1 << 10)
+#define R_STOP_DET             (1 << 9)
+#define R_ACTIVITY             (1 << 8)
+#define R_RX_DONE              (1 << 7)
+#define        R_TX_ABRT               (1 << 6)
+#define R_RD_REQ               (1 << 5)
+#define R_TX_EMPTY             (1 << 4)
+#define R_TX_OVER              (1 << 3)
+#define        R_RX_FULL               (1 << 2)
+#define        R_RX_OVER               (1 << 1)
+#define R_RX_UNDER             (1 << 0)
+
+/* Interrupt Mask Register */
+#define IC_INTR_MASK           0x30            /* Read and Write */
+#define M_GEN_CALL             (1 << 11)
+#define M_START_DET            (1 << 10)
+#define M_STOP_DET             (1 << 9)
+#define M_ACTIVITY             (1 << 8)
+#define M_RX_DONE              (1 << 7)
+#define        M_TX_ABRT               (1 << 6)
+#define M_RD_REQ               (1 << 5)
+#define M_TX_EMPTY             (1 << 4)
+#define M_TX_OVER              (1 << 3)
+#define        M_RX_FULL               (1 << 2)
+#define        M_RX_OVER               (1 << 1)
+#define M_RX_UNDER             (1 << 0)
+
+/* Raw Interrupt Status Register */
+#define IC_RAW_INTR_STAT       0x34            /* Read Only */
+#define GEN_CALL               (1 << 11)       /* General call */
+#define START_DET              (1 << 10)       /* (RE)START occured */
+#define STOP_DET               (1 << 9)        /* STOP occured */
+#define ACTIVITY               (1 << 8)        /* Bus busy */
+#define RX_DONE                        (1 << 7)        /* Not used in Master mode */
+#define        TX_ABRT                 (1 << 6)        /* Transmit Abort */
+#define RD_REQ                 (1 << 5)        /* Not used in Master mode */
+#define TX_EMPTY               (1 << 4)        /* TX FIFO <= threshold */
+#define TX_OVER                        (1 << 3)        /* TX FIFO overflow */
+#define        RX_FULL                 (1 << 2)        /* RX FIFO >= threshold */
+#define        RX_OVER                 (1 << 1)        /* RX FIFO overflow */
+#define RX_UNDER               (1 << 0)        /* RX FIFO empty */
+
+/* Receive FIFO Threshold Register */
+#define IC_RX_TL               0x38
+
+/* Transmit FIFO Treshold Register */
+#define IC_TX_TL               0x3c
+
+/* Clear Combined and Individual Interrupt Register */
+#define IC_CLR_INTR            0x40
+#define CLR_INTR               (1 << 0)
+
+/* Clear RX_UNDER Interrupt Register */
+#define IC_CLR_RX_UNDER                0x44
+#define CLR_RX_UNDER           (1 << 0)
+
+/* Clear RX_OVER Interrupt Register */
+#define IC_CLR_RX_OVER         0x48
+#define CLR_RX_OVER            (1 << 0)
+
+/* Clear TX_OVER Interrupt Register */
+#define IC_CLR_TX_OVER         0x4c
+#define CLR_TX_OVER            (1 << 0)
+
+#define IC_CLR_RD_REQ          0x50
+
+/* Clear TX_ABRT Interrupt Register */
+#define IC_CLR_TX_ABRT         0x54
+#define CLR_TX_ABRT            (1 << 0)
+
+#define IC_CLR_RX_DONE         0x58
+
+
+/* Clear ACTIVITY Interrupt Register */
+#define IC_CLR_ACTIVITY                0x5c
+#define CLR_ACTIVITY           (1 << 0)
+
+/* Clear STOP_DET Interrupt Register */
+#define IC_CLR_STOP_DET                0x60
+#define CLR_STOP_DET           (1 << 0)
+
+/* Clear START_DET Interrupt Register */
+#define IC_CLR_START_DET       0x64
+#define CLR_START_DET          (1 << 0)
+
+/* Clear GEN_CALL Interrupt Register */
+#define IC_CLR_GEN_CALL                0x68
+#define CLR_GEN_CALL           (1 << 0)
+
+/* Enable Register */
+#define IC_ENABLE              0x6c
+#define ENABLE                 (1 << 0)
+
+/* Status Register */
+#define IC_STATUS              0x70            /* Read Only */
+#define STAT_SLV_ACTIVITY      (1 << 6)        /* Slave not in idle */
+#define STAT_MST_ACTIVITY      (1 << 5)        /* Master not in idle */
+#define STAT_RFF               (1 << 4)        /* RX FIFO Full */
+#define STAT_RFNE              (1 << 3)        /* RX FIFO Not Empty */
+#define STAT_TFE               (1 << 2)        /* TX FIFO Empty */
+#define STAT_TFNF              (1 << 1)        /* TX FIFO Not Full */
+#define STAT_ACTIVITY          (1 << 0)        /* Activity Status */
+
+/* Transmit FIFO Level Register */
+#define IC_TXFLR               0x74            /* Read Only */
+#define TXFLR                  (1 << 0)        /* TX FIFO level */
+
+/* Receive FIFO Level Register */
+#define IC_RXFLR               0x78            /* Read Only */
+#define RXFLR                  (1 << 0)        /* RX FIFO level */
+
+/* Transmit Abort Source Register */
+#define IC_TX_ABRT_SOURCE      0x80
+#define ABRT_SLVRD_INTX                (1 << 15)
+#define ABRT_SLV_ARBLOST       (1 << 14)
+#define ABRT_SLVFLUSH_TXFIFO   (1 << 13)
+#define        ARB_LOST                (1 << 12)
+#define ABRT_MASTER_DIS                (1 << 11)
+#define ABRT_10B_RD_NORSTRT    (1 << 10)
+#define ABRT_SBYTE_NORSTRT     (1 << 9)
+#define ABRT_HS_NORSTRT                (1 << 8)
+#define ABRT_SBYTE_ACKDET      (1 << 7)
+#define ABRT_HS_ACKDET         (1 << 6)
+#define ABRT_GCALL_READ                (1 << 5)
+#define ABRT_GCALL_NOACK       (1 << 4)
+#define ABRT_TXDATA_NOACK      (1 << 3)
+#define ABRT_10ADDR2_NOACK     (1 << 2)
+#define ABRT_10ADDR1_NOACK     (1 << 1)
+#define ABRT_7B_ADDR_NOACK     (1 << 0)
+
+/* Enable Status Register */
+#define IC_ENABLE_STATUS       0x9c
+#define IC_EN                  (1 << 0)        /* I2C in an enabled state */
+
+/* Component Parameter Register 1*/
+#define IC_COMP_PARAM_1                0xf4
+#define APB_DATA_WIDTH         (0x3 << 0)
+
+/* GPIO_PINS */
+#define GPIO_I2C_0_SDA         56
+#define GPIO_I2C_0_SCL         57
+
+#define GPIO_I2C_1_SDA         54
+#define GPIO_I2C_1_SCL         55
+
+#define GPIO_I2C_2_SDA         52
+#define GPIO_I2C_2_SCL         53
+
+/* added by xiaolin --begin */
+#define SS_MIN_SCL_HIGH         4000
+#define SS_MIN_SCL_LOW          4700
+#define FS_MIN_SCL_HIGH         600
+#define FS_MIN_SCL_LOW          1300
+#define HS_MIN_SCL_HIGH_100PF   60
+#define HS_MIN_SCL_LOW_100PF    120
+
+enum mrst_i2c_irq {
+    i2c_irq_none = 0x000,
+    i2c_irq_rx_under = 0x001,
+    i2c_irq_rx_over = 0x002,
+    i2c_irq_rx_full = 0x004,
+    i2c_irq_tx_over = 0x008,
+    i2c_irq_tx_empty = 0x010,
+    i2c_irq_rd_req = 0x020,
+    i2c_irq_tx_abrt = 0x040,
+    i2c_irq_rx_done = 0x080,
+    i2c_irq_activity = 0x100,
+    i2c_irq_stop_det = 0x200,
+    i2c_irq_start_det = 0x400,
+    i2c_irq_gen_call = 0x800,
+    i2c_irq_all = 0xfff
+};
+
+/* Function declarations */
+static int mrst_i2c_disable(struct i2c_adapter *);
+static int __devinit mrst_i2c_hwinit(struct pci_dev *);
+static u32 mrst_i2c_func(struct i2c_adapter *);
+static inline int mrst_i2c_invalid_address(const struct i2c_msg *);
+static inline int mrst_i2c_address_neq(const struct i2c_msg *,
+                                      const struct i2c_msg *);
+static int mrst_i2c_xfer(struct i2c_adapter *,
+                        struct i2c_msg *,
+                        int);
+static int __devinit mrst_i2c_probe(struct pci_dev *,
+                                   const struct pci_device_id *);
+static void __devexit mrst_i2c_remove(struct pci_dev *);
+static int __init mrst_i2c_init(void);
+static void __exit mrst_i2c_exit(void);
+static int xfer_read(struct i2c_adapter *,
+                    unsigned char *, int);
+static int xfer_write(struct i2c_adapter *,
+                     unsigned char *, int);
+#endif /* __I2C_MRST_H */
--
1.5.5.1

>-----Original Message-----
>From: Wang, Wen W
>Sent: 2009年4月23日 18:20
>To: Jean Delvare
>Cc: linux-i2c@vger.kernel.org; Wang, Wen W
>Subject: [PATCH 0/2] I2C: I2C controller driver for Intel Moorestown platform
>
>Hi Jean,
>
>This is a description for the patches:
>1. Patches for I2C controller driver for Intel low power platform "Moorestown".
>2. The driver depends on a GPIO driver for Intel Moorestown platform.
>3. Patch 1 will:
>       a. Add "i2c_moorestown.c" and "i2c_moorestown.h" to kernel directory
>drivers/i2c/busses"
>       b. Add items into kernel files "drivers/i2c/busses/Kconfig" and
>"drivers/i2c/Makefile".
>4. Patch 2 will:
>       a. Modify i2c-boardinfo.c to export i2c_register_board_info() function and add
>code to detect if a device is already in i2c_board_list.
>
>Thanks
>Wen

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 2/2] I2C: I2C controller driver for Intel Moorestown platform
       [not found]           ` <0A882F4D99BBF6449D58E61AAFD7EDD613677A69-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2009-04-23 10:25             ` Wang, Wen W
  0 siblings, 0 replies; 26+ messages in thread
From: Wang, Wen W @ 2009-04-23 10:25 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Wang, Wen W

From 84ad2b6f3e80eca16e9f87eae5389569b9eeed13 Mon Sep 17 00:00:00 2001
From: Wen Wang <wen.w.wang@intel.com>
Date: Thu, 23 Apr 2009 18:15:41 +0800
Subject: [PATCH] Modify the i2c_register_board_info() function:
 1. Export the function out.
 2. Add code to detect if a device is already in i2c_board_list

Signed-off-by: Wen Wang <wen.w.wang@intel.com>
---
 drivers/i2c/i2c-boardinfo.c |   36 +++++++++++++++++++++++++-----------
 1 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/drivers/i2c/i2c-boardinfo.c b/drivers/i2c/i2c-boardinfo.c
index ffb35f0..72bde31 100644
--- a/drivers/i2c/i2c-boardinfo.c
+++ b/drivers/i2c/i2c-boardinfo.c
@@ -57,11 +57,13 @@ EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num);
  * The board info passed can safely be __initdata, but be careful of embedded
  * pointers (for platform_data, functions, etc) since that won't be copied.
  */
-int __init
+int
 i2c_register_board_info(int busnum,
        struct i2c_board_info const *info, unsigned len)
 {
        int status;
+       int flag = 0;
+       struct i2c_devinfo      *devinfo;

        mutex_lock(&__i2c_board_lock);

@@ -69,22 +71,34 @@ i2c_register_board_info(int busnum,
        if (busnum >= __i2c_first_dynamic_bus_num)
                __i2c_first_dynamic_bus_num = busnum + 1;

+       /* Detect if the device is already in i2c_board_list */
        for (status = 0; len; len--, info++) {
-               struct i2c_devinfo      *devinfo;
-
-               devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
-               if (!devinfo) {
-                       pr_debug("i2c-core: can't register boardinfo!\n");
-                       status = -ENOMEM;
-                       break;
+               list_for_each_entry(devinfo, &__i2c_board_list, list) {
+                       if (devinfo->busnum == busnum
+                           && devinfo->board_info.addr == info->addr) {
+                               flag = 1;
+                               break;
+                       }
                }
+               if (flag != 1) {
+                       struct i2c_devinfo      *dev;
+                       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+                       if (!dev) {
+                               pr_debug("i2c-core: can't register"
+                                        "boardinfo!\n");
+                               status = -ENOMEM;
+                               break;
+                       }

-               devinfo->busnum = busnum;
-               devinfo->board_info = *info;
-               list_add_tail(&devinfo->list, &__i2c_board_list);
+                       dev->busnum = busnum;
+                       dev->board_info = *info;
+                       list_add_tail(&dev->list, &__i2c_board_list);
+               }
+               flag = 0;
        }

        mutex_unlock(&__i2c_board_lock);

        return status;
 }
+EXPORT_SYMBOL_GPL(i2c_register_board_info);
--
1.5.5.1


>-----Original Message-----
>From: Wang, Wen W
>Sent: 2009年4月23日 18:23
>To: Jean Delvare
>Cc: linux-i2c@vger.kernel.org; Wang, Wen W
>Subject: [PATCH 1/2] I2C: I2C controller driver for Intel Moorestown platform
>
>From 6c5a5c1ae1977deefa181f883ecfc4efa7c8555b Mon Sep 17 00:00:00 2001
>From: Wen Wang <wen.w.wang@intel.com>
>Date: Thu, 23 Apr 2009 18:11:33 +0800
>Subject: [PATCH] I2C controller driver for Intel Moorestown platform
> Signed-off-by: Wen Wang <wen.w.wang@intel.com>
>
>---
> drivers/i2c/busses/Kconfig          |   10 +
> drivers/i2c/busses/Makefile         |    1 +
> drivers/i2c/busses/i2c-moorestown.c |  973
>+++++++++++++++++++++++++++++++++++
> drivers/i2c/busses/i2c-moorestown.h |  279 ++++++++++
> 4 files changed, 1263 insertions(+), 0 deletions(-)
> create mode 100644 drivers/i2c/busses/i2c-moorestown.c
> create mode 100755 drivers/i2c/busses/i2c-moorestown.h
>
>diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
>index a48c8ae..cf84038 100644
>--- a/drivers/i2c/busses/Kconfig
>+++ b/drivers/i2c/busses/Kconfig
>@@ -738,4 +738,14 @@ config SCx200_ACB
>         This support is also available as a module.  If so, the module
>         will be called scx200_acb.
>
>+config I2C_MOORESTOWN
>+      tristate "Intel Moorestown I2C Controller"
>+      depends on PCI && GPIOLIB
>+      default y
>+      help
>+        If you say yes to this option, support will be included for the Intel
>+        Moorestown chipset I2C controller.
>+        This driver can also be built as a module.  If so, the module
>+        will be called i2c-moorestown.
>+
> endmenu
>diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
>index 776acb6..9d5f89c 100644
>--- a/drivers/i2c/busses/Makefile
>+++ b/drivers/i2c/busses/Makefile
>@@ -69,6 +69,7 @@ obj-$(CONFIG_I2C_SIBYTE)     += i2c-sibyte.o
> obj-$(CONFIG_I2C_STUB)                += i2c-stub.o
> obj-$(CONFIG_SCx200_ACB)      += scx200_acb.o
> obj-$(CONFIG_SCx200_I2C)      += scx200_i2c.o
>+obj-$(CONFIG_I2C_MOORESTOWN)  += i2c-moorestown.o
>
> ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
> EXTRA_CFLAGS += -DDEBUG
>diff --git a/drivers/i2c/busses/i2c-moorestown.c
>b/drivers/i2c/busses/i2c-moorestown.c
>new file mode 100644
>index 0000000..1c314ca
>--- /dev/null
>+++ b/drivers/i2c/busses/i2c-moorestown.c
>@@ -0,0 +1,973 @@
>+/*
>+ * Support for Moorestown I2C controller
>+ *
>+ * Copyright (c) 2009 Intel Corporation.
>+ * Copyright (c) 2009 Synopsys. Inc.
>+ *
>+ * This program is free software; you can redistribute it and/or modify it
>+ * under the terms and conditions of the GNU General Public License, version
>+ * 2, as published by the Free Software Foundation.
>+ *
>+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
>+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
>FITNESS
>+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>more
>+ * details.
>+ *
>+ * You should have received a copy of the GNU General Public License along
>+ * with this program; if not, write to the Free Software Foundation, Inc., 51
>+ * Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
>+ *
>+ */
>+
>+#include <linux/module.h>
>+#include <linux/moduleparam.h>
>+#include <linux/version.h>
>+#include <linux/kernel.h>
>+#include <linux/err.h>
>+#include <linux/slab.h>
>+#include <linux/stat.h>
>+#include <linux/types.h>
>+#include <linux/delay.h>
>+#include <linux/i2c.h>
>+#include <linux/init.h>
>+#include <linux/pci.h>
>+#include <linux/gpio.h>
>+
>+#include <linux/io.h>
>+
>+#include "i2c-moorestown.h"
>+
>+#define MAX_T_POLL_COUNT      4000    /* FIXME */
>+#define DEF_BAR               0
>+#define VERSION               "Version 0.5"
>+
>+#define mrst_i2c_read(reg)            __raw_readl(reg)
>+#define mrst_i2c_write(reg, val)      __raw_writel((val), (reg))
>+
>+static int speed_mode = STANDARD;
>+module_param(speed_mode, int, S_IRUGO);
>+
>+/**
>+ * mrst_i2c_register_board_info - Register I2C device info
>+ * @dev: struct pointer to pci_dev
>+ * @busnum: Bus number to register
>+ *
>+ * Return Value:
>+ * 0          success
>+ * -ENOMEM    if fail to allocate memory
>+ * -ENODEV    if fail to detect the address of I2C device info table
>+ *
>+ * Moorestown I2C device info table is initialized by firmware and the address
>+ * pointer is filled into I2C controller PCI config space BAR 1.
>+ *
>+ * Driver will read this table from memory and register this device table into
>+ * I2C core.
>+ */
>+static int mrst_i2c_register_board_info(struct pci_dev *dev, int busnum)
>+{
>+      struct mrst_i2c_private *mrst = (struct mrst_i2c_private *)
>+                                      pci_get_drvdata(dev);
>+      int err;
>+      unsigned short addr, irq, host;
>+      char *name = NULL;
>+      struct i2c_board_info *info = NULL;
>+      unsigned int addr_off, irq_off, name_off, data_off, host_off;
>+      unsigned int table_len, block_num, block = 0;
>+      int i, j;
>+      unsigned int start, len;
>+      void __iomem *base = NULL, *ptr = NULL;
>+
>+      /* Determine the address of the I2C device info table area */
>+      start = pci_resource_start(dev, 1);
>+      len = pci_resource_len(dev, 1);
>+      if (!start || len <= 0) {
>+              err = -ENODEV;
>+              return err;
>+      }
>+
>+      err = pci_request_region(dev, 1, "mrst_i2c");
>+      if (err) {
>+              dev_err(&dev->dev, "Failed to request I2C region "
>+                      "0x%1x-0x%Lx\n", start,
>+                      (unsigned long long)pci_resource_end(dev, 1));
>+              return err;
>+      }
>+
>+      ptr = ioremap(start, len);
>+      if (!ptr) {
>+              dev_err(&dev->dev, "I/O memory remapping failed\n");
>+              err = -ENOMEM;
>+              goto err0;
>+      }
>+
>+      /*
>+       * Detect if an old firmware is used.
>+       * Newer firmware is using two levels pointer to the device info table
>+       */
>+      if (len == 8) {
>+              start = ioread32(ptr);
>+              len = ioread32(ptr + 4);
>+              iounmap(ptr);
>+              base = ioremap(start, len);
>+      } else
>+              base = ptr;
>+
>+      /* Initialization */
>+      name = kzalloc(sizeof(char) * NAME_LENGTH, GFP_KERNEL);
>+      if (name == NULL) {
>+              err = -ENOMEM;
>+              goto err1;
>+      }
>+
>+      info = kzalloc(sizeof(struct i2c_board_info), GFP_KERNEL);
>+      if (info == NULL) {
>+              dev_err(&dev->dev,
>+                      "Can't allocate interface for i2c_board_info\n");
>+              err = -ENOMEM;
>+              goto err2;
>+      }
>+
>+      /* Get I2C info table length */
>+      table_len = ioread32(base + I2C_INFO_TABLE_LENGTH);
>+
>+      /* Calculate the number of I2C device */
>+      block_num = (table_len - HEAD_LENGTH)/BLOCK_LENGTH;
>+      if (!block_num)
>+              /* No I2C device info */
>+              goto err3;
>+
>+      /* Initialize mrst_i2c_info array */
>+      mrst->mrst_i2c_info = kzalloc(sizeof(struct i2c_board_info) *
>+                                    block_num, GFP_KERNEL);
>+      if (mrst->mrst_i2c_info == NULL) {
>+              dev_err(&dev->dev,
>+                      "Can't allocate interface for i2c_board_info\n");
>+              err = -ENOMEM;
>+              goto err3;
>+      }
>+
>+      mrst->data = kzalloc(sizeof(*mrst->data) * block_num, GFP_KERNEL);
>+      if (mrst->data == NULL) {
>+              dev_err(&dev->dev,
>+                      "Can't allocate interface for per device data\n");
>+              err = -ENOMEM;
>+              goto err4;
>+      }
>+
>+      for (i = 0; i < block_num; i++) {
>+              /* I2C device info block offsets */
>+              host_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i;
>+              addr_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i +
>I2C_DEV_ADDR;
>+              irq_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i + I2C_DEV_IRQ;
>+              name_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i +
>I2C_DEV_NAME;
>+              data_off = I2C_INFO_DEV_BLOCK + BLOCK_LENGTH * i +
>I2C_DEV_INFO;
>+
>+              /* Read PCI config table */
>+              host = ioread16(base + host_off);
>+              if (host != busnum)
>+                      continue;
>+              addr = ioread16(base + addr_off);
>+              irq = ioread16(base + irq_off);
>+              for (j = 0; j < NAME_LENGTH; j++)
>+                      name[j] = ioread8(base + name_off + j);
>+
>+              for (j = 0; j < INFO_LENGTH; j++)
>+                      mrst->data[i][j] = ioread8(base + data_off + j);
>+              dev_dbg(&dev->dev, "I2C device info table: name = %s, address ="
>+                      " %x\n", name, addr);
>+
>+              /* Fill in i2c_board_info struct */
>+              memcpy(info->type, name, NAME_LENGTH);
>+              info->platform_data = mrst->data[i];
>+              info->addr = addr;
>+              info->irq = irq;
>+
>+              /* Add to mrst_i2c_info array */
>+              memcpy(mrst->mrst_i2c_info + block, info,
>+                     sizeof(struct i2c_board_info));
>+              block++;
>+      }
>+
>+      /* Register i2c board info */
>+      err = i2c_register_board_info(busnum, mrst->mrst_i2c_info, block);
>+      goto err3;
>+
>+/* Clean up */
>+err4:
>+      kfree(mrst->mrst_i2c_info);
>+err3:
>+      kfree(info);
>+err2:
>+      kfree(name);
>+err1:
>+      iounmap(base);
>+err0:
>+      pci_release_region(dev, 1);
>+      return err;
>+}
>+
>+/**
>+ * mrst_i2c_disable - Disable I2C controller
>+ * @adap: struct pointer to i2c_adapter
>+ *
>+ * Return Value:
>+ * 0          success
>+ * -EBUSY     if device is busy
>+ * -ETIMEOUT  if i2c cannot be disabled within the given time
>+ *
>+ * I2C bus state should be checked prior to disabling the hardware. If bus is
>+ * not in idle state, an errno is returned. Write "0" to IC_ENABLE to disable
>+ * I2C controller.
>+ */
>+static int mrst_i2c_disable(struct i2c_adapter *adap)
>+{
>+      struct mrst_i2c_private *i2c =
>+          (struct mrst_i2c_private *)i2c_get_adapdata(adap);
>+
>+      int count = 0;
>+
>+      /* Check if device is busy */
>+      dev_dbg(&adap->dev, "mrst i2c disable\n");
>+      while (mrst_i2c_read(i2c->base + IC_STATUS) & 0x1) {
>+              dev_dbg(&adap->dev, "i2c is busy, count is %d\n", count);
>+              if (count++ > 10000)
>+                      return -EBUSY;
>+      }
>+
>+      /* Set IC_ENABLE to 0 */
>+      mrst_i2c_write(i2c->base + IC_ENABLE, 0);
>+
>+      /* Disable all interupts */
>+      mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
>+
>+      /* Clear all interrupts */
>+      mrst_i2c_read(i2c->base + IC_CLR_INTR);
>+
>+      return 0;
>+}
>+
>+/**
>+ * mrst_i2c_hwinit - Initiate the I2C hardware registers. This function will
>+ * be called in mrst_i2c_probe() before device registration.
>+ * @dev: pci device struct pointer
>+ *
>+ * Return Values:
>+ * 0          success
>+ * -EBUSY     i2c cannot be disabled
>+ * -ETIMEDOUT i2c cannot be disabled
>+ * -EFAULT    If APB data width is not 32-bit wide
>+ *
>+ * I2C should be disabled prior to other register operation. If failed, an
>+ * errno is returned. Mask and Clear all interrpts, this should be done at
>+ * first.  Set common registers which will not be modified during normal
>+ * transfers, including: controll register, FIFO threshold and clock freq.
>+ * Check APB data width at last.
>+ */
>+static int  __devinit mrst_i2c_hwinit(struct pci_dev *dev)
>+{
>+      struct mrst_i2c_private *i2c =
>+          (struct mrst_i2c_private *)pci_get_drvdata(dev);
>+      int err = 0;
>+
>+      /* Disable i2c first */
>+      err = mrst_i2c_disable(i2c->adap);
>+      if (err)
>+              return err;
>+
>+      /* Disable all interupts */
>+      mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
>+
>+      /* Clear all interrupts */
>+      mrst_i2c_read(i2c->base + IC_CLR_INTR);
>+
>+      /*
>+       * Setup clock frequency and speed mode
>+       * Enable restart condition,
>+       * enable master FSM, disable slave FSM,
>+       * use target address when initiating transfer
>+       */
>+      switch (speed_mode) {
>+      case STANDARD:
>+              mrst_i2c_write(i2c->base + IC_CON,
>+                             SLV_DIS | RESTART | STANDARD_MODE | MASTER_EN);
>+              mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x75);
>+              mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x7c);
>+              break;
>+      case FAST:
>+              mrst_i2c_write(i2c->base + IC_CON,
>+                             SLV_DIS | RESTART | FAST_MODE | MASTER_EN);
>+              mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x15);
>+              mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x21);
>+              break;
>+      case HIGH:
>+              mrst_i2c_write(i2c->base + IC_CON,
>+                             SLV_DIS | RESTART | HIGH_MODE | MASTER_EN);
>+              mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x7);
>+              mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0xE);
>+              break;
>+      default:
>+              ;
>+      }
>+
>+      /* Set tranmit & receive FIFO threshold to zero */
>+      mrst_i2c_write(i2c->base + IC_RX_TL, 0x3);
>+      mrst_i2c_write(i2c->base + IC_TX_TL, 0x3);
>+
>+      mrst_i2c_write(i2c->base + IC_ENABLE, 1);
>+
>+      return err;
>+}
>+
>+/**
>+ * mrst_i2c_func - Return the supported three I2C operations.
>+ * @adapter: i2c_adapter struct pointer
>+ */
>+static u32 mrst_i2c_func(struct i2c_adapter *adapter)
>+{
>+      return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR |
>I2C_FUNC_SMBUS_EMUL;
>+}
>+
>+/**
>+ * mrst_i2c_invalid_address - To check if the address in i2c message is
>+ * correct.
>+ * @p: i2c_msg struct pointer
>+ *
>+ * Return Values:
>+ * 0  if the address is valid
>+ * 1  if the address is invalid
>+ */
>+static inline int mrst_i2c_invalid_address(const struct i2c_msg *p)
>+{
>+      int ret = ((p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN)
>+                                       && (p->addr > 0x7f)));
>+      return ret;
>+}
>+
>+/**
>+ * mrst_i2c_address_neq - To check if the addresses for different i2c messages
>+ * are equal.
>+ * @p1: first i2c_msg
>+ * @p2: second i2c_msg
>+ *
>+ * Return Values:
>+ * 0   if addresse are equal
>+ * 1   if not equal
>+ *
>+ * Within a single transfer, I2C client may need to send its address more
>+ * than one time. So a check for the address equation is needed.
>+ */
>+static inline int mrst_i2c_address_neq(const struct i2c_msg *p1,
>+                                     const struct i2c_msg *p2)
>+{
>+      int ret = ((p1->addr != p2->addr) || ((p1->flags & (I2C_M_TEN))
>+                                            != ((p2->flags) & (I2C_M_TEN))));
>+      return ret;
>+}
>+
>+/**
>+ * mrst_i2c_abort - To handle transfer abortions and print error messages.
>+ * @adap: i2c_adapter struct pointer
>+ *
>+ * By reading register IC_TX_ABRT_SOURCE, various transfer errors can be
>+ * distingushed. At present, no circumstances have been found out that
>+ * multiple errors would be occured simutaneously, so we simply use the
>+ * register value directly.
>+ *
>+ * At last the error bits are cleared. (Note clear ABRT_SBYTE_NORSTRT bit need
>+ * a few extra steps)
>+ */
>+static void mrst_i2c_abort(struct i2c_adapter *adap)
>+{
>+      struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
>+          i2c_get_adapdata(adap);
>+
>+      /* Read about source register */
>+      int abort = mrst_i2c_read(i2c->base + IC_TX_ABRT_SOURCE);
>+
>+      dev_dbg(&adap->dev, "Abort: ");
>+
>+      /* Single transfer error check:
>+       * According to databook, TX/RX FIFOs would be flushed when
>+       * the abort interrupt occured.
>+       */
>+      switch (abort) {
>+      case (ABRT_MASTER_DIS):
>+              dev_err(&adap->dev,
>+                      "initiate Master operation with Master mode"
>+                      "disabled.\n");
>+
>+              break;
>+      case (ABRT_10B_RD_NORSTRT):
>+              dev_err(&adap->dev,
>+                      "RESTART disabled and master sends READ cmd in 10-BIT"
>+                      "addressing.\n");
>+              break;
>+      case (ABRT_SBYTE_NORSTRT):
>+              dev_err(&adap->dev,
>+                      "RESTART disabled and user is trying to send START"
>+                      "byte.\n");
>+              /* Page 141 data book */
>+              mrst_i2c_write(i2c->base + IC_TX_ABRT_SOURCE,
>+                             !(ABRT_SBYTE_NORSTRT));
>+              mrst_i2c_write(i2c->base + IC_CON, RESTART);
>+              mrst_i2c_write(i2c->base + IC_TAR, !(IC_TAR_SPECIAL));
>+              break;
>+      case (ABRT_SBYTE_ACKDET):
>+              dev_err(&adap->dev,
>+                      "START byte was acknowledged.\n");
>+              break;
>+      case (ABRT_TXDATA_NOACK):
>+              dev_err(&adap->dev,
>+                      "No acknowledge received from slave.\n");
>+              break;
>+      case (ABRT_10ADDR2_NOACK):
>+              dev_err(&adap->dev,
>+                      "The 2nd address byte of 10-bit address not"
>+                      "acknowledged.\n");
>+              break;
>+      case (ABRT_10ADDR1_NOACK):
>+              dev_dbg(&adap->dev,
>+                      "The 1st address byte of 10-bit address not"
>+                      "acknowledged.\n");
>+              break;
>+      case (ABRT_7B_ADDR_NOACK):
>+              dev_err(&adap->dev,
>+                      "7-bit address not acknowledged.\n");
>+              break;
>+      default:
>+              ;;
>+      }
>+
>+      /* Clear TX_ABRT bit */
>+      mrst_i2c_read(i2c->base + IC_CLR_TX_ABRT);
>+}
>+
>+/**
>+ * xfer_read - Internal function to implement master read transfer.
>+ * @adap: i2c_adapter struct pointer
>+ * @buf: buffer in i2c_msg
>+ * @length: number of bytes to be read
>+ *
>+ * Return Values:
>+ * 0          if the read transfer succeeds
>+ * -ETIMEDOUT if cannot read the "raw" interrupt register
>+ * -EINVAL    if transfer abort occured
>+ *
>+ * For every byte, a "READ" command will be loaded into IC_DATA_CMD prior to
>+ * data transfer. The actual "read" operation will be performed if the RX_FULL
>+ * interrupt is occured.
>+ *
>+ * Note there may be two interrupt signals captured, one should read
>+ * IC_RAW_INTR_STAT to seperate between errors and actual data.
>+ */
>+static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
>+{
>+      struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
>+          i2c_get_adapdata(adap);
>+      uint32_t reg_val;
>+      int i = length;
>+      unsigned count = 0;
>+      uint32_t bit_get = 1 << 3; /* receive fifo not empty */
>+
>+      while (i--)
>+              mrst_i2c_write(i2c->base + IC_DATA_CMD, (uint16_t)0x100);
>+
>+      i = length;
>+      while (i--) {
>+              count = 0;
>+              reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
>+              while ((reg_val & bit_get) == 0) {
>+                      reg_val = mrst_i2c_read(i2c->base + IC_RAW_INTR_STAT);
>+                      if ((reg_val & 0x40) == 0x40)
>+                              goto read_abrt;
>+                      reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
>+                      if (count++ > MAX_T_POLL_COUNT)
>+                              goto read_loop;
>+              }
>+
>+              reg_val = mrst_i2c_read(i2c->base + IC_DATA_CMD);
>+              *buf++ = reg_val;
>+      }
>+
>+      return 0;
>+
>+read_loop:
>+      dev_err(&adap->dev, "Time out in read\n");
>+      return -ETIMEDOUT;
>+read_abrt:
>+      dev_err(&adap->dev, "Abort from read\n");
>+      mrst_i2c_abort(adap);
>+      return -EINVAL;
>+}
>+
>+/**
>+ * xfer_write - Internal function to implement master write transfer.
>+ * @adap: i2c_adapter struct pointer
>+ * @buf: buffer in i2c_msg
>+ * @length: number of bytes to be read
>+ *
>+ * Return Values:
>+ * 0  if the read transfer succeeds
>+ * -ETIMEDOUT if cannot read the "raw" interrupt register
>+ * -EINVAL    if transfer abort occured
>+ *
>+ * For every byte, a "WRITE" command will be loaded into IC_DATA_CMD prior to
>+ * data transfer. The actual "write" operation will be performed if the
>+ * RX_FULL interrupt siganal is occured.
>+ *
>+ * Note there may be two interrupt signals captured, one should read
>+ * IC_RAW_INTR_STAT to seperate between errors and actual data.
>+ */
>+static int xfer_write(struct i2c_adapter *adap,
>+                    unsigned char *buf, int length)
>+{
>+      struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
>+          i2c_get_adapdata(adap);
>+
>+      int i;
>+      uint32_t reg_val;
>+      unsigned count = 0;
>+      uint32_t bit_get = 1 << 2; /* transmit fifo completely empty */
>+
>+      for (i = 0; i < length; i++)
>+              mrst_i2c_write(i2c->base + IC_DATA_CMD,
>+                             (uint16_t)(*(buf + i)));
>+
>+      reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
>+      while ((reg_val & bit_get) == 0) {
>+              if (count++ > MAX_T_POLL_COUNT)
>+                      goto write_loop;
>+              reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
>+      }
>+
>+      udelay(100);
>+      reg_val = mrst_i2c_read(i2c->base + IC_RAW_INTR_STAT);
>+      if ((reg_val & 0x40) == 0x40)
>+              goto write_abrt;
>+
>+      return 0;
>+
>+write_loop:
>+      dev_err(&adap->dev, "Time out in write\n");
>+      return -ETIMEDOUT;
>+write_abrt:
>+      dev_err(&adap->dev, "Abort from write\n");
>+      mrst_i2c_abort(adap);
>+      return -EINVAL;
>+}
>+
>+static int mrst_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
>+{
>+      struct mrst_i2c_private *i2c =
>+          (struct mrst_i2c_private *)i2c_get_adapdata(adap);
>+      int err;
>+      uint32_t reg_val;
>+      uint32_t bit_mask;
>+
>+      /* Disable device first */
>+      err = mrst_i2c_disable(adap);
>+      if (err) {
>+              dev_err(&adap->dev,
>+                      "Cannot disable i2c controller, timeout!\n");
>+              return -ETIMEDOUT;
>+      }
>+
>+
>+      reg_val = mrst_i2c_read(i2c->base + IC_ENABLE);
>+      if (reg_val & 0x1) {
>+              dev_dbg(&adap->dev, "i2c busy, can't setup\n");
>+              return -EINVAL;
>+      }
>+
>+      /* set the speed mode to standard */
>+      reg_val = mrst_i2c_read(i2c->base + IC_CON);
>+      if ((reg_val & (1<<1 | 1<<2)) != 1<<1) {
>+              dev_dbg(&adap->dev, "set standard mode\n");
>+              mrst_i2c_write(i2c->base + IC_CON, (reg_val & (~0x6)) | 1<<1);
>+      }
>+
>+      reg_val = mrst_i2c_read(i2c->base + IC_CON);
>+      /* use 7-bit addressing */
>+      if ((reg_val & (1<<4)) != 0x0) {
>+              dev_dbg(&adap->dev, "set i2c 7 bit address mode\n");
>+              mrst_i2c_write(i2c->base + IC_CON, reg_val & (~(1<<4)));
>+      }
>+
>+      /*enable restart conditions */
>+      reg_val = mrst_i2c_read(i2c->base + IC_CON);
>+      if ((reg_val & (1<<5)) != 1<<5) {
>+              dev_dbg(&adap->dev, "enable restart conditions\n");
>+              mrst_i2c_write(i2c->base + IC_CON, (reg_val & (~(1 << 5)))
>+                             | 1 << 5);
>+      }
>+
>+      /* enable master FSM */
>+      reg_val = mrst_i2c_read(i2c->base + IC_CON);
>+      dev_dbg(&adap->dev, "ic_con reg_val is 0x%x\n", reg_val);
>+      if ((reg_val & (1<<6)) != 1<<6) {
>+              dev_dbg(&adap->dev, "enable master FSM\n");
>+              mrst_i2c_write(i2c->base + IC_CON, (reg_val & (~(1 << 6)))
>+                             | 1<<6);
>+              dev_dbg(&adap->dev, "ic_con reg_val is 0x%x\n", reg_val);
>+      }
>+
>+      /* use target address when initiating transfer */
>+      reg_val = mrst_i2c_read(i2c->base + IC_TAR);
>+      bit_mask = 1 << 11 | 1 << 10;
>+
>+      if ((reg_val & bit_mask) != 0x0) {
>+              dev_dbg(&adap->dev, "WR: use target address when intiating"
>+                      "transfer, i2c_tx_target\n");
>+              mrst_i2c_write(i2c->base + IC_TAR, reg_val & ~bit_mask);
>+      }
>+
>+      /* set target address to the I2C slave address */
>+      dev_dbg(&adap->dev, "set target address to the I2C slave address,"
>+              "addr is %x\n", pmsg->addr);
>+      mrst_i2c_write(i2c->base + IC_TAR, pmsg->addr
>+                     | (pmsg->flags & I2C_M_TEN ? IC_TAR_10BIT_ADDR : 0));
>+
>+      /* Enable I2C controller */
>+      mrst_i2c_write(i2c->base + IC_ENABLE, ENABLE);
>+
>+      reg_val = mrst_i2c_read(i2c->base + IC_CON);
>+
>+      return 0;
>+}
>+
>+/**
>+ * mrst_i2c_xfer - Main master transfer routine.
>+ * @adap: i2c_adapter struct pointer
>+ * @pmsg: i2c_msg struct pointer
>+ * @num: number of i2c_msg
>+ *
>+ * Return Values:
>+ * +          number of messages transfered
>+ * -ETIMEDOUT If cannot disable I2C controller or read IC_STATUS
>+ * -EINVAL    If the address in i2c_msg is invalid
>+ *
>+ * This function will be registered in i2c-core and exposed to external
>+ * I2C clients.
>+ * 1. Disable I2C controller
>+ * 2. Unmask three interrupts: RX_FULL, TX_EMPTY, TX_ABRT
>+ * 3. Check if address in i2c_msg is valid
>+ * 4. Enable I2C controller
>+ * 5. Perform real transfer (call xfer_read or xfer_write)
>+ * 6. Wait until the current transfer is finished(check bus state)
>+ * 7. Mask and clear all interrupts
>+ */
>+static int mrst_i2c_xfer(struct i2c_adapter *adap,
>+                       struct i2c_msg *pmsg,
>+                       int num)
>+{
>+      struct mrst_i2c_private *i2c =
>+          (struct mrst_i2c_private *)i2c_get_adapdata(adap);
>+      int i, err;
>+
>+      dev_dbg(&adap->dev, "mrst_i2c_xfer, process %d msg(s)\n", num);
>+      dev_dbg(&adap->dev, KERN_INFO "slave address is %x\n", pmsg->addr);
>+
>+      /* if number of messages equal 0*/
>+      if (num == 0)
>+              return 0;
>+
>+      /* Checked the sanity of passed messages. */
>+      if (unlikely(mrst_i2c_invalid_address(&pmsg[0]))) {
>+              dev_err(&adap->dev, "Invalid address 0x%03x (%d-bit)\n",
>+                      pmsg[0].addr, pmsg[0].flags & I2C_M_TEN ? 10 : 7);
>+              return -EINVAL;
>+      }
>+      for (i = 0; i < num; i++) {
>+              /* Message address equal? */
>+              if (unlikely(mrst_i2c_address_neq(&pmsg[0], &pmsg[i]))) {
>+                      dev_err(&adap->dev, "Invalid address in msg[%d]\n", i);
>+                      return -EINVAL;
>+              }
>+      }
>+
>+      if (mrst_i2c_setup(adap, pmsg))
>+              return -EINVAL;
>+
>+      for (i = 0; i < num; i++) {
>+              dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
>+                      pmsg->flags & I2C_M_RD ? "read" : "writ",
>+                      pmsg->len, pmsg->len > 1 ? "s" : "",
>+                      pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
>+
>+
>+              /* Read or Write */
>+              if (pmsg->len && pmsg->buf) {
>+                      if (pmsg->flags & I2C_M_RD) {
>+                              dev_dbg(&adap->dev, "I2C_M_RD\n");
>+                              err = xfer_read(adap, pmsg->buf, pmsg->len);
>+                      } else {
>+                              dev_dbg(&adap->dev, "I2C_M_WR\n");
>+                              err = xfer_write(adap, pmsg->buf, pmsg->len);
>+                      }
>+                      if (err < 0)
>+                              goto err_1;
>+              }
>+              dev_dbg(&adap->dev, "msg[%d] transfer complete\n", i);
>+              pmsg++;         /* next message */
>+      }
>+      goto exit;
>+
>+err_1:
>+      i = err;
>+exit:
>+      /* Mask interrupts */
>+      mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
>+      /* Clear all interrupts */
>+      mrst_i2c_read(i2c->base + IC_CLR_INTR);
>+
>+      return i;
>+}
>+
>+static int mrst_gpio_init(int sda, int scl)
>+{
>+      if (gpio_request(sda, "I2C_SDA"))
>+              goto err_sda;
>+
>+      if (gpio_request(scl, "I2C_SCL"))
>+              goto err_scl;
>+
>+      /* TODO: Wait for Moorestown GPIO driver into upstream to uncomment */
>+      /*gpio_alt_func(sda, 1);*/
>+      /*gpio_alt_func(scl, 1);*/
>+
>+      return 0;
>+err_scl:
>+      gpio_free(sda);
>+err_sda:
>+      return -1;
>+}
>+
>+static struct pci_device_id mrst_i2c_ids[] = {
>+      {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0802)},
>+      {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0803)},
>+      {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0804)},
>+      {0,}
>+};
>+MODULE_DEVICE_TABLE(pci, mrst_i2c_ids);
>+
>+static struct i2c_algorithm mrst_i2c_algorithm = {
>+      .master_xfer    = mrst_i2c_xfer,
>+      .functionality  = mrst_i2c_func,
>+};
>+
>+static struct pci_driver mrst_i2c_driver = {
>+      .name           = "mrst_i2c",
>+      .id_table       = mrst_i2c_ids,
>+      .probe          = mrst_i2c_probe,
>+      .remove         = __devexit_p(mrst_i2c_remove),
>+      .suspend        = NULL,
>+      .resume         = NULL,
>+};
>+
>+/**
>+ * mrst_i2c_probe - I2C controller initialization routine
>+ * @dev: pci device
>+ * @id: device id
>+ *
>+ * Return Values:
>+ * 0          success
>+ * -ENODEV    If cannot allocate pci resource
>+ * -ENOMEM    If the register base remapping failed, or
>+ *            if kzalloc failed
>+ *
>+ * Initialization steps:
>+ * 1. Request for PCI resource
>+ * 2. Remap the start address of PCI resource to register base
>+ * 3. Request for device memory region
>+ * 4. Fill in the struct members of mrst_i2c_private
>+ * 5. Call mrst_i2c_hwinit() for hardware initialization
>+ * 6. Read I2C device info table from memory and register into core
>+ * 7. Register I2C adapter in i2c-core
>+ */
>+static int __devinit mrst_i2c_probe(struct pci_dev *dev,
>+                                  const struct pci_device_id *id)
>+{
>+      struct mrst_i2c_private *mrst;
>+      struct i2c_adapter *adap;
>+      unsigned int start, len;
>+      int err, busnum = 0;
>+      void __iomem *base = NULL;
>+      int gpio_sda = 0, gpio_scl = 0;
>+
>+      err = pci_enable_device(dev);
>+      if (err) {
>+              dev_err(&dev->dev, "Failed to enable I2C PCI device (%d)\n",
>+                      err);
>+              goto exit;
>+      }
>+
>+      /* Determine the address of the I2C area */
>+      start = pci_resource_start(dev, DEF_BAR);
>+      len = pci_resource_len(dev, DEF_BAR);
>+      if (!start || len <= 0) {
>+              dev_err(&dev->dev, "Base address initialization failed\n");
>+              err = -ENODEV;
>+              goto exit;
>+      }
>+      dev_dbg(&dev->dev, "mrst i2c resource start %x, len=%d\n",
>+              start, len);
>+      err = pci_request_region(dev, DEF_BAR, mrst_i2c_driver.name);
>+      if (err) {
>+              dev_err(&dev->dev, "Failed to request I2C region "
>+                      "0x%1x-0x%Lx\n", start,
>+                      (unsigned long long)pci_resource_end(dev, DEF_BAR));
>+              goto exit;
>+      }
>+
>+      base = ioremap_nocache(start, len);
>+      if (!base) {
>+              dev_err(&dev->dev, "I/O memory remapping failed\n");
>+              err = -ENOMEM;
>+              goto fail0;
>+      }
>+
>+      /* Allocate the per-device data structure, mrst_i2c_private */
>+      mrst = kzalloc(sizeof(struct mrst_i2c_private), GFP_KERNEL);
>+      if (mrst == NULL) {
>+              dev_err(&dev->dev, "Can't allocate interface!\n");
>+              err = -ENOMEM;
>+              goto fail1;
>+      }
>+
>+      adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
>+      if (adap == NULL) {
>+              dev_err(&dev->dev, "Can't allocate interface!\n");
>+              err = -ENOMEM;
>+              goto fail2;
>+      }
>+
>+      /* Initialize struct members */
>+      snprintf(adap->name, sizeof(adap->name), "mrst_i2c");
>+      adap->owner = THIS_MODULE;
>+      adap->algo = &mrst_i2c_algorithm;
>+      adap->class = I2C_CLASS_HWMON;
>+      adap->dev.parent = &dev->dev;
>+      mrst->adap = adap;
>+      mrst->base = base;
>+      mrst->speed = speed_mode;
>+
>+      pci_set_drvdata(dev, mrst);
>+      i2c_set_adapdata(adap, mrst);
>+
>+      /* Initialize i2c controller */
>+      err = mrst_i2c_hwinit(dev);
>+      if (err < 0) {
>+              dev_err(&dev->dev, "I2C interface initialization failed\n");
>+              goto fail3;
>+      }
>+
>+      switch (id->device) {
>+      case 0x0802:
>+              dev_dbg(&adap->dev, KERN_INFO "I2C0\n");
>+              gpio_sda = GPIO_I2C_0_SDA;
>+              gpio_scl = GPIO_I2C_0_SCL;
>+              adap->nr = busnum = 0;
>+              break;
>+      case 0x0803:
>+              dev_dbg(&adap->dev, KERN_INFO "I2C1\n");
>+              gpio_sda = GPIO_I2C_1_SDA;
>+              gpio_scl = GPIO_I2C_1_SCL;
>+              adap->nr = busnum = 1;
>+              break;
>+      case 0x0804:
>+              dev_dbg(&adap->dev, KERN_INFO "I2C2\n");
>+              gpio_sda = GPIO_I2C_2_SDA;
>+              gpio_scl = GPIO_I2C_2_SCL;
>+              adap->nr = busnum = 2;
>+              break;
>+      default:
>+              ;
>+      }
>+
>+      /* Config GPIO pin for I2C */
>+      err = mrst_gpio_init(gpio_sda, gpio_scl);
>+      if (err) {
>+              dev_err(&dev->dev, "GPIO %s registration failed\n",
>+                      adap->name);
>+              goto fail3;
>+      }
>+
>+      /* Register i2c board info */
>+      mrst_i2c_register_board_info(dev, busnum);
>+
>+      /* Adapter registration */
>+      err = i2c_add_numbered_adapter(adap);
>+      if (err) {
>+              dev_err(&dev->dev, "Adapter %s registration failed\n",
>+                      adap->name);
>+              goto fail3;
>+      }
>+
>+      dev_dbg(&dev->dev, "MRST I2C bus %d driver bind success.\n", busnum);
>+      return 0;
>+
>+fail3:
>+      i2c_set_adapdata(adap, NULL);
>+      pci_set_drvdata(dev, NULL);
>+      kfree(adap);
>+fail2:
>+      kfree(mrst);
>+fail1:
>+      iounmap(base);
>+fail0:
>+      pci_release_region(dev, DEF_BAR);
>+exit:
>+      return err;
>+}
>+
>+static void __devexit mrst_i2c_remove(struct pci_dev *dev)
>+{
>+      struct mrst_i2c_private *mrst = (struct mrst_i2c_private *)
>+                                      pci_get_drvdata(dev);
>+      if (i2c_del_adapter(mrst->adap))
>+              dev_err(&dev->dev, "Failed to delete i2c adapter");
>+
>+      kfree(mrst->mrst_i2c_info);
>+      kfree(mrst->data);
>+
>+      switch (dev->device) {
>+      case 0x0802:
>+              gpio_free(GPIO_I2C_0_SDA);
>+              gpio_free(GPIO_I2C_0_SCL);
>+              break;
>+      case 0x0803:
>+              gpio_free(GPIO_I2C_1_SDA);
>+              gpio_free(GPIO_I2C_1_SCL);
>+              break;
>+      case 0x0804:
>+              gpio_free(GPIO_I2C_2_SDA);
>+              gpio_free(GPIO_I2C_2_SCL);
>+              break;
>+      default:
>+              break;
>+      }
>+
>+      pci_set_drvdata(dev, NULL);
>+      iounmap(mrst->base);
>+      kfree(mrst);
>+      pci_release_region(dev, DEF_BAR);
>+}
>+
>+static int __init mrst_i2c_init(void)
>+{
>+      printk(KERN_NOTICE "Moorestown I2C driver %s\n", VERSION);
>+      return pci_register_driver(&mrst_i2c_driver);
>+}
>+
>+static void __exit mrst_i2c_exit(void)
>+{
>+      pci_unregister_driver(&mrst_i2c_driver);
>+}
>+
>+module_init(mrst_i2c_init);
>+module_exit(mrst_i2c_exit);
>+
>+MODULE_AUTHOR("Ba Zheng <zheng.ba@intel.com>");
>+MODULE_DESCRIPTION("I2C driver for Moorestown Platform");
>+MODULE_LICENSE("GPL");
>+MODULE_VERSION(VERSION);
>diff --git a/drivers/i2c/busses/i2c-moorestown.h
>b/drivers/i2c/busses/i2c-moorestown.h
>new file mode 100755
>index 0000000..3a51bd2
>--- /dev/null
>+++ b/drivers/i2c/busses/i2c-moorestown.h
>@@ -0,0 +1,279 @@
>+#ifndef __I2C_MRST_H
>+#define __I2C_MRST_H
>+
>+#include <linux/i2c.h>
>+
>+/* Update for 2.6.27 kernel by Wen */
>+
>+/* PCI config table macros */
>+/* Offests */
>+#define I2C_INFO_TABLE_LENGTH         4
>+#define I2C_INFO_DEV_BLOCK            10
>+#define I2C_DEV_ADDR                  2
>+#define I2C_DEV_IRQ                   4
>+#define I2C_DEV_NAME                  6
>+#define I2C_DEV_INFO                  22
>+/* Length */
>+#define HEAD_LENGTH                   10
>+#define BLOCK_LENGTH                  32
>+#define ADDR_LENGTH                   2
>+#define IRQ_LENGTH                    2
>+#define NAME_LENGTH                   16
>+#define INFO_LENGTH                   10
>+
>+struct mrst_i2c_private {
>+      struct i2c_adapter *adap;
>+      /* Register base address */
>+      void __iomem *base;
>+      /* Speed mode */
>+      int speed;
>+      struct i2c_board_info *mrst_i2c_info;
>+      char (*data)[INFO_LENGTH];
>+};
>+
>+/* Speed mode macros */
>+#define STANDARD      100
>+#define FAST          25
>+#define       HIGH            3
>+
>+/* Control register */
>+#define IC_CON                        0x00
>+#define SLV_DIS                       (1 << 6)        /* Disable slave mode */
>+#define RESTART                       (1 << 5)        /* Send a Restart condition */
>+#define       ADDR_10BIT              (1 << 4)        /* 10-bit addressing */
>+#define       STANDARD_MODE           (1 << 1)        /* standard mode */
>+#define FAST_MODE             (2 << 1)        /* fast mode */
>+#define HIGH_MODE             (3 << 1)        /* high speed mode */
>+#define       MASTER_EN               (1 << 0)        /* Master mode */
>+
>+/* Target address register */
>+#define IC_TAR                        0x04
>+#define IC_TAR_10BIT_ADDR     (1 << 12)       /* 10-bit addressing */
>+#define IC_TAR_SPECIAL                (1 << 11)       /* Perform special I2C cmd */
>+#define IC_TAR_GC_OR_START    (1 << 10)       /* 0: Gerneral Call Address */
>+                                              /* 1: START BYTE */
>+
>+/* Slave Address Register */
>+#define IC_SAR                        0x08            /* Not used in Master mode */
>+
>+/* High Speed Master Mode Code Address Register */
>+#define IC_HS_MADDR           0x0c
>+
>+/* Rx/Tx Data Buffer and Command Register */
>+#define IC_DATA_CMD           0x10
>+#define IC_RD                 (1 << 8)        /* 1: Read 0: Write */
>+
>+/* Standard Speed Clock SCL High Count Register */
>+#define IC_SS_SCL_HCNT                0x14
>+
>+/* Standard Speed Clock SCL Low Count Register */
>+#define IC_SS_SCL_LCNT                0x18
>+
>+/* Fast Speed Clock SCL High Count Register */
>+#define IC_FS_SCL_HCNT                0x1c
>+
>+/* Fast Spedd Clock SCL Low Count Register */
>+#define IC_FS_SCL_LCNT                0x20
>+
>+/* High Speed Clock SCL High Count Register */
>+#define IC_HS_SCL_HCNT                0x24
>+
>+/* High Speed Clock SCL Low Count Register */
>+#define IC_HS_SCL_LCNT                0x28
>+
>+/* Interrupt Status Register */
>+#define IC_INTR_STAT          0x2c            /* Read only */
>+#define R_GEN_CALL            (1 << 11)
>+#define R_START_DET           (1 << 10)
>+#define R_STOP_DET            (1 << 9)
>+#define R_ACTIVITY            (1 << 8)
>+#define R_RX_DONE             (1 << 7)
>+#define       R_TX_ABRT               (1 << 6)
>+#define R_RD_REQ              (1 << 5)
>+#define R_TX_EMPTY            (1 << 4)
>+#define R_TX_OVER             (1 << 3)
>+#define       R_RX_FULL               (1 << 2)
>+#define       R_RX_OVER               (1 << 1)
>+#define R_RX_UNDER            (1 << 0)
>+
>+/* Interrupt Mask Register */
>+#define IC_INTR_MASK          0x30            /* Read and Write */
>+#define M_GEN_CALL            (1 << 11)
>+#define M_START_DET           (1 << 10)
>+#define M_STOP_DET            (1 << 9)
>+#define M_ACTIVITY            (1 << 8)
>+#define M_RX_DONE             (1 << 7)
>+#define       M_TX_ABRT               (1 << 6)
>+#define M_RD_REQ              (1 << 5)
>+#define M_TX_EMPTY            (1 << 4)
>+#define M_TX_OVER             (1 << 3)
>+#define       M_RX_FULL               (1 << 2)
>+#define       M_RX_OVER               (1 << 1)
>+#define M_RX_UNDER            (1 << 0)
>+
>+/* Raw Interrupt Status Register */
>+#define IC_RAW_INTR_STAT      0x34            /* Read Only */
>+#define GEN_CALL              (1 << 11)       /* General call */
>+#define START_DET             (1 << 10)       /* (RE)START occured */
>+#define STOP_DET              (1 << 9)        /* STOP occured */
>+#define ACTIVITY              (1 << 8)        /* Bus busy */
>+#define RX_DONE                       (1 << 7)        /* Not used in Master mode */
>+#define       TX_ABRT                 (1 << 6)        /* Transmit Abort */
>+#define RD_REQ                        (1 << 5)        /* Not used in Master mode */
>+#define TX_EMPTY              (1 << 4)        /* TX FIFO <= threshold */
>+#define TX_OVER                       (1 << 3)        /* TX FIFO overflow */
>+#define       RX_FULL                 (1 << 2)        /* RX FIFO >= threshold */
>+#define       RX_OVER                 (1 << 1)        /* RX FIFO overflow */
>+#define RX_UNDER              (1 << 0)        /* RX FIFO empty */
>+
>+/* Receive FIFO Threshold Register */
>+#define IC_RX_TL              0x38
>+
>+/* Transmit FIFO Treshold Register */
>+#define IC_TX_TL              0x3c
>+
>+/* Clear Combined and Individual Interrupt Register */
>+#define IC_CLR_INTR           0x40
>+#define CLR_INTR              (1 << 0)
>+
>+/* Clear RX_UNDER Interrupt Register */
>+#define IC_CLR_RX_UNDER               0x44
>+#define CLR_RX_UNDER          (1 << 0)
>+
>+/* Clear RX_OVER Interrupt Register */
>+#define IC_CLR_RX_OVER                0x48
>+#define CLR_RX_OVER           (1 << 0)
>+
>+/* Clear TX_OVER Interrupt Register */
>+#define IC_CLR_TX_OVER                0x4c
>+#define CLR_TX_OVER           (1 << 0)
>+
>+#define IC_CLR_RD_REQ                 0x50
>+
>+/* Clear TX_ABRT Interrupt Register */
>+#define IC_CLR_TX_ABRT                0x54
>+#define CLR_TX_ABRT           (1 << 0)
>+
>+#define IC_CLR_RX_DONE                0x58
>+
>+
>+/* Clear ACTIVITY Interrupt Register */
>+#define IC_CLR_ACTIVITY               0x5c
>+#define CLR_ACTIVITY          (1 << 0)
>+
>+/* Clear STOP_DET Interrupt Register */
>+#define IC_CLR_STOP_DET               0x60
>+#define CLR_STOP_DET          (1 << 0)
>+
>+/* Clear START_DET Interrupt Register */
>+#define IC_CLR_START_DET      0x64
>+#define CLR_START_DET         (1 << 0)
>+
>+/* Clear GEN_CALL Interrupt Register */
>+#define IC_CLR_GEN_CALL               0x68
>+#define CLR_GEN_CALL          (1 << 0)
>+
>+/* Enable Register */
>+#define IC_ENABLE             0x6c
>+#define ENABLE                        (1 << 0)
>+
>+/* Status Register */
>+#define IC_STATUS             0x70            /* Read Only */
>+#define STAT_SLV_ACTIVITY     (1 << 6)        /* Slave not in idle */
>+#define STAT_MST_ACTIVITY     (1 << 5)        /* Master not in idle */
>+#define STAT_RFF              (1 << 4)        /* RX FIFO Full */
>+#define STAT_RFNE             (1 << 3)        /* RX FIFO Not Empty */
>+#define STAT_TFE              (1 << 2)        /* TX FIFO Empty */
>+#define STAT_TFNF             (1 << 1)        /* TX FIFO Not Full */
>+#define STAT_ACTIVITY         (1 << 0)        /* Activity Status */
>+
>+/* Transmit FIFO Level Register */
>+#define IC_TXFLR              0x74            /* Read Only */
>+#define TXFLR                 (1 << 0)        /* TX FIFO level */
>+
>+/* Receive FIFO Level Register */
>+#define IC_RXFLR              0x78            /* Read Only */
>+#define RXFLR                 (1 << 0)        /* RX FIFO level */
>+
>+/* Transmit Abort Source Register */
>+#define IC_TX_ABRT_SOURCE     0x80
>+#define ABRT_SLVRD_INTX               (1 << 15)
>+#define ABRT_SLV_ARBLOST      (1 << 14)
>+#define ABRT_SLVFLUSH_TXFIFO  (1 << 13)
>+#define       ARB_LOST                (1 << 12)
>+#define ABRT_MASTER_DIS               (1 << 11)
>+#define ABRT_10B_RD_NORSTRT   (1 << 10)
>+#define ABRT_SBYTE_NORSTRT    (1 << 9)
>+#define ABRT_HS_NORSTRT               (1 << 8)
>+#define ABRT_SBYTE_ACKDET     (1 << 7)
>+#define ABRT_HS_ACKDET                (1 << 6)
>+#define ABRT_GCALL_READ               (1 << 5)
>+#define ABRT_GCALL_NOACK      (1 << 4)
>+#define ABRT_TXDATA_NOACK     (1 << 3)
>+#define ABRT_10ADDR2_NOACK    (1 << 2)
>+#define ABRT_10ADDR1_NOACK    (1 << 1)
>+#define ABRT_7B_ADDR_NOACK    (1 << 0)
>+
>+/* Enable Status Register */
>+#define IC_ENABLE_STATUS      0x9c
>+#define IC_EN                 (1 << 0)        /* I2C in an enabled state */
>+
>+/* Component Parameter Register 1*/
>+#define IC_COMP_PARAM_1               0xf4
>+#define APB_DATA_WIDTH                (0x3 << 0)
>+
>+/* GPIO_PINS */
>+#define GPIO_I2C_0_SDA                56
>+#define GPIO_I2C_0_SCL                57
>+
>+#define GPIO_I2C_1_SDA                54
>+#define GPIO_I2C_1_SCL                55
>+
>+#define GPIO_I2C_2_SDA                52
>+#define GPIO_I2C_2_SCL                53
>+
>+/* added by xiaolin --begin */
>+#define SS_MIN_SCL_HIGH         4000
>+#define SS_MIN_SCL_LOW          4700
>+#define FS_MIN_SCL_HIGH         600
>+#define FS_MIN_SCL_LOW          1300
>+#define HS_MIN_SCL_HIGH_100PF   60
>+#define HS_MIN_SCL_LOW_100PF    120
>+
>+enum mrst_i2c_irq {
>+    i2c_irq_none = 0x000,
>+    i2c_irq_rx_under = 0x001,
>+    i2c_irq_rx_over = 0x002,
>+    i2c_irq_rx_full = 0x004,
>+    i2c_irq_tx_over = 0x008,
>+    i2c_irq_tx_empty = 0x010,
>+    i2c_irq_rd_req = 0x020,
>+    i2c_irq_tx_abrt = 0x040,
>+    i2c_irq_rx_done = 0x080,
>+    i2c_irq_activity = 0x100,
>+    i2c_irq_stop_det = 0x200,
>+    i2c_irq_start_det = 0x400,
>+    i2c_irq_gen_call = 0x800,
>+    i2c_irq_all = 0xfff
>+};
>+
>+/* Function declarations */
>+static int mrst_i2c_disable(struct i2c_adapter *);
>+static int __devinit mrst_i2c_hwinit(struct pci_dev *);
>+static u32 mrst_i2c_func(struct i2c_adapter *);
>+static inline int mrst_i2c_invalid_address(const struct i2c_msg *);
>+static inline int mrst_i2c_address_neq(const struct i2c_msg *,
>+                                     const struct i2c_msg *);
>+static int mrst_i2c_xfer(struct i2c_adapter *,
>+                       struct i2c_msg *,
>+                       int);
>+static int __devinit mrst_i2c_probe(struct pci_dev *,
>+                                  const struct pci_device_id *);
>+static void __devexit mrst_i2c_remove(struct pci_dev *);
>+static int __init mrst_i2c_init(void);
>+static void __exit mrst_i2c_exit(void);
>+static int xfer_read(struct i2c_adapter *,
>+                   unsigned char *, int);
>+static int xfer_write(struct i2c_adapter *,
>+                    unsigned char *, int);
>+#endif /* __I2C_MRST_H */
>--
>1.5.5.1
>
>>-----Original Message-----
>>From: Wang, Wen W
>>Sent: 2009年4月23日 18:20
>>To: Jean Delvare
>>Cc: linux-i2c@vger.kernel.org; Wang, Wen W
>>Subject: [PATCH 0/2] I2C: I2C controller driver for Intel Moorestown platform
>>
>>Hi Jean,
>>
>>This is a description for the patches:
>>1. Patches for I2C controller driver for Intel low power platform "Moorestown".
>>2. The driver depends on a GPIO driver for Intel Moorestown platform.
>>3. Patch 1 will:
>>      a. Add "i2c_moorestown.c" and "i2c_moorestown.h" to kernel directory
>>drivers/i2c/busses"
>>      b. Add items into kernel files "drivers/i2c/busses/Kconfig" and
>>"drivers/i2c/Makefile".
>>4. Patch 2 will:
>>      a. Modify i2c-boardinfo.c to export i2c_register_board_info() function and add
>>code to detect if a device is already in i2c_board_list.
>>
>>Thanks
>>Wen

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]                 ` <0A882F4D99BBF6449D58E61AAFD7EDD613677A5B-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2009-04-23 11:22                   ` Jean Delvare
       [not found]                     ` <20090423132224.25553a5b-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Jean Delvare @ 2009-04-23 11:22 UTC (permalink / raw)
  To: Wang, Wen W; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

On Thu, 23 Apr 2009 17:55:42 +0800, Wang, Wen W wrote:
> Hi Jean,
> 
> >-----Original Message-----
> >From: Jean Delvare [mailto:khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org]
> >Sent: 2009年4月23日 17:30
> >To: Wang, Wen W
> >Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> >Subject: Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
> >
> >Hi Wen,
> >
> >On Thu, 23 Apr 2009 17:00:56 +0800, Wang, Wen W wrote:
> >> Hi Jean,
> >>
> >> This is a description for the patch:
> >> 1. Patch for I2C controller driver for Intel low power platform "Moorestown".
> >> 2. The driver depends on a GPIO driver for Intel Moorestown platform.
> >> 3. The patch will:
> >> 	a. Add i2c_mrst.c and i2c_mrst.h to kernel directory "drivers/i2c/busses"
> >
> >Why such a cryptic name? You know, this isn't MS-DOS, names can be
> >longer than 8 characters ;)
> 
> :-) I can change the name to i2c_moorestown.c

Yes, please.

> >> 	b. Add items into kernel files "drivers/i2c/busses/Kconfig" and
> >"drivers/i2c/Makefile".
> >> 	c. Modify i2c-boardinfo.c to export i2c_register_board_info() function and add
> >code to detect if a device is already in i2c_board_list.
> >
> >This last item should go to a separate patch, so that it can be
> 
> I will separate the patch into two.

Thanks.

> >discussed. It is not clear to me why you would need to export functions
> >nobody else needed to export. It will be easier to review and merge
> >your code if the bus driver itself is in one patch and any required
> >integration changes are in another.
> 
> This is because:
> 1. The I2C driver need to call i2c_register_board_info() to register I2C device info table when loaded.
> 2. To support loadable module, I made such change to i2c_register_board_info().
> 
> I know it’s quite ugly there, but I really can't find a way to do so. Please feel free to teach me.

Which I2C devices are present on the bus, depends on the platform /
system. This really shouldn't go in the bus driver itself, but rather
somewhere in arch/. This is what all other platforms are doing. Just
grep the kernel source tree for "i2c_register_board_info" and you'll
see.

Now I would need to know more about the Moorestown platform.
Traditionally, PC platforms never registered I2C devices at the
platform level because it all depended on the vendor and specific
mainboard model and there were simply too many out there to list them
all. There are a few exceptions to this rule but generally we have been
relying on detection for most I2C devices (EEPROM and hardware
monitoring chips, mainly) on PC SMBus. This approach has its problems
(I2C doesn't have any official detection/identification mechanism) but
overall it works fine.

I would like to understand what makes you believe that the Moorestown
platform is so different from other Intel-based PC systems, that we
should list the I2C devices on all of them and add this knowledge to
the I2C bus driver (or somewhere else in the kernel).

Would Intel be willing to send me one of these Moorestown systems, so
that I can help more with the reviewing/testing of the i2c-moorestown
driver and the implementation of any infrastructure change possibly
required for this platform? This would speed up things a lot, I believe.

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]                     ` <20090423132224.25553a5b-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2009-04-30  7:15                       ` Wang, Wen W
  0 siblings, 0 replies; 26+ messages in thread
From: Wang, Wen W @ 2009-04-30  7:15 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

Hi Jean,

Sorry for my slow response. Just been off last week.

Intel Moorestown platform is designed for MID which is quite different from traditional PC. So I2C devices are present on the bus depended on the platform/system.

I will discuss with our team to see if we can move this part to arch/. Then will get back to you.

For the device, due to the platform has not released, so I have to ask legal first.

Thanks
Wen

>-----Original Message-----
>From: Jean Delvare [mailto:khali@linux-fr.org]
>Sent: 2009年4月23日 19:22
>To: Wang, Wen W
>Cc: linux-i2c@vger.kernel.org
>Subject: Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
>
>On Thu, 23 Apr 2009 17:55:42 +0800, Wang, Wen W wrote:
>> Hi Jean,
>>
>> >-----Original Message-----
>> >From: Jean Delvare [mailto:khali@linux-fr.org]
>> >Sent: 2009年4月23日 17:30
>> >To: Wang, Wen W
>> >Cc: linux-i2c@vger.kernel.org
>> >Subject: Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
>> >
>> >Hi Wen,
>> >
>> >On Thu, 23 Apr 2009 17:00:56 +0800, Wang, Wen W wrote:
>> >> Hi Jean,
>> >>
>> >> This is a description for the patch:
>> >> 1. Patch for I2C controller driver for Intel low power platform "Moorestown".
>> >> 2. The driver depends on a GPIO driver for Intel Moorestown platform.
>> >> 3. The patch will:
>> >> 	a. Add i2c_mrst.c and i2c_mrst.h to kernel directory "drivers/i2c/busses"
>> >
>> >Why such a cryptic name? You know, this isn't MS-DOS, names can be
>> >longer than 8 characters ;)
>>
>> :-) I can change the name to i2c_moorestown.c
>
>Yes, please.
>
>> >> 	b. Add items into kernel files "drivers/i2c/busses/Kconfig" and
>> >"drivers/i2c/Makefile".
>> >> 	c. Modify i2c-boardinfo.c to export i2c_register_board_info() function and
>add
>> >code to detect if a device is already in i2c_board_list.
>> >
>> >This last item should go to a separate patch, so that it can be
>>
>> I will separate the patch into two.
>
>Thanks.
>
>> >discussed. It is not clear to me why you would need to export functions
>> >nobody else needed to export. It will be easier to review and merge
>> >your code if the bus driver itself is in one patch and any required
>> >integration changes are in another.
>>
>> This is because:
>> 1. The I2C driver need to call i2c_register_board_info() to register I2C device info
>table when loaded.
>> 2. To support loadable module, I made such change to i2c_register_board_info().
>>
>> I know it’s quite ugly there, but I really can't find a way to do so. Please feel free to
>teach me.
>
>Which I2C devices are present on the bus, depends on the platform /
>system. This really shouldn't go in the bus driver itself, but rather
>somewhere in arch/. This is what all other platforms are doing. Just
>grep the kernel source tree for "i2c_register_board_info" and you'll
>see.
>
>Now I would need to know more about the Moorestown platform.
>Traditionally, PC platforms never registered I2C devices at the
>platform level because it all depended on the vendor and specific
>mainboard model and there were simply too many out there to list them
>all. There are a few exceptions to this rule but generally we have been
>relying on detection for most I2C devices (EEPROM and hardware
>monitoring chips, mainly) on PC SMBus. This approach has its problems
>(I2C doesn't have any official detection/identification mechanism) but
>overall it works fine.
>
>I would like to understand what makes you believe that the Moorestown
>platform is so different from other Intel-based PC systems, that we
>should list the I2C devices on all of them and add this knowledge to
>the I2C bus driver (or somewhere else in the kernel).
>
>Would Intel be willing to send me one of these Moorestown systems, so
>that I can help more with the reviewing/testing of the i2c-moorestown
>driver and the implementation of any infrastructure change possibly
>required for this platform? This would speed up things a lot, I believe.
>
>--
>Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]       ` <0A882F4D99BBF6449D58E61AAFD7EDD613677A65-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2009-04-23 10:22         ` [PATCH 1/2] " Wang, Wen W
@ 2009-05-14  7:35         ` Wang, Wen W
       [not found]           ` <0A882F4D99BBF6449D58E61AAFD7EDD62876816C-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  1 sibling, 1 reply; 26+ messages in thread
From: Wang, Wen W @ 2009-05-14  7:35 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Wang, Wen W

Hi Jean,

After a long discussion with other engineers, we finally got parsing I2C device info table code out of the I2C controller driver. Here is a description for the patch:

1. Patch for I2C controller driver for Intel low power platform "Moorestown".
2. The driver depends on a GPIO driver for Intel Moorestown platform.
3. Patch is based on Linux 2.6.30-rc5.
4. Patch 1 will:
	a. Add "i2c_moorestown.c" and "i2c_moorestown.h" to kernel directory
"drivers/i2c/busses"
	b. Add items into kernel files "drivers/i2c/busses/Kconfig" and
"drivers/i2c/Makefile".

Code for parsing I2C device info table and register the table into I2C core are moved into a separate platform driver under arch/ directory per your comments.

Thanks
Wen

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]           ` <0A882F4D99BBF6449D58E61AAFD7EDD62876816C-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2009-05-14  7:39             ` Wang, Wen W
       [not found]               ` <0A882F4D99BBF6449D58E61AAFD7EDD628768177-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2009-05-14  7:52             ` [PATCH 0/1] " Jean Delvare
  1 sibling, 1 reply; 26+ messages in thread
From: Wang, Wen W @ 2009-05-14  7:39 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Wang, Wen W

From f5ace22d5aec5e62b6110e3a61f03ca04eaffafb Mon Sep 17 00:00:00 2001
From: Wen Wang <wen.w.wang@intel.com>
Date: Thu, 14 May 2009 14:56:44 +0800
Subject: [PATCH] Patch for Moorestown I2C controller driver
 Signed-off-by: Wen Wang <wen.w.wang@intel.com>

---
 drivers/i2c/busses/Kconfig          |   10 +
 drivers/i2c/busses/Makefile         |    1 +
 drivers/i2c/busses/i2c-moorestown.c |  778 +++++++++++++++++++++++++++++++++++
 drivers/i2c/busses/i2c-moorestown.h |  259 ++++++++++++
 4 files changed, 1048 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-moorestown.c
 create mode 100755 drivers/i2c/busses/i2c-moorestown.h

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index a48c8ae..cf84038 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -738,4 +738,14 @@ config SCx200_ACB
          This support is also available as a module.  If so, the module
          will be called scx200_acb.

+config I2C_MOORESTOWN
+       tristate "Intel Moorestown I2C Controller"
+       depends on PCI && GPIOLIB
+       default y
+       help
+         If you say yes to this option, support will be included for the Intel
+         Moorestown chipset I2C controller.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-moorestown.
+
 endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 776acb6..9d5f89c 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_I2C_SIBYTE)      += i2c-sibyte.o
 obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
+obj-$(CONFIG_I2C_MOORESTOWN)   += i2c-moorestown.o

 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/busses/i2c-moorestown.c b/drivers/i2c/busses/i2c-moorestown.c
new file mode 100644
index 0000000..ab8a619
--- /dev/null
+++ b/drivers/i2c/busses/i2c-moorestown.c
@@ -0,0 +1,778 @@
+/*
+ * Support for Moorestown I2C controller
+ *
+ * Copyright (c) 2009 Intel Corporation.
+ * Copyright (c) 2009 Synopsys. Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License, version
+ * 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include "i2c-moorestown.h"
+
+#define MAX_T_POLL_COUNT       10000   /* FIXME */
+#define DEF_BAR                0
+#define VERSION                "Version 0.5"
+
+#define mrst_i2c_read(reg)             __raw_readl(reg)
+#define mrst_i2c_write(reg, val)       __raw_writel((val), (reg))
+
+static int speed_mode = STANDARD;
+module_param(speed_mode, int, S_IRUGO);
+
+/**
+ * mrst_i2c_disable - Disable I2C controller
+ * @adap: struct pointer to i2c_adapter
+ *
+ * Return Value:
+ * 0           success
+ * -EBUSY      if device is busy
+ * -ETIMEOUT   if i2c cannot be disabled within the given time
+ *
+ * I2C bus state should be checked prior to disabling the hardware. If bus is
+ * not in idle state, an errno is returned. Write "0" to IC_ENABLE to disable
+ * I2C controller.
+ */
+static int mrst_i2c_disable(struct i2c_adapter *adap)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)i2c_get_adapdata(adap);
+       int count = 0;
+
+       /* Check if device is busy */
+       dev_dbg(&adap->dev, "mrst i2c disable\n");
+       while (mrst_i2c_read(i2c->base + IC_STATUS) & 0x1) {
+               dev_dbg(&adap->dev, "i2c is busy, count is %d\n", count);
+               if (count++ > MAX_T_POLL_COUNT)
+                       return -EBUSY;
+       }
+
+       /* Set IC_ENABLE to 0 */
+       mrst_i2c_write(i2c->base + IC_ENABLE, 0);
+
+       /* Disable all interupts */
+       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
+
+       /* Clear all interrupts */
+       mrst_i2c_read(i2c->base + IC_CLR_INTR);
+
+       return 0;
+}
+
+/**
+ * mrst_i2c_hwinit - Initiate the I2C hardware registers. This function will
+ * be called in mrst_i2c_probe() before device registration.
+ * @dev: pci device struct pointer
+ *
+ * Return Values:
+ * 0           success
+ * -EBUSY      i2c cannot be disabled
+ * -ETIMEDOUT  i2c cannot be disabled
+ * -EFAULT     If APB data width is not 32-bit wide
+ *
+ * I2C should be disabled prior to other register operation. If failed, an
+ * errno is returned. Mask and Clear all interrpts, this should be done at
+ * first.  Set common registers which will not be modified during normal
+ * transfers, including: controll register, FIFO threshold and clock freq.
+ * Check APB data width at last.
+ */
+static int  __devinit mrst_i2c_hwinit(struct pci_dev *dev)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)pci_get_drvdata(dev);
+       int err = 0;
+
+       /* Disable i2c first */
+       err = mrst_i2c_disable(i2c->adap);
+       if (err)
+               return err;
+
+       /* Disable all interupts */
+       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
+
+       /* Clear all interrupts */
+       mrst_i2c_read(i2c->base + IC_CLR_INTR);
+
+       /*
+        * Setup clock frequency and speed mode
+        * Enable restart condition,
+        * enable master FSM, disable slave FSM,
+        * use target address when initiating transfer
+        */
+       switch (speed_mode) {
+       case STANDARD:
+               mrst_i2c_write(i2c->base + IC_CON,
+                              SLV_DIS | RESTART | STANDARD_MODE | MASTER_EN);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x75);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x7c);
+               break;
+       case FAST:
+               mrst_i2c_write(i2c->base + IC_CON,
+                              SLV_DIS | RESTART | FAST_MODE | MASTER_EN);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x15);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x21);
+               break;
+       case HIGH:
+               mrst_i2c_write(i2c->base + IC_CON,
+                              SLV_DIS | RESTART | HIGH_MODE | MASTER_EN);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x7);
+               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0xE);
+               break;
+       default:
+               ;
+       }
+
+       /* Set tranmit & receive FIFO threshold to zero */
+       mrst_i2c_write(i2c->base + IC_RX_TL, 0x3);
+       mrst_i2c_write(i2c->base + IC_TX_TL, 0x3);
+
+       mrst_i2c_write(i2c->base + IC_ENABLE, 1);
+
+       return err;
+}
+
+/**
+ * mrst_i2c_func - Return the supported three I2C operations.
+ * @adapter: i2c_adapter struct pointer
+ */
+static u32 mrst_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
+}
+
+/**
+ * mrst_i2c_invalid_address - To check if the address in i2c message is
+ * correct.
+ * @p: i2c_msg struct pointer
+ *
+ * Return Values:
+ * 0   if the address is valid
+ * 1   if the address is invalid
+ */
+static inline int mrst_i2c_invalid_address(const struct i2c_msg *p)
+{
+       int ret = ((p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN)
+                                        && (p->addr > 0x7f)));
+       return ret;
+}
+
+/**
+ * mrst_i2c_address_neq - To check if the addresses for different i2c messages
+ * are equal.
+ * @p1: first i2c_msg
+ * @p2: second i2c_msg
+ *
+ * Return Values:
+ * 0    if addresse are equal
+ * 1    if not equal
+ *
+ * Within a single transfer, I2C client may need to send its address more
+ * than one time. So a check for the address equation is needed.
+ */
+static inline int mrst_i2c_address_neq(const struct i2c_msg *p1,
+                                      const struct i2c_msg *p2)
+{
+       int ret = ((p1->addr != p2->addr) || ((p1->flags & (I2C_M_TEN))
+                                             != ((p2->flags) & (I2C_M_TEN))));
+       return ret;
+}
+
+/**
+ * mrst_i2c_abort - To handle transfer abortions and print error messages.
+ * @adap: i2c_adapter struct pointer
+ *
+ * By reading register IC_TX_ABRT_SOURCE, various transfer errors can be
+ * distingushed. At present, no circumstances have been found out that
+ * multiple errors would be occured simutaneously, so we simply use the
+ * register value directly.
+ *
+ * At last the error bits are cleared. (Note clear ABRT_SBYTE_NORSTRT bit need
+ * a few extra steps)
+ */
+static void mrst_i2c_abort(struct i2c_adapter *adap)
+{
+       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
+           i2c_get_adapdata(adap);
+
+       /* Read about source register */
+       int abort = mrst_i2c_read(i2c->base + IC_TX_ABRT_SOURCE);
+
+       dev_dbg(&adap->dev, "Abort: ");
+
+       /* Single transfer error check:
+        * According to databook, TX/RX FIFOs would be flushed when
+        * the abort interrupt occured.
+        */
+       switch (abort) {
+       case (ABRT_MASTER_DIS):
+               dev_err(&adap->dev,
+                       "initiate Master operation with Master mode"
+                       "disabled.\n");
+
+               break;
+       case (ABRT_10B_RD_NORSTRT):
+               dev_err(&adap->dev,
+                       "RESTART disabled and master sends READ cmd in 10-BIT"
+                       "addressing.\n");
+               break;
+       case (ABRT_SBYTE_NORSTRT):
+               dev_err(&adap->dev,
+                       "RESTART disabled and user is trying to send START"
+                       "byte.\n");
+               /* Page 141 data book */
+               mrst_i2c_write(i2c->base + IC_TX_ABRT_SOURCE,
+                              !(ABRT_SBYTE_NORSTRT));
+               mrst_i2c_write(i2c->base + IC_CON, RESTART);
+               mrst_i2c_write(i2c->base + IC_TAR, !(IC_TAR_SPECIAL));
+               break;
+       case (ABRT_SBYTE_ACKDET):
+               dev_err(&adap->dev,
+                       "START byte was acknowledged.\n");
+               break;
+       case (ABRT_TXDATA_NOACK):
+               dev_err(&adap->dev,
+                       "No acknowledge received from slave.\n");
+               break;
+       case (ABRT_10ADDR2_NOACK):
+               dev_err(&adap->dev,
+                       "The 2nd address byte of 10-bit address not"
+                       "acknowledged.\n");
+               break;
+       case (ABRT_10ADDR1_NOACK):
+               dev_dbg(&adap->dev,
+                       "The 1st address byte of 10-bit address not"
+                       "acknowledged.\n");
+               break;
+       case (ABRT_7B_ADDR_NOACK):
+               dev_err(&adap->dev,
+                       "7-bit address not acknowledged.\n");
+               break;
+       default:
+               ;;
+       }
+
+       /* Clear TX_ABRT bit */
+       mrst_i2c_read(i2c->base + IC_CLR_TX_ABRT);
+}
+
+/**
+ * xfer_read - Internal function to implement master read transfer.
+ * @adap: i2c_adapter struct pointer
+ * @buf: buffer in i2c_msg
+ * @length: number of bytes to be read
+ *
+ * Return Values:
+ * 0           if the read transfer succeeds
+ * -ETIMEDOUT  if cannot read the "raw" interrupt register
+ * -EINVAL     if transfer abort occured
+ *
+ * For every byte, a "READ" command will be loaded into IC_DATA_CMD prior to
+ * data transfer. The actual "read" operation will be performed if the RX_FULL
+ * interrupt is occured.
+ *
+ * Note there may be two interrupt signals captured, one should read
+ * IC_RAW_INTR_STAT to seperate between errors and actual data.
+ */
+static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
+           i2c_get_adapdata(adap);
+       uint32_t reg_val;
+       int i = length;
+       unsigned count = 0;
+       uint32_t bit_get = 1 << 3; /* receive fifo not empty */
+
+       while (i--)
+               mrst_i2c_write(i2c->base + IC_DATA_CMD, (uint16_t)0x100);
+
+       i = length;
+       while (i--) {
+               count = 0;
+               reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+               while ((reg_val & bit_get) == 0) {
+                       reg_val = mrst_i2c_read(i2c->base + IC_RAW_INTR_STAT);
+                       if ((reg_val & 0x40) == 0x40)
+                               goto read_abrt;
+                       reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+                       if (count++ > MAX_T_POLL_COUNT)
+                               goto read_loop;
+               }
+
+               reg_val = mrst_i2c_read(i2c->base + IC_DATA_CMD);
+               *buf++ = reg_val;
+       }
+
+       return 0;
+
+read_loop:
+       dev_err(&adap->dev, "Time out in read\n");
+       return -ETIMEDOUT;
+read_abrt:
+       dev_err(&adap->dev, "Abort from read\n");
+       mrst_i2c_abort(adap);
+       return -EINVAL;
+}
+
+/**
+ * xfer_write - Internal function to implement master write transfer.
+ * @adap: i2c_adapter struct pointer
+ * @buf: buffer in i2c_msg
+ * @length: number of bytes to be read
+ *
+ * Return Values:
+ * 0   if the read transfer succeeds
+ * -ETIMEDOUT  if cannot read the "raw" interrupt register
+ * -EINVAL     if transfer abort occured
+ *
+ * For every byte, a "WRITE" command will be loaded into IC_DATA_CMD prior to
+ * data transfer. The actual "write" operation will be performed if the
+ * RX_FULL interrupt siganal is occured.
+ *
+ * Note there may be two interrupt signals captured, one should read
+ * IC_RAW_INTR_STAT to seperate between errors and actual data.
+ */
+static int xfer_write(struct i2c_adapter *adap,
+                     unsigned char *buf, int length)
+{
+       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
+           i2c_get_adapdata(adap);
+
+       int i;
+       uint32_t reg_val;
+       unsigned count = 0;
+       uint32_t bit_get = 1 << 2; /* transmit fifo completely empty */
+
+       for (i = 0; i < length; i++)
+               mrst_i2c_write(i2c->base + IC_DATA_CMD,
+                              (uint16_t)(*(buf + i)));
+
+       reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+       while ((reg_val & bit_get) == 0) {
+               if (count++ > MAX_T_POLL_COUNT)
+                       goto write_loop;
+               reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
+       }
+
+       udelay(speed_mode);
+       reg_val = mrst_i2c_read(i2c->base + IC_RAW_INTR_STAT);
+       if ((reg_val & 0x40) == 0x40)
+               goto write_abrt;
+
+       return 0;
+
+write_loop:
+       dev_err(&adap->dev, "Time out in write\n");
+       return -ETIMEDOUT;
+write_abrt:
+       dev_err(&adap->dev, "Abort from write\n");
+       mrst_i2c_abort(adap);
+       return -EINVAL;
+}
+
+static int mrst_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)i2c_get_adapdata(adap);
+       int err;
+       uint32_t reg_val;
+
+       /* Disable device first */
+       err = mrst_i2c_disable(adap);
+       if (err) {
+               dev_err(&adap->dev,
+                       "Cannot disable i2c controller, timeout!\n");
+               return -ETIMEDOUT;
+       }
+
+       reg_val = mrst_i2c_read(i2c->base + IC_ENABLE);
+       if (reg_val & 0x1) {
+               dev_dbg(&adap->dev, "i2c busy, can't setup\n");
+               return -EINVAL;
+       }
+
+       /* Note here we have a change */
+       switch (speed_mode) {
+       case STANDARD:
+               reg_val = SLV_DIS | RESTART | STANDARD_MODE | MASTER_EN;
+               break;
+       case FAST:
+               reg_val = SLV_DIS | RESTART | FAST_MODE | MASTER_EN;
+               break;
+       case HIGH:
+               reg_val = SLV_DIS | RESTART | HIGH_MODE | MASTER_EN;
+               break;
+       default:
+               ;
+       }
+
+       reg_val = reg_val | (pmsg->flags & I2C_M_TEN ? 1 : 0) << 4;
+       mrst_i2c_write(i2c->base + IC_CON, reg_val);
+
+       /* set target address to the I2C slave address */
+       dev_dbg(&adap->dev, "set target address to the I2C slave address,"
+               "addr is %x\n", pmsg->addr);
+       reg_val = ((pmsg->addr & 0x3ff) |
+                  (pmsg->flags & I2C_M_TEN ? IC_TAR_10BIT_ADDR : 0));
+       mrst_i2c_write(i2c->base + IC_TAR, reg_val);
+
+       /* Enable I2C controller */
+       mrst_i2c_write(i2c->base + IC_ENABLE, ENABLE);
+
+       return 0;
+}
+
+/**
+ * mrst_i2c_xfer - Main master transfer routine.
+ * @adap: i2c_adapter struct pointer
+ * @pmsg: i2c_msg struct pointer
+ * @num: number of i2c_msg
+ *
+ * Return Values:
+ * +           number of messages transfered
+ * -ETIMEDOUT  If cannot disable I2C controller or read IC_STATUS
+ * -EINVAL     If the address in i2c_msg is invalid
+ *
+ * This function will be registered in i2c-core and exposed to external
+ * I2C clients.
+ * 1. Disable I2C controller
+ * 2. Unmask three interrupts: RX_FULL, TX_EMPTY, TX_ABRT
+ * 3. Check if address in i2c_msg is valid
+ * 4. Enable I2C controller
+ * 5. Perform real transfer (call xfer_read or xfer_write)
+ * 6. Wait until the current transfer is finished(check bus state)
+ * 7. Mask and clear all interrupts
+ */
+static int mrst_i2c_xfer(struct i2c_adapter *adap,
+                        struct i2c_msg *pmsg,
+                        int num)
+{
+       struct mrst_i2c_private *i2c =
+           (struct mrst_i2c_private *)i2c_get_adapdata(adap);
+       int i, err;
+
+       dev_dbg(&adap->dev, "mrst_i2c_xfer, process %d msg(s)\n", num);
+       dev_dbg(&adap->dev, KERN_INFO "slave address is %x\n", pmsg->addr);
+
+       /* if number of messages equal 0*/
+       if (num == 0)
+               return 0;
+
+       /* Checked the sanity of passed messages. */
+       if (unlikely(mrst_i2c_invalid_address(&pmsg[0]))) {
+               dev_err(&adap->dev, "Invalid address 0x%03x (%d-bit)\n",
+                       pmsg[0].addr, pmsg[0].flags & I2C_M_TEN ? 10 : 7);
+               return -EINVAL;
+       }
+       for (i = 0; i < num; i++) {
+               /* Message address equal? */
+               if (unlikely(mrst_i2c_address_neq(&pmsg[0], &pmsg[i]))) {
+                       dev_err(&adap->dev, "Invalid address in msg[%d]\n", i);
+                       return -EINVAL;
+               }
+       }
+
+       if (mrst_i2c_setup(adap, pmsg))
+               return -EINVAL;
+
+       for (i = 0; i < num; i++) {
+               dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
+                       pmsg->flags & I2C_M_RD ? "read" : "writ",
+                       pmsg->len, pmsg->len > 1 ? "s" : "",
+                       pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);
+
+
+               /* Read or Write */
+               if (pmsg->len && pmsg->buf) {
+                       if (pmsg->flags & I2C_M_RD) {
+                               dev_dbg(&adap->dev, "I2C_M_RD\n");
+                               err = xfer_read(adap, pmsg->buf, pmsg->len);
+                       } else {
+                               dev_dbg(&adap->dev, "I2C_M_WR\n");
+                               err = xfer_write(adap, pmsg->buf, pmsg->len);
+                       }
+                       if (err < 0)
+                               goto err_1;
+               }
+               dev_dbg(&adap->dev, "msg[%d] transfer complete\n", i);
+               pmsg++;         /* next message */
+       }
+       goto exit;
+
+err_1:
+       i = err;
+exit:
+       /* Mask interrupts */
+       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
+       /* Clear all interrupts */
+       mrst_i2c_read(i2c->base + IC_CLR_INTR);
+
+       return i;
+}
+
+static int mrst_gpio_init(int sda, int scl)
+{
+       if (gpio_request(sda, "I2C_SDA"))
+               goto err_sda;
+
+       if (gpio_request(scl, "I2C_SCL"))
+               goto err_scl;
+
+       /* TODO: Wait for Moorestown GPIO driver into upstream to uncomment */
+       /*gpio_alt_func(sda, 1);*/
+       /*gpio_alt_func(scl, 1);*/
+
+       return 0;
+err_scl:
+       gpio_free(sda);
+err_sda:
+       return -1;
+}
+
+static struct pci_device_id mrst_i2c_ids[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0802)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0803)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0804)},
+       {0,}
+};
+MODULE_DEVICE_TABLE(pci, mrst_i2c_ids);
+
+static struct i2c_algorithm mrst_i2c_algorithm = {
+       .master_xfer    = mrst_i2c_xfer,
+       .functionality  = mrst_i2c_func,
+};
+
+static struct pci_driver mrst_i2c_driver = {
+       .name           = "mrst_i2c",
+       .id_table       = mrst_i2c_ids,
+       .probe          = mrst_i2c_probe,
+       .remove         = __devexit_p(mrst_i2c_remove),
+       .suspend        = NULL,
+       .resume         = NULL,
+};
+
+/**
+ * mrst_i2c_probe - I2C controller initialization routine
+ * @dev: pci device
+ * @id: device id
+ *
+ * Return Values:
+ * 0           success
+ * -ENODEV     If cannot allocate pci resource
+ * -ENOMEM     If the register base remapping failed, or
+ *             if kzalloc failed
+ *
+ * Initialization steps:
+ * 1. Request for PCI resource
+ * 2. Remap the start address of PCI resource to register base
+ * 3. Request for device memory region
+ * 4. Fill in the struct members of mrst_i2c_private
+ * 5. Call mrst_i2c_hwinit() for hardware initialization
+ * 6. Register I2C adapter in i2c-core
+ */
+static int __devinit mrst_i2c_probe(struct pci_dev *dev,
+                                   const struct pci_device_id *id)
+{
+       struct mrst_i2c_private *mrst;
+       struct i2c_adapter *adap;
+       unsigned int start, len;
+       int err, busnum = 0;
+       void __iomem *base = NULL;
+       int gpio_sda = 0, gpio_scl = 0;
+
+       err = pci_enable_device(dev);
+       if (err) {
+               dev_err(&dev->dev, "Failed to enable I2C PCI device (%d)\n",
+                       err);
+               goto exit;
+       }
+
+       /* Determine the address of the I2C area */
+       start = pci_resource_start(dev, DEF_BAR);
+       len = pci_resource_len(dev, DEF_BAR);
+       if (!start || len <= 0) {
+               dev_err(&dev->dev, "Base address initialization failed\n");
+               err = -ENODEV;
+               goto exit;
+       }
+       dev_dbg(&dev->dev, "mrst i2c resource start %x, len=%d\n",
+               start, len);
+       err = pci_request_region(dev, DEF_BAR, mrst_i2c_driver.name);
+       if (err) {
+               dev_err(&dev->dev, "Failed to request I2C region "
+                       "0x%1x-0x%Lx\n", start,
+                       (unsigned long long)pci_resource_end(dev, DEF_BAR));
+               goto exit;
+       }
+
+       base = ioremap_nocache(start, len);
+       if (!base) {
+               dev_err(&dev->dev, "I/O memory remapping failed\n");
+               err = -ENOMEM;
+               goto fail0;
+       }
+
+       /* Allocate the per-device data structure, mrst_i2c_private */
+       mrst = kzalloc(sizeof(struct mrst_i2c_private), GFP_KERNEL);
+       if (mrst == NULL) {
+               dev_err(&dev->dev, "Can't allocate interface!\n");
+               err = -ENOMEM;
+               goto fail1;
+       }
+
+       adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+       if (adap == NULL) {
+               dev_err(&dev->dev, "Can't allocate interface!\n");
+               err = -ENOMEM;
+               goto fail2;
+       }
+
+       /* Initialize struct members */
+       snprintf(adap->name, sizeof(adap->name), "mrst_i2c");
+       adap->owner = THIS_MODULE;
+       adap->algo = &mrst_i2c_algorithm;
+       adap->class = I2C_CLASS_HWMON;
+       adap->dev.parent = &dev->dev;
+       mrst->adap = adap;
+       mrst->base = base;
+       mrst->speed = speed_mode;
+
+       pci_set_drvdata(dev, mrst);
+       i2c_set_adapdata(adap, mrst);
+
+       /* Initialize i2c controller */
+       err = mrst_i2c_hwinit(dev);
+       if (err < 0) {
+               dev_err(&dev->dev, "I2C interface initialization failed\n");
+               goto fail3;
+       }
+
+       switch (id->device) {
+       case 0x0802:
+               dev_dbg(&adap->dev, KERN_INFO "I2C0\n");
+               gpio_sda = GPIO_I2C_0_SDA;
+               gpio_scl = GPIO_I2C_0_SCL;
+               adap->nr = busnum = 0;
+               break;
+       case 0x0803:
+               dev_dbg(&adap->dev, KERN_INFO "I2C1\n");
+               gpio_sda = GPIO_I2C_1_SDA;
+               gpio_scl = GPIO_I2C_1_SCL;
+               adap->nr = busnum = 1;
+               break;
+       case 0x0804:
+               dev_dbg(&adap->dev, KERN_INFO "I2C2\n");
+               gpio_sda = GPIO_I2C_2_SDA;
+               gpio_scl = GPIO_I2C_2_SCL;
+               adap->nr = busnum = 2;
+               break;
+       default:
+               ;
+       }
+
+       /* Config GPIO pin for I2C */
+       err = mrst_gpio_init(gpio_sda, gpio_scl);
+       if (err) {
+               dev_err(&dev->dev, "GPIO %s registration failed\n",
+                       adap->name);
+               goto fail3;
+       }
+
+       /* Adapter registration */
+       err = i2c_add_numbered_adapter(adap);
+       if (err) {
+               dev_err(&dev->dev, "Adapter %s registration failed\n",
+                       adap->name);
+               goto fail3;
+       }
+
+       dev_dbg(&dev->dev, "MRST I2C bus %d driver bind success.\n", busnum);
+       return 0;
+
+fail3:
+       i2c_set_adapdata(adap, NULL);
+       pci_set_drvdata(dev, NULL);
+       kfree(adap);
+fail2:
+       kfree(mrst);
+fail1:
+       iounmap(base);
+fail0:
+       pci_release_region(dev, DEF_BAR);
+exit:
+       return err;
+}
+
+static void __devexit mrst_i2c_remove(struct pci_dev *dev)
+{
+       struct mrst_i2c_private *mrst = (struct mrst_i2c_private *)
+                                       pci_get_drvdata(dev);
+       if (i2c_del_adapter(mrst->adap))
+               dev_err(&dev->dev, "Failed to delete i2c adapter");
+
+       switch (dev->device) {
+       case 0x0802:
+               gpio_free(GPIO_I2C_0_SDA);
+               gpio_free(GPIO_I2C_0_SCL);
+               break;
+       case 0x0803:
+               gpio_free(GPIO_I2C_1_SDA);
+               gpio_free(GPIO_I2C_1_SCL);
+               break;
+       case 0x0804:
+               gpio_free(GPIO_I2C_2_SDA);
+               gpio_free(GPIO_I2C_2_SCL);
+               break;
+       default:
+               break;
+       }
+
+       pci_set_drvdata(dev, NULL);
+       iounmap(mrst->base);
+       kfree(mrst);
+       pci_release_region(dev, DEF_BAR);
+}
+
+static int __init mrst_i2c_init(void)
+{
+       printk(KERN_NOTICE "Moorestown I2C driver %s\n", VERSION);
+       return pci_register_driver(&mrst_i2c_driver);
+}
+
+static void __exit mrst_i2c_exit(void)
+{
+       pci_unregister_driver(&mrst_i2c_driver);
+}
+
+module_init(mrst_i2c_init);
+module_exit(mrst_i2c_exit);
+
+MODULE_AUTHOR("Ba Zheng <zheng.ba@intel.com>");
+MODULE_DESCRIPTION("I2C driver for Moorestown Platform");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(VERSION);
diff --git a/drivers/i2c/busses/i2c-moorestown.h b/drivers/i2c/busses/i2c-moorestown.h
new file mode 100755
index 0000000..e2645c0
--- /dev/null
+++ b/drivers/i2c/busses/i2c-moorestown.h
@@ -0,0 +1,259 @@
+#ifndef __I2C_MRST_H
+#define __I2C_MRST_H
+
+#include <linux/i2c.h>
+
+struct mrst_i2c_private {
+       struct i2c_adapter *adap;
+       /* Register base address */
+       void __iomem *base;
+       /* Speed mode */
+       int speed;
+};
+
+/* Speed mode macros */
+#define STANDARD       100
+#define FAST           25
+#define        HIGH            3
+
+/* Control register */
+#define IC_CON                 0x00
+#define SLV_DIS                        (1 << 6)        /* Disable slave mode */
+#define RESTART                        (1 << 5)        /* Send a Restart condition */
+#define        ADDR_10BIT              (1 << 4)        /* 10-bit addressing */
+#define        STANDARD_MODE           (1 << 1)        /* standard mode */
+#define FAST_MODE              (2 << 1)        /* fast mode */
+#define HIGH_MODE              (3 << 1)        /* high speed mode */
+#define        MASTER_EN               (1 << 0)        /* Master mode */
+
+/* Target address register */
+#define IC_TAR                 0x04
+#define IC_TAR_10BIT_ADDR      (1 << 12)       /* 10-bit addressing */
+#define IC_TAR_SPECIAL         (1 << 11)       /* Perform special I2C cmd */
+#define IC_TAR_GC_OR_START     (1 << 10)       /* 0: Gerneral Call Address */
+                                               /* 1: START BYTE */
+
+/* Slave Address Register */
+#define IC_SAR                 0x08            /* Not used in Master mode */
+
+/* High Speed Master Mode Code Address Register */
+#define IC_HS_MADDR            0x0c
+
+/* Rx/Tx Data Buffer and Command Register */
+#define IC_DATA_CMD            0x10
+#define IC_RD                  (1 << 8)        /* 1: Read 0: Write */
+
+/* Standard Speed Clock SCL High Count Register */
+#define IC_SS_SCL_HCNT         0x14
+
+/* Standard Speed Clock SCL Low Count Register */
+#define IC_SS_SCL_LCNT         0x18
+
+/* Fast Speed Clock SCL High Count Register */
+#define IC_FS_SCL_HCNT         0x1c
+
+/* Fast Spedd Clock SCL Low Count Register */
+#define IC_FS_SCL_LCNT         0x20
+
+/* High Speed Clock SCL High Count Register */
+#define IC_HS_SCL_HCNT         0x24
+
+/* High Speed Clock SCL Low Count Register */
+#define IC_HS_SCL_LCNT         0x28
+
+/* Interrupt Status Register */
+#define IC_INTR_STAT           0x2c            /* Read only */
+#define R_GEN_CALL             (1 << 11)
+#define R_START_DET            (1 << 10)
+#define R_STOP_DET             (1 << 9)
+#define R_ACTIVITY             (1 << 8)
+#define R_RX_DONE              (1 << 7)
+#define        R_TX_ABRT               (1 << 6)
+#define R_RD_REQ               (1 << 5)
+#define R_TX_EMPTY             (1 << 4)
+#define R_TX_OVER              (1 << 3)
+#define        R_RX_FULL               (1 << 2)
+#define        R_RX_OVER               (1 << 1)
+#define R_RX_UNDER             (1 << 0)
+
+/* Interrupt Mask Register */
+#define IC_INTR_MASK           0x30            /* Read and Write */
+#define M_GEN_CALL             (1 << 11)
+#define M_START_DET            (1 << 10)
+#define M_STOP_DET             (1 << 9)
+#define M_ACTIVITY             (1 << 8)
+#define M_RX_DONE              (1 << 7)
+#define        M_TX_ABRT               (1 << 6)
+#define M_RD_REQ               (1 << 5)
+#define M_TX_EMPTY             (1 << 4)
+#define M_TX_OVER              (1 << 3)
+#define        M_RX_FULL               (1 << 2)
+#define        M_RX_OVER               (1 << 1)
+#define M_RX_UNDER             (1 << 0)
+
+/* Raw Interrupt Status Register */
+#define IC_RAW_INTR_STAT       0x34            /* Read Only */
+#define GEN_CALL               (1 << 11)       /* General call */
+#define START_DET              (1 << 10)       /* (RE)START occured */
+#define STOP_DET               (1 << 9)        /* STOP occured */
+#define ACTIVITY               (1 << 8)        /* Bus busy */
+#define RX_DONE                        (1 << 7)        /* Not used in Master mode */
+#define        TX_ABRT                 (1 << 6)        /* Transmit Abort */
+#define RD_REQ                 (1 << 5)        /* Not used in Master mode */
+#define TX_EMPTY               (1 << 4)        /* TX FIFO <= threshold */
+#define TX_OVER                        (1 << 3)        /* TX FIFO overflow */
+#define        RX_FULL                 (1 << 2)        /* RX FIFO >= threshold */
+#define        RX_OVER                 (1 << 1)        /* RX FIFO overflow */
+#define RX_UNDER               (1 << 0)        /* RX FIFO empty */
+
+/* Receive FIFO Threshold Register */
+#define IC_RX_TL               0x38
+
+/* Transmit FIFO Treshold Register */
+#define IC_TX_TL               0x3c
+
+/* Clear Combined and Individual Interrupt Register */
+#define IC_CLR_INTR            0x40
+#define CLR_INTR               (1 << 0)
+
+/* Clear RX_UNDER Interrupt Register */
+#define IC_CLR_RX_UNDER                0x44
+#define CLR_RX_UNDER           (1 << 0)
+
+/* Clear RX_OVER Interrupt Register */
+#define IC_CLR_RX_OVER         0x48
+#define CLR_RX_OVER            (1 << 0)
+
+/* Clear TX_OVER Interrupt Register */
+#define IC_CLR_TX_OVER         0x4c
+#define CLR_TX_OVER            (1 << 0)
+
+#define IC_CLR_RD_REQ          0x50
+
+/* Clear TX_ABRT Interrupt Register */
+#define IC_CLR_TX_ABRT         0x54
+#define CLR_TX_ABRT            (1 << 0)
+
+#define IC_CLR_RX_DONE         0x58
+
+
+/* Clear ACTIVITY Interrupt Register */
+#define IC_CLR_ACTIVITY                0x5c
+#define CLR_ACTIVITY           (1 << 0)
+
+/* Clear STOP_DET Interrupt Register */
+#define IC_CLR_STOP_DET                0x60
+#define CLR_STOP_DET           (1 << 0)
+
+/* Clear START_DET Interrupt Register */
+#define IC_CLR_START_DET       0x64
+#define CLR_START_DET          (1 << 0)
+
+/* Clear GEN_CALL Interrupt Register */
+#define IC_CLR_GEN_CALL                0x68
+#define CLR_GEN_CALL           (1 << 0)
+
+/* Enable Register */
+#define IC_ENABLE              0x6c
+#define ENABLE                 (1 << 0)
+
+/* Status Register */
+#define IC_STATUS              0x70            /* Read Only */
+#define STAT_SLV_ACTIVITY      (1 << 6)        /* Slave not in idle */
+#define STAT_MST_ACTIVITY      (1 << 5)        /* Master not in idle */
+#define STAT_RFF               (1 << 4)        /* RX FIFO Full */
+#define STAT_RFNE              (1 << 3)        /* RX FIFO Not Empty */
+#define STAT_TFE               (1 << 2)        /* TX FIFO Empty */
+#define STAT_TFNF              (1 << 1)        /* TX FIFO Not Full */
+#define STAT_ACTIVITY          (1 << 0)        /* Activity Status */
+
+/* Transmit FIFO Level Register */
+#define IC_TXFLR               0x74            /* Read Only */
+#define TXFLR                  (1 << 0)        /* TX FIFO level */
+
+/* Receive FIFO Level Register */
+#define IC_RXFLR               0x78            /* Read Only */
+#define RXFLR                  (1 << 0)        /* RX FIFO level */
+
+/* Transmit Abort Source Register */
+#define IC_TX_ABRT_SOURCE      0x80
+#define ABRT_SLVRD_INTX                (1 << 15)
+#define ABRT_SLV_ARBLOST       (1 << 14)
+#define ABRT_SLVFLUSH_TXFIFO   (1 << 13)
+#define        ARB_LOST                (1 << 12)
+#define ABRT_MASTER_DIS                (1 << 11)
+#define ABRT_10B_RD_NORSTRT    (1 << 10)
+#define ABRT_SBYTE_NORSTRT     (1 << 9)
+#define ABRT_HS_NORSTRT                (1 << 8)
+#define ABRT_SBYTE_ACKDET      (1 << 7)
+#define ABRT_HS_ACKDET         (1 << 6)
+#define ABRT_GCALL_READ                (1 << 5)
+#define ABRT_GCALL_NOACK       (1 << 4)
+#define ABRT_TXDATA_NOACK      (1 << 3)
+#define ABRT_10ADDR2_NOACK     (1 << 2)
+#define ABRT_10ADDR1_NOACK     (1 << 1)
+#define ABRT_7B_ADDR_NOACK     (1 << 0)
+
+/* Enable Status Register */
+#define IC_ENABLE_STATUS       0x9c
+#define IC_EN                  (1 << 0)        /* I2C in an enabled state */
+
+/* Component Parameter Register 1*/
+#define IC_COMP_PARAM_1                0xf4
+#define APB_DATA_WIDTH         (0x3 << 0)
+
+/* GPIO_PINS */
+#define GPIO_I2C_0_SDA         56
+#define GPIO_I2C_0_SCL         57
+
+#define GPIO_I2C_1_SDA         54
+#define GPIO_I2C_1_SCL         55
+
+#define GPIO_I2C_2_SDA         52
+#define GPIO_I2C_2_SCL         53
+
+/* added by xiaolin --begin */
+#define SS_MIN_SCL_HIGH         4000
+#define SS_MIN_SCL_LOW          4700
+#define FS_MIN_SCL_HIGH         600
+#define FS_MIN_SCL_LOW          1300
+#define HS_MIN_SCL_HIGH_100PF   60
+#define HS_MIN_SCL_LOW_100PF    120
+
+enum mrst_i2c_irq {
+    i2c_irq_none = 0x000,
+    i2c_irq_rx_under = 0x001,
+    i2c_irq_rx_over = 0x002,
+    i2c_irq_rx_full = 0x004,
+    i2c_irq_tx_over = 0x008,
+    i2c_irq_tx_empty = 0x010,
+    i2c_irq_rd_req = 0x020,
+    i2c_irq_tx_abrt = 0x040,
+    i2c_irq_rx_done = 0x080,
+    i2c_irq_activity = 0x100,
+    i2c_irq_stop_det = 0x200,
+    i2c_irq_start_det = 0x400,
+    i2c_irq_gen_call = 0x800,
+    i2c_irq_all = 0xfff
+};
+
+/* Function declarations */
+static int mrst_i2c_disable(struct i2c_adapter *);
+static int __devinit mrst_i2c_hwinit(struct pci_dev *);
+static u32 mrst_i2c_func(struct i2c_adapter *);
+static inline int mrst_i2c_invalid_address(const struct i2c_msg *);
+static inline int mrst_i2c_address_neq(const struct i2c_msg *,
+                                      const struct i2c_msg *);
+static int mrst_i2c_xfer(struct i2c_adapter *,
+                        struct i2c_msg *,
+                        int);
+static int __devinit mrst_i2c_probe(struct pci_dev *,
+                                   const struct pci_device_id *);
+static void __devexit mrst_i2c_remove(struct pci_dev *);
+static int __init mrst_i2c_init(void);
+static void __exit mrst_i2c_exit(void);
+static int xfer_read(struct i2c_adapter *,
+                    unsigned char *, int);
+static int xfer_write(struct i2c_adapter *,
+                     unsigned char *, int);
+#endif /* __I2C_MRST_H */
--
1.5.5.1


>-----Original Message-----
>From: Wang, Wen W
>Sent: 2009年5月14日 15:36
>To: Jean Delvare
>Cc: linux-i2c@vger.kernel.org; Wang, Wen W
>Subject: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
>
>Hi Jean,
>
>After a long discussion with other engineers, we finally got parsing I2C device info
>table code out of the I2C controller driver. Here is a description for the patch:
>
>1. Patch for I2C controller driver for Intel low power platform "Moorestown".
>2. The driver depends on a GPIO driver for Intel Moorestown platform.
>3. Patch is based on Linux 2.6.30-rc5.
>4. Patch 1 will:
>       a. Add "i2c_moorestown.c" and "i2c_moorestown.h" to kernel directory
>"drivers/i2c/busses"
>       b. Add items into kernel files "drivers/i2c/busses/Kconfig" and
>"drivers/i2c/Makefile".
>
>Code for parsing I2C device info table and register the table into I2C core are moved
>into a separate platform driver under arch/ directory per your comments.
>
>Thanks
>Wen

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]           ` <0A882F4D99BBF6449D58E61AAFD7EDD62876816C-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2009-05-14  7:39             ` [PATCH 1/1] " Wang, Wen W
@ 2009-05-14  7:52             ` Jean Delvare
       [not found]               ` <20090514095201.577b17c4-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  1 sibling, 1 reply; 26+ messages in thread
From: Jean Delvare @ 2009-05-14  7:52 UTC (permalink / raw)
  To: Wang, Wen W; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

Hi Wen,

On Thu, 14 May 2009 15:35:37 +0800, Wang, Wen W wrote:
> Hi Jean,
> 
> After a long discussion with other engineers, we finally got parsing I2C device info table code out of the I2C controller driver. Here is a description for the patch:
> 
> 1. Patch for I2C controller driver for Intel low power platform "Moorestown".
> 2. The driver depends on a GPIO driver for Intel Moorestown platform.
> 3. Patch is based on Linux 2.6.30-rc5.
> 4. Patch 1 will:
> 	a. Add "i2c_moorestown.c" and "i2c_moorestown.h" to kernel directory
> "drivers/i2c/busses"
> 	b. Add items into kernel files "drivers/i2c/busses/Kconfig" and
> "drivers/i2c/Makefile".
> 
> Code for parsing I2C device info table and register the table into I2C core are moved into a separate platform driver under arch/ directory per your comments.

Very good, thank you.

Any news on the possibility to get me a piece of hardware to test the
code?

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]               ` <20090514095201.577b17c4-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2009-05-14 10:50                 ` Wang, Wen W
  2009-05-27  2:06                 ` Wang, Wen W
  1 sibling, 0 replies; 26+ messages in thread
From: Wang, Wen W @ 2009-05-14 10:50 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

Hi Jean

>-----Original Message-----
>From: Jean Delvare [mailto:khali@linux-fr.org]
>Sent: 2009年5月14日 15:52
>To: Wang, Wen W
>Cc: linux-i2c@vger.kernel.org
>Subject: Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
>
>Hi Wen,
>
>On Thu, 14 May 2009 15:35:37 +0800, Wang, Wen W wrote:
>> Hi Jean,
>>
>> After a long discussion with other engineers, we finally got parsing I2C device info
>table code out of the I2C controller driver. Here is a description for the patch:
>>
>> 1. Patch for I2C controller driver for Intel low power platform "Moorestown".
>> 2. The driver depends on a GPIO driver for Intel Moorestown platform.
>> 3. Patch is based on Linux 2.6.30-rc5.
>> 4. Patch 1 will:
>> 	a. Add "i2c_moorestown.c" and "i2c_moorestown.h" to kernel directory
>> "drivers/i2c/busses"
>> 	b. Add items into kernel files "drivers/i2c/busses/Kconfig" and
>> "drivers/i2c/Makefile".
>>
>> Code for parsing I2C device info table and register the table into I2C core are
>moved into a separate platform driver under arch/ directory per your comments.
>
>Very good, thank you.
>
>Any news on the possibility to get me a piece of hardware to test the
>code?

Really sorry about that. Currently we can not share the board to external. :(

Please feel free to let me know what else I can do to help you review the code.

>--
>Jean Delvare

Thanks
Wen

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]               ` <20090514095201.577b17c4-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  2009-05-14 10:50                 ` Wang, Wen W
@ 2009-05-27  2:06                 ` Wang, Wen W
       [not found]                   ` <0A882F4D99BBF6449D58E61AAFD7EDD62EEF13AC-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  1 sibling, 1 reply; 26+ messages in thread
From: Wang, Wen W @ 2009-05-27  2:06 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, Wang, Wen W

Hi Jean,

Can you please help provide the status of the I2C controller driver submission? I'm trying to understand the gap and be willing to fix it to get it accepted.

Thanks
Wen

>-----Original Message-----
>From: Jean Delvare [mailto:khali@linux-fr.org]
>Sent: 2009年5月14日 15:52
>To: Wang, Wen W
>Cc: linux-i2c@vger.kernel.org
>Subject: Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
>
>Hi Wen,
>
>On Thu, 14 May 2009 15:35:37 +0800, Wang, Wen W wrote:
>> Hi Jean,
>>
>> After a long discussion with other engineers, we finally got parsing I2C device info
>table code out of the I2C controller driver. Here is a description for the patch:
>>
>> 1. Patch for I2C controller driver for Intel low power platform "Moorestown".
>> 2. The driver depends on a GPIO driver for Intel Moorestown platform.
>> 3. Patch is based on Linux 2.6.30-rc5.
>> 4. Patch 1 will:
>> 	a. Add "i2c_moorestown.c" and "i2c_moorestown.h" to kernel directory
>> "drivers/i2c/busses"
>> 	b. Add items into kernel files "drivers/i2c/busses/Kconfig" and
>> "drivers/i2c/Makefile".
>>
>> Code for parsing I2C device info table and register the table into I2C core are
>moved into a separate platform driver under arch/ directory per your comments.
>
>Very good, thank you.
>
>Any news on the possibility to get me a piece of hardware to test the
>code?
>
>--
>Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]                   ` <0A882F4D99BBF6449D58E61AAFD7EDD62EEF13AC-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2009-05-27  6:39                     ` Jean Delvare
       [not found]                       ` <20090527083957.20641ebc-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Jean Delvare @ 2009-05-27  6:39 UTC (permalink / raw)
  To: Wang, Wen W; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

Hi Wen,

On Wed, 27 May 2009 10:06:33 +0800, Wang, Wen W wrote:
> Can you please help provide the status of the I2C controller driver submission? I'm trying to understand the gap and be willing to fix it to get it accepted.

There is no specific problem other than the fact that I have no time to
look at your code at the moment. I have a lot of work and many
important things happening in my private life, and spare time doesn't
grow on trees. I've added the review to my to-do list but it's a long
list and new items are added faster than old items are removed these
days :( Maybe someone else on the linux-i2c list can review your code?

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown   platform
       [not found]                       ` <20090527083957.20641ebc-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2009-06-09  8:45                         ` Jean Delvare
       [not found]                           ` <20090609104555.6d81c106-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Jean Delvare @ 2009-06-09  8:45 UTC (permalink / raw)
  To: Wang, Wen W; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

Hi Wen,

On Wed, 27 May 2009 08:39:57 +0200, Jean Delvare wrote:
> On Wed, 27 May 2009 10:06:33 +0800, Wang, Wen W wrote:
> > Can you please help provide the status of the I2C controller driver submission? I'm trying to understand the gap and be willing to fix it to get it accepted.
> 
> There is no specific problem other than the fact that I have no time to
> look at your code at the moment. I have a lot of work and many
> important things happening in my private life, and spare time doesn't
> grow on trees. I've added the review to my to-do list but it's a long
> list and new items are added faster than old items are removed these
> days :( Maybe someone else on the linux-i2c list can review your code?

FYI, I have started reviewing your driver. Unfortunately my mainboard
caught fire on last Friday, interrupting my effort. I had to spend
quite some time fixing my system and reinstalling everything, which
delayed everything else. I'll go on with the review of your driver in
the next few days once the more urgent tasks which have stacked up are
done.

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]                           ` <20090609104555.6d81c106-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2009-06-09  9:00                             ` Wen Wang
       [not found]                               ` <20090609090049.GB28640-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Wen Wang @ 2009-06-09  9:00 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

Hi Jean,

On Tue, Jun 09, 2009 at 04:45:55PM +0800, Jean Delvare wrote:
> Hi Wen,
> 
> On Wed, 27 May 2009 08:39:57 +0200, Jean Delvare wrote:
> > On Wed, 27 May 2009 10:06:33 +0800, Wang, Wen W wrote:
> > > Can you please help provide the status of the I2C controller driver submission? I'm trying to understand the gap and be willing to fix it to get it accepted.
> > 
> > There is no specific problem other than the fact that I have no time to
> > look at your code at the moment. I have a lot of work and many
> > important things happening in my private life, and spare time doesn't
> > grow on trees. I've added the review to my to-do list but it's a long
> > list and new items are added faster than old items are removed these
> > days :( Maybe someone else on the linux-i2c list can review your code?
> 
> FYI, I have started reviewing your driver. Unfortunately my mainboard
> caught fire on last Friday, interrupting my effort. I had to spend
> quite some time fixing my system and reinstalling everything, which
> delayed everything else. I'll go on with the review of your driver in
> the next few days once the more urgent tasks which have stacked up are
> done.

This is terrible :( Do you need me to resent the patch to you?

And thank you for let me know the status, please be my guest if you need any of
my help.

Thanks
Wen 
> -- 
> Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]                               ` <20090609090049.GB28640-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
@ 2009-06-09  9:28                                 ` Jean Delvare
  0 siblings, 0 replies; 26+ messages in thread
From: Jean Delvare @ 2009-06-09  9:28 UTC (permalink / raw)
  To: Wen Wang; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA

On Tue, 9 Jun 2009 17:00:49 +0800, Wen Wang wrote:
> On Tue, Jun 09, 2009 at 04:45:55PM +0800, Jean Delvare wrote:
> > FYI, I have started reviewing your driver. Unfortunately my mainboard
> > caught fire on last Friday, interrupting my effort. I had to spend
> > quite some time fixing my system and reinstalling everything, which
> > delayed everything else. I'll go on with the review of your driver in
> > the next few days once the more urgent tasks which have stacked up are
> > done.
> 
> This is terrible :( Do you need me to resent the patch to you?

No, it's OK. Thankfully I didn't lose any data in the hardware crash,
the hard disk drive survived. "Only" the mainboard and the CPU died. I
have to run on old, slow hardware now :(

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]               ` <0A882F4D99BBF6449D58E61AAFD7EDD628768177-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2009-06-15 11:50                 ` Jean Delvare
       [not found]                   ` <20090615135058.1bf40a75-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Jean Delvare @ 2009-06-15 11:50 UTC (permalink / raw)
  To: Wang, Wen W; +Cc: Linux I2C

Hi Wen,

Sorry for the late reply. Here comes a full review of your driver.

On Thu, 14 May 2009 15:39:03 +0800, Wang, Wen W wrote:
> From f5ace22d5aec5e62b6110e3a61f03ca04eaffafb Mon Sep 17 00:00:00 2001
> From: Wen Wang <wen.w.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> Date: Thu, 14 May 2009 14:56:44 +0800
> Subject: [PATCH] Patch for Moorestown I2C controller driver
>  Signed-off-by: Wen Wang <wen.w.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> 
> ---
>  drivers/i2c/busses/Kconfig          |   10 +
>  drivers/i2c/busses/Makefile         |    1 +
>  drivers/i2c/busses/i2c-moorestown.c |  778 +++++++++++++++++++++++++++++++++++
>  drivers/i2c/busses/i2c-moorestown.h |  259 ++++++++++++
>  4 files changed, 1048 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/i2c/busses/i2c-moorestown.c
>  create mode 100755 drivers/i2c/busses/i2c-moorestown.h
> 

Your code uses spaces for indentation while the Linux kernel code
_must_ use tabs. Please fix. Please also check your code with
scripts/checkpatch.pl --file, this will help you fix most coding-style
issues.

> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index a48c8ae..cf84038 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -738,4 +738,14 @@ config SCx200_ACB
>           This support is also available as a module.  If so, the module
>           will be called scx200_acb.
> 
> +config I2C_MOORESTOWN

Insert this entry in alphabetical order please.

> +       tristate "Intel Moorestown I2C Controller"
> +       depends on PCI && GPIOLIB
> +       default y
> +       help
> +         If you say yes to this option, support will be included for the Intel
> +         Moorestown chipset I2C controller.
> +         This driver can also be built as a module.  If so, the module
> +         will be called i2c-moorestown.
> +
>  endmenu
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 776acb6..9d5f89c 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -69,6 +69,7 @@ obj-$(CONFIG_I2C_SIBYTE)      += i2c-sibyte.o
>  obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
>  obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
>  obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
> +obj-$(CONFIG_I2C_MOORESTOWN)   += i2c-moorestown.o

Alphabetical order here too, please.

> 
>  ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
>  EXTRA_CFLAGS += -DDEBUG
> diff --git a/drivers/i2c/busses/i2c-moorestown.c b/drivers/i2c/busses/i2c-moorestown.c
> new file mode 100644
> index 0000000..ab8a619
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-moorestown.c
> @@ -0,0 +1,778 @@
> +/*
> + * Support for Moorestown I2C controller
> + *
> + * Copyright (c) 2009 Intel Corporation.
> + * Copyright (c) 2009 Synopsys. Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License, version
> + * 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT ANY
> + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
> + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
> + * details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc., 51
> + * Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>

Included by <linux/module.h> so you don't need to specify it.

> +#include <linux/version.h>

Drivers should no longer include <linux/version.h>.

> +#include <linux/kernel.h>
> +#include <linux/err.h>
> +#include <linux/slab.h>
> +#include <linux/stat.h>
> +#include <linux/types.h>

Included by <linux/kernel.h> so you don't need to specify it.

> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +#include <linux/gpio.h>
> +#include <linux/io.h>
> +
> +#include "i2c-moorestown.h"
> +
> +#define MAX_T_POLL_COUNT       10000   /* FIXME */
> +#define DEF_BAR                0
> +#define VERSION                "Version 0.5"
> +
> +#define mrst_i2c_read(reg)             __raw_readl(reg)
> +#define mrst_i2c_write(reg, val)       __raw_writel((val), (reg))

Why macros rather than inline functions? With inline functions you
would have type checking at build time... you could also pass the i2c
controller itself as the first parameter, for slightly shorter calls.

> +
> +static int speed_mode = STANDARD;
> +module_param(speed_mode, int, S_IRUGO);

This parameter lacks a description (use MODULE_PARM_DESC). I also find
it odd that you expose internals to user-space that way. Wouldn't it be
cleaner to take a bus speed in kHz from user-space, and convert it to
a delay inside the driver?

> +
> +/**
> + * mrst_i2c_disable - Disable I2C controller
> + * @adap: struct pointer to i2c_adapter
> + *
> + * Return Value:
> + * 0           success
> + * -EBUSY      if device is busy
> + * -ETIMEOUT   if i2c cannot be disabled within the given time

This function actually never returns -ETIMEOUT (which additionally
doesn't exist - it's ETIMEDOUT.)

> + *
> + * I2C bus state should be checked prior to disabling the hardware. If bus is
> + * not in idle state, an errno is returned. Write "0" to IC_ENABLE to disable
> + * I2C controller.
> + */
> +static int mrst_i2c_disable(struct i2c_adapter *adap)
> +{
> +       struct mrst_i2c_private *i2c =
> +           (struct mrst_i2c_private *)i2c_get_adapdata(adap);

Cast isn't needed, as i2c_get_adapdata() returns a void *. There are
other instances of this throughout the driver code, please fix them all.

> +       int count = 0;
> +
> +       /* Check if device is busy */
> +       dev_dbg(&adap->dev, "mrst i2c disable\n");
> +       while (mrst_i2c_read(i2c->base + IC_STATUS) & 0x1) {
> +               dev_dbg(&adap->dev, "i2c is busy, count is %d\n", count);
> +               if (count++ > MAX_T_POLL_COUNT)
> +                       return -EBUSY;
> +       }

This is a tight loop, with a count-based exit condition. This means
you'll keep the CPU and I/O bus busy for a period of time and you can
hardly say how much this will last. This is no good. Please use a
time-based exit condition. And I suggest you sleep between retries.

> +
> +       /* Set IC_ENABLE to 0 */
> +       mrst_i2c_write(i2c->base + IC_ENABLE, 0);
> +
> +       /* Disable all interupts */
> +       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
> +
> +       /* Clear all interrupts */
> +       mrst_i2c_read(i2c->base + IC_CLR_INTR);
> +
> +       return 0;
> +}
> +
> +/**
> + * mrst_i2c_hwinit - Initiate the I2C hardware registers. This function will
> + * be called in mrst_i2c_probe() before device registration.
> + * @dev: pci device struct pointer
> + *
> + * Return Values:
> + * 0           success
> + * -EBUSY      i2c cannot be disabled
> + * -ETIMEDOUT  i2c cannot be disabled
> + * -EFAULT     If APB data width is not 32-bit wide
> + *
> + * I2C should be disabled prior to other register operation. If failed, an
> + * errno is returned. Mask and Clear all interrpts, this should be done at
> + * first.  Set common registers which will not be modified during normal
> + * transfers, including: controll register, FIFO threshold and clock freq.
> + * Check APB data width at last.
> + */
> +static int  __devinit mrst_i2c_hwinit(struct pci_dev *dev)

Coding style: doubled space.

> +{
> +       struct mrst_i2c_private *i2c =
> +           (struct mrst_i2c_private *)pci_get_drvdata(dev);
> +       int err = 0;

Useless initialization.

> +
> +       /* Disable i2c first */
> +       err = mrst_i2c_disable(i2c->adap);
> +       if (err)
> +               return err;
> +
> +       /* Disable all interupts */
> +       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
> +
> +       /* Clear all interrupts */
> +       mrst_i2c_read(i2c->base + IC_CLR_INTR);

mrst_i2c_disable() already did just that, why do it again?

> +
> +       /*
> +        * Setup clock frequency and speed mode
> +        * Enable restart condition,
> +        * enable master FSM, disable slave FSM,
> +        * use target address when initiating transfer
> +        */
> +       switch (speed_mode) {
> +       case STANDARD:
> +               mrst_i2c_write(i2c->base + IC_CON,
> +                              SLV_DIS | RESTART | STANDARD_MODE | MASTER_EN);
> +               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x75);
> +               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x7c);
> +               break;
> +       case FAST:
> +               mrst_i2c_write(i2c->base + IC_CON,
> +                              SLV_DIS | RESTART | FAST_MODE | MASTER_EN);
> +               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x15);
> +               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x21);
> +               break;
> +       case HIGH:
> +               mrst_i2c_write(i2c->base + IC_CON,
> +                              SLV_DIS | RESTART | HIGH_MODE | MASTER_EN);
> +               mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x7);
> +               mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0xE);
> +               break;
> +       default:
> +               ;

You should probably do something here (return an error, or default
to STANDARD), as speed_mode may be user-provided so it could have an
unexpected value.

> +       }
> +
> +       /* Set tranmit & receive FIFO threshold to zero */
> +       mrst_i2c_write(i2c->base + IC_RX_TL, 0x3);
> +       mrst_i2c_write(i2c->base + IC_TX_TL, 0x3);
> +
> +       mrst_i2c_write(i2c->base + IC_ENABLE, 1);
> +
> +       return err;
> +}
> +
> +/**
> + * mrst_i2c_func - Return the supported three I2C operations.
> + * @adapter: i2c_adapter struct pointer
> + */
> +static u32 mrst_i2c_func(struct i2c_adapter *adapter)
> +{
> +       return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
> +}

FWIW, 10-bit addressing support is incomplete in i2c-core, so even if
your bus driver implements it, you won't be able to use it right away.

> +
> +/**
> + * mrst_i2c_invalid_address - To check if the address in i2c message is
> + * correct.
> + * @p: i2c_msg struct pointer
> + *
> + * Return Values:
> + * 0   if the address is valid
> + * 1   if the address is invalid
> + */
> +static inline int mrst_i2c_invalid_address(const struct i2c_msg *p)
> +{
> +       int ret = ((p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN)
> +                                        && (p->addr > 0x7f)));
> +       return ret;
> +}

I don't think your driver should check this. If this check needs to be
done, that should be done in i2c-core instead of individual drivers.
But my opinion is that this check is unneeded and only slows down the
driver for no benefit, as in most cases the address value comes from
struct i2c_client, and it _is_ already checked when the client is
registered.

> +
> +/**
> + * mrst_i2c_address_neq - To check if the addresses for different i2c messages
> + * are equal.
> + * @p1: first i2c_msg
> + * @p2: second i2c_msg
> + *
> + * Return Values:
> + * 0    if addresse are equal

Typo: addresses.

> + * 1    if not equal
> + *
> + * Within a single transfer, I2C client may need to send its address more
> + * than one time. So a check for the address equation is needed.

one time -> once. And I think you mean equality, not equation.

> + */
> +static inline int mrst_i2c_address_neq(const struct i2c_msg *p1,
> +                                      const struct i2c_msg *p2)
> +{
> +       int ret = ((p1->addr != p2->addr) || ((p1->flags & (I2C_M_TEN))
> +                                             != ((p2->flags) & (I2C_M_TEN))));
> +       return ret;
> +}
> +
> +/**
> + * mrst_i2c_abort - To handle transfer abortions and print error messages.
> + * @adap: i2c_adapter struct pointer
> + *
> + * By reading register IC_TX_ABRT_SOURCE, various transfer errors can be
> + * distingushed. At present, no circumstances have been found out that
> + * multiple errors would be occured simutaneously, so we simply use the
> + * register value directly.

This doesn't make sense. This register is a bitfield, you have to
handle it that way no matter what. With your current code, if two
errors occur simultaneously, you don't display _any_ error message,
which is very bad practice. Handling this properly should hardly be
more code, so please do it.

> + *
> + * At last the error bits are cleared. (Note clear ABRT_SBYTE_NORSTRT bit need
> + * a few extra steps)
> + */
> +static void mrst_i2c_abort(struct i2c_adapter *adap)
> +{
> +       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
> +           i2c_get_adapdata(adap);
> +
> +       /* Read about source register */
> +       int abort = mrst_i2c_read(i2c->base + IC_TX_ABRT_SOURCE);
> +
> +       dev_dbg(&adap->dev, "Abort: ");

No message fragments, please, each message must end with a newline.

> +
> +       /* Single transfer error check:
> +        * According to databook, TX/RX FIFOs would be flushed when
> +        * the abort interrupt occured.
> +        */
> +       switch (abort) {
> +       case (ABRT_MASTER_DIS):

No parentheses around constants, please.

> +               dev_err(&adap->dev,
> +                       "initiate Master operation with Master mode"
> +                       "disabled.\n");

Missing space in the middle of message.

> +

Coding style: extra blank line.

> +               break;
> +       case (ABRT_10B_RD_NORSTRT):
> +               dev_err(&adap->dev,
> +                       "RESTART disabled and master sends READ cmd in 10-BIT"
> +                       "addressing.\n");

Missing space in the middle of message.

> +               break;
> +       case (ABRT_SBYTE_NORSTRT):
> +               dev_err(&adap->dev,
> +                       "RESTART disabled and user is trying to send START"
> +                       "byte.\n");

Same here.

> +               /* Page 141 data book */
> +               mrst_i2c_write(i2c->base + IC_TX_ABRT_SOURCE,
> +                              !(ABRT_SBYTE_NORSTRT));

Binary-not (!) makes no sense for a constant. Maybe you mean
bitwise-not (~) instead? And again parentheses aren't needed.

> +               mrst_i2c_write(i2c->base + IC_CON, RESTART);
> +               mrst_i2c_write(i2c->base + IC_TAR, !(IC_TAR_SPECIAL));

Same here.

> +               break;
> +       case (ABRT_SBYTE_ACKDET):
> +               dev_err(&adap->dev,
> +                       "START byte was acknowledged.\n");
> +               break;
> +       case (ABRT_TXDATA_NOACK):
> +               dev_err(&adap->dev,
> +                       "No acknowledge received from slave.\n");
> +               break;
> +       case (ABRT_10ADDR2_NOACK):
> +               dev_err(&adap->dev,
> +                       "The 2nd address byte of 10-bit address not"
> +                       "acknowledged.\n");

This should be a debug message, not error. Missing space in the middle
of message.

> +               break;
> +       case (ABRT_10ADDR1_NOACK):
> +               dev_dbg(&adap->dev,
> +                       "The 1st address byte of 10-bit address not"
> +                       "acknowledged.\n");

Missing space in the middle of message.

> +               break;
> +       case (ABRT_7B_ADDR_NOACK):
> +               dev_err(&adap->dev,
> +                       "7-bit address not acknowledged.\n");

This should be a debug message, not error.

> +               break;
> +       default:
> +               ;;

Useless statement.

> +       }
> +
> +       /* Clear TX_ABRT bit */
> +       mrst_i2c_read(i2c->base + IC_CLR_TX_ABRT);

Is it really sufficient to _read_ from this register? If so, why is
CLR_TX_ABRT defined?

> +}
> +
> +/**
> + * xfer_read - Internal function to implement master read transfer.
> + * @adap: i2c_adapter struct pointer
> + * @buf: buffer in i2c_msg
> + * @length: number of bytes to be read
> + *
> + * Return Values:
> + * 0           if the read transfer succeeds
> + * -ETIMEDOUT  if cannot read the "raw" interrupt register
> + * -EINVAL     if transfer abort occured

Spelling: occurred. Shouldn't you return -EIO instead of -EINVAL in
case of errors?

> + *
> + * For every byte, a "READ" command will be loaded into IC_DATA_CMD prior to
> + * data transfer. The actual "read" operation will be performed if the RX_FULL
> + * interrupt is occured.

"Is occurred" sounds incorrect, I think "occurs" would be better. And
"when" rather than "if".

> + *
> + * Note there may be two interrupt signals captured, one should read
> + * IC_RAW_INTR_STAT to seperate between errors and actual data.

Spelling: separate.

> + */
> +static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
> +{
> +       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
> +           i2c_get_adapdata(adap);
> +       uint32_t reg_val;

reg_val is a poor variable name.

> +       int i = length;
> +       unsigned count = 0;
> +       uint32_t bit_get = 1 << 3; /* receive fifo not empty */

Isn't this STAT_RFNE? And why define a local variable for it?

> +
> +       while (i--)
> +               mrst_i2c_write(i2c->base + IC_DATA_CMD, (uint16_t)0x100);

Why the cast? And why do you hardcode 0x100 instead of using IC_RD?

> +
> +       i = length;
> +       while (i--) {
> +               count = 0;
> +               reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
> +               while ((reg_val & bit_get) == 0) {
> +                       reg_val = mrst_i2c_read(i2c->base + IC_RAW_INTR_STAT);
> +                       if ((reg_val & 0x40) == 0x40)
> +                               goto read_abrt;
> +                       reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
> +                       if (count++ > MAX_T_POLL_COUNT)
> +                               goto read_loop;

Again, timeout should be time-based, not count-based.

> +               }
> +
> +               reg_val = mrst_i2c_read(i2c->base + IC_DATA_CMD);
> +               *buf++ = reg_val;
> +       }
> +
> +       return 0;
> +
> +read_loop:
> +       dev_err(&adap->dev, "Time out in read\n");
> +       return -ETIMEDOUT;
> +read_abrt:
> +       dev_err(&adap->dev, "Abort from read\n");
> +       mrst_i2c_abort(adap);
> +       return -EINVAL;

Not sure why you use gotos when you could handle the errors directly in
the loop.

> +}
> +
> +/**
> + * xfer_write - Internal function to implement master write transfer.
> + * @adap: i2c_adapter struct pointer
> + * @buf: buffer in i2c_msg
> + * @length: number of bytes to be read

Copy-and-paste error: to be written, not to be read.

> + *
> + * Return Values:
> + * 0   if the read transfer succeeds
> + * -ETIMEDOUT  if cannot read the "raw" interrupt register
> + * -EINVAL     if transfer abort occured

Spelling: occurred. Shouldn't you return -EIO instead of -EINVAL in
case of errors?

> + *
> + * For every byte, a "WRITE" command will be loaded into IC_DATA_CMD prior to
> + * data transfer. The actual "write" operation will be performed if the
> + * RX_FULL interrupt siganal is occured.

Same as above: "occurs" would sound better than "is occurred". Also
"when" instead of "if", and a typo: "signal".

> + *
> + * Note there may be two interrupt signals captured, one should read
> + * IC_RAW_INTR_STAT to seperate between errors and actual data.

Spelling: separate.

> + */
> +static int xfer_write(struct i2c_adapter *adap,
> +                     unsigned char *buf, int length)
> +{
> +       struct mrst_i2c_private *i2c = (struct mrst_i2c_private *)
> +           i2c_get_adapdata(adap);
> +
> +       int i;
> +       uint32_t reg_val;

reg_val is a poor variable name.

> +       unsigned count = 0;
> +       uint32_t bit_get = 1 << 2; /* transmit fifo completely empty */

Isn't this STAT_TFE? And why define a local variable for it?

> +
> +       for (i = 0; i < length; i++)
> +               mrst_i2c_write(i2c->base + IC_DATA_CMD,
> +                              (uint16_t)(*(buf + i)));
> +
> +       reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
> +       while ((reg_val & bit_get) == 0) {
> +               if (count++ > MAX_T_POLL_COUNT)
> +                       goto write_loop;

Again, timeout should be time-based, not count-based.

> +               reg_val = mrst_i2c_read(i2c->base + IC_STATUS);
> +       }
> +
> +       udelay(speed_mode);
> +       reg_val = mrst_i2c_read(i2c->base + IC_RAW_INTR_STAT);
> +       if ((reg_val & 0x40) == 0x40)
> +               goto write_abrt;
> +
> +       return 0;
> +
> +write_loop:
> +       dev_err(&adap->dev, "Time out in write\n");
> +       return -ETIMEDOUT;
> +write_abrt:
> +       dev_err(&adap->dev, "Abort from write\n");
> +       mrst_i2c_abort(adap);
> +       return -EINVAL;

Again, not sure why you use gotos when you could handle the errors
directly in the loop.

> +}
> +
> +static int mrst_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
> +{
> +       struct mrst_i2c_private *i2c =
> +           (struct mrst_i2c_private *)i2c_get_adapdata(adap);
> +       int err;
> +       uint32_t reg_val;

reg_val is a poor variable name.

> +
> +       /* Disable device first */
> +       err = mrst_i2c_disable(adap);
> +       if (err) {
> +               dev_err(&adap->dev,
> +                       "Cannot disable i2c controller, timeout!\n");
> +               return -ETIMEDOUT;

You should return err instead of hard-coding a value.

> +       }
> +
> +       reg_val = mrst_i2c_read(i2c->base + IC_ENABLE);
> +       if (reg_val & 0x1) {
> +               dev_dbg(&adap->dev, "i2c busy, can't setup\n");
> +               return -EINVAL;
> +       }

I don't understand why you check this again, given that
mrst_i2c_disable() just did it already. If I2C is busy, it will
have returned -EBUSY and you never reach this part of the code.

> +
> +       /* Note here we have a change */

This comment is quite mysterious.

> +       switch (speed_mode) {
> +       case STANDARD:
> +               reg_val = SLV_DIS | RESTART | STANDARD_MODE | MASTER_EN;
> +               break;
> +       case FAST:
> +               reg_val = SLV_DIS | RESTART | FAST_MODE | MASTER_EN;
> +               break;
> +       case HIGH:
> +               reg_val = SLV_DIS | RESTART | HIGH_MODE | MASTER_EN;
> +               break;
> +       default:
> +               ;

Same comment as for mrst_i2c_hwinit(): the default case is
insufficient as you have no guarantee the value of speed_mode
is one of the 3 supported ones. The best would probably be to
check the value at driver initialization time and either fail
on unsupported values, or default to STANDARD, at your option.

> +       }
> +
> +       reg_val = reg_val | (pmsg->flags & I2C_M_TEN ? 1 : 0) << 4;

You could use |=. And you should use ADDR_10BIT instead of
hard-coding the value - otherwise it was really not worth defining
all these constants in a header file.

> +       mrst_i2c_write(i2c->base + IC_CON, reg_val);
> +
> +       /* set target address to the I2C slave address */
> +       dev_dbg(&adap->dev, "set target address to the I2C slave address,"
> +               "addr is %x\n", pmsg->addr);
> +       reg_val = ((pmsg->addr & 0x3ff) |
> +                  (pmsg->flags & I2C_M_TEN ? IC_TAR_10BIT_ADDR : 0));
> +       mrst_i2c_write(i2c->base + IC_TAR, reg_val);
> +
> +       /* Enable I2C controller */
> +       mrst_i2c_write(i2c->base + IC_ENABLE, ENABLE);
> +
> +       return 0;
> +}
> +
> +/**
> + * mrst_i2c_xfer - Main master transfer routine.
> + * @adap: i2c_adapter struct pointer
> + * @pmsg: i2c_msg struct pointer
> + * @num: number of i2c_msg
> + *
> + * Return Values:
> + * +           number of messages transfered
> + * -ETIMEDOUT  If cannot disable I2C controller or read IC_STATUS
> + * -EINVAL     If the address in i2c_msg is invalid
> + *
> + * This function will be registered in i2c-core and exposed to external
> + * I2C clients.
> + * 1. Disable I2C controller
> + * 2. Unmask three interrupts: RX_FULL, TX_EMPTY, TX_ABRT
> + * 3. Check if address in i2c_msg is valid
> + * 4. Enable I2C controller
> + * 5. Perform real transfer (call xfer_read or xfer_write)
> + * 6. Wait until the current transfer is finished(check bus state)

Missing space before opening parenthesis.

> + * 7. Mask and clear all interrupts
> + */
> +static int mrst_i2c_xfer(struct i2c_adapter *adap,
> +                        struct i2c_msg *pmsg,
> +                        int num)
> +{
> +       struct mrst_i2c_private *i2c =
> +           (struct mrst_i2c_private *)i2c_get_adapdata(adap);
> +       int i, err;
> +
> +       dev_dbg(&adap->dev, "mrst_i2c_xfer, process %d msg(s)\n", num);
> +       dev_dbg(&adap->dev, KERN_INFO "slave address is %x\n", pmsg->addr);

KERN_INFO definitely shouldn't be there, dev_dbg() already inserts
a log level code for you.

> +
> +       /* if number of messages equal 0*/
> +       if (num == 0)
> +               return 0;
> +
> +       /* Checked the sanity of passed messages. */
> +       if (unlikely(mrst_i2c_invalid_address(&pmsg[0]))) {
> +               dev_err(&adap->dev, "Invalid address 0x%03x (%d-bit)\n",
> +                       pmsg[0].addr, pmsg[0].flags & I2C_M_TEN ? 10 : 7);
> +               return -EINVAL;
> +       }
> +       for (i = 0; i < num; i++) {
> +               /* Message address equal? */
> +               if (unlikely(mrst_i2c_address_neq(&pmsg[0], &pmsg[i]))) {

This check can't fail for i = 0, obviously, so you should start the
loop at i = 1.

> +                       dev_err(&adap->dev, "Invalid address in msg[%d]\n", i);
> +                       return -EINVAL;
> +               }
> +       }
> +
> +       if (mrst_i2c_setup(adap, pmsg))
> +               return -EINVAL;
> +
> +       for (i = 0; i < num; i++) {
> +               dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
> +                       pmsg->flags & I2C_M_RD ? "read" : "writ",
> +                       pmsg->len, pmsg->len > 1 ? "s" : "",
> +                       pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr);

i2c-core already provides this type of debugging messages, so
this is redundant.

> +
> +

Coding style: doubled blank line.

> +               /* Read or Write */
> +               if (pmsg->len && pmsg->buf) {
> +                       if (pmsg->flags & I2C_M_RD) {
> +                               dev_dbg(&adap->dev, "I2C_M_RD\n");
> +                               err = xfer_read(adap, pmsg->buf, pmsg->len);
> +                       } else {
> +                               dev_dbg(&adap->dev, "I2C_M_WR\n");
> +                               err = xfer_write(adap, pmsg->buf, pmsg->len);
> +                       }
> +                       if (err < 0)
> +                               goto err_1;
> +               }

What if pmsg->len = 0? You skip the message entirely, which
is not correct.

> +               dev_dbg(&adap->dev, "msg[%d] transfer complete\n", i);
> +               pmsg++;         /* next message */
> +       }
> +       goto exit;
> +
> +err_1:
> +       i = err;
> +exit:
> +       /* Mask interrupts */
> +       mrst_i2c_write(i2c->base + IC_INTR_MASK, 0x0000);
> +       /* Clear all interrupts */
> +       mrst_i2c_read(i2c->base + IC_CLR_INTR);
> +
> +       return i;
> +}
> +
> +static int mrst_gpio_init(int sda, int scl)
> +{
> +       if (gpio_request(sda, "I2C_SDA"))
> +               goto err_sda;
> +
> +       if (gpio_request(scl, "I2C_SCL"))
> +               goto err_scl;
> +
> +       /* TODO: Wait for Moorestown GPIO driver into upstream to uncomment */
> +       /*gpio_alt_func(sda, 1);*/
> +       /*gpio_alt_func(scl, 1);*/

Is the driver upstream by now? If not then there's little point
in merging this i2c controller driver.

> +
> +       return 0;
> +err_scl:
> +       gpio_free(sda);
> +err_sda:
> +       return -1;

You should rather return the error code from gpio_request().

> +}
> +
> +static struct pci_device_id mrst_i2c_ids[] = {
> +       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0802)},
> +       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0803)},
> +       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0804)},
> +       {0,}
> +};
> +MODULE_DEVICE_TABLE(pci, mrst_i2c_ids);
> +
> +static struct i2c_algorithm mrst_i2c_algorithm = {
> +       .master_xfer    = mrst_i2c_xfer,
> +       .functionality  = mrst_i2c_func,
> +};
> +
> +static struct pci_driver mrst_i2c_driver = {
> +       .name           = "mrst_i2c",
> +       .id_table       = mrst_i2c_ids,
> +       .probe          = mrst_i2c_probe,
> +       .remove         = __devexit_p(mrst_i2c_remove),
> +       .suspend        = NULL,
> +       .resume         = NULL,

You don't need to define callbacks if you set them to NULL, just
omit them.

> +};
> +
> +/**
> + * mrst_i2c_probe - I2C controller initialization routine
> + * @dev: pci device
> + * @id: device id
> + *
> + * Return Values:
> + * 0           success
> + * -ENODEV     If cannot allocate pci resource
> + * -ENOMEM     If the register base remapping failed, or
> + *             if kzalloc failed
> + *
> + * Initialization steps:
> + * 1. Request for PCI resource
> + * 2. Remap the start address of PCI resource to register base
> + * 3. Request for device memory region
> + * 4. Fill in the struct members of mrst_i2c_private
> + * 5. Call mrst_i2c_hwinit() for hardware initialization
> + * 6. Register I2C adapter in i2c-core
> + */
> +static int __devinit mrst_i2c_probe(struct pci_dev *dev,
> +                                   const struct pci_device_id *id)
> +{
> +       struct mrst_i2c_private *mrst;
> +       struct i2c_adapter *adap;
> +       unsigned int start, len;
> +       int err, busnum = 0;
> +       void __iomem *base = NULL;
> +       int gpio_sda = 0, gpio_scl = 0;
> +
> +       err = pci_enable_device(dev);
> +       if (err) {
> +               dev_err(&dev->dev, "Failed to enable I2C PCI device (%d)\n",
> +                       err);
> +               goto exit;
> +       }
> +
> +       /* Determine the address of the I2C area */
> +       start = pci_resource_start(dev, DEF_BAR);
> +       len = pci_resource_len(dev, DEF_BAR);
> +       if (!start || len <= 0) {
> +               dev_err(&dev->dev, "Base address initialization failed\n");
> +               err = -ENODEV;
> +               goto exit;
> +       }
> +       dev_dbg(&dev->dev, "mrst i2c resource start %x, len=%d\n",
> +               start, len);

Please use 0x%x, to make it clear it is an hexadecimal value.

> +       err = pci_request_region(dev, DEF_BAR, mrst_i2c_driver.name);
> +       if (err) {
> +               dev_err(&dev->dev, "Failed to request I2C region "
> +                       "0x%1x-0x%Lx\n", start,
> +                       (unsigned long long)pci_resource_end(dev, DEF_BAR));
> +               goto exit;
> +       }
> +
> +       base = ioremap_nocache(start, len);
> +       if (!base) {
> +               dev_err(&dev->dev, "I/O memory remapping failed\n");
> +               err = -ENOMEM;
> +               goto fail0;
> +       }
> +
> +       /* Allocate the per-device data structure, mrst_i2c_private */
> +       mrst = kzalloc(sizeof(struct mrst_i2c_private), GFP_KERNEL);
> +       if (mrst == NULL) {
> +               dev_err(&dev->dev, "Can't allocate interface!\n");
> +               err = -ENOMEM;
> +               goto fail1;
> +       }
> +
> +       adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);

Why don't you include this structure in struct mrst_i2c_private?
This would avoid memory fragmentation.

> +       if (adap == NULL) {
> +               dev_err(&dev->dev, "Can't allocate interface!\n");
> +               err = -ENOMEM;
> +               goto fail2;
> +       }
> +
> +       /* Initialize struct members */
> +       snprintf(adap->name, sizeof(adap->name), "mrst_i2c");

Please come up with a nicer and unique name. Usually we include
the base address so that you can differentiate between multiple
buses on the same system. So something like:

snprintf(adap->name, sizeof(adap->name), "Moorestown I2C at %x", start);

> +       adap->owner = THIS_MODULE;
> +       adap->algo = &mrst_i2c_algorithm;
> +       adap->class = I2C_CLASS_HWMON;
> +       adap->dev.parent = &dev->dev;
> +       mrst->adap = adap;
> +       mrst->base = base;
> +       mrst->speed = speed_mode;

You store this value but then never use it.

> +
> +       pci_set_drvdata(dev, mrst);
> +       i2c_set_adapdata(adap, mrst);
> +
> +       /* Initialize i2c controller */
> +       err = mrst_i2c_hwinit(dev);
> +       if (err < 0) {
> +               dev_err(&dev->dev, "I2C interface initialization failed\n");
> +               goto fail3;
> +       }
> +
> +       switch (id->device) {
> +       case 0x0802:
> +               dev_dbg(&adap->dev, KERN_INFO "I2C0\n");
> +               gpio_sda = GPIO_I2C_0_SDA;
> +               gpio_scl = GPIO_I2C_0_SCL;
> +               adap->nr = busnum = 0;

You don't use busnum anywhere, so just drop it.

> +               break;
> +       case 0x0803:
> +               dev_dbg(&adap->dev, KERN_INFO "I2C1\n");
> +               gpio_sda = GPIO_I2C_1_SDA;
> +               gpio_scl = GPIO_I2C_1_SCL;
> +               adap->nr = busnum = 1;
> +               break;
> +       case 0x0804:
> +               dev_dbg(&adap->dev, KERN_INFO "I2C2\n");
> +               gpio_sda = GPIO_I2C_2_SDA;
> +               gpio_scl = GPIO_I2C_2_SCL;
> +               adap->nr = busnum = 2;
> +               break;
> +       default:
> +               ;

Not good. If someone force-binds the driver to another device,
you go on with unconfigured GPIOs. If it doesn't make sense then
you have to return an error here.

> +       }
> +
> +       /* Config GPIO pin for I2C */
> +       err = mrst_gpio_init(gpio_sda, gpio_scl);
> +       if (err) {
> +               dev_err(&dev->dev, "GPIO %s registration failed\n",
> +                       adap->name);
> +               goto fail3;
> +       }
> +
> +       /* Adapter registration */
> +       err = i2c_add_numbered_adapter(adap);
> +       if (err) {
> +               dev_err(&dev->dev, "Adapter %s registration failed\n",
> +                       adap->name);
> +               goto fail3;

If this happens, you return without releasing the GPIOs you
requested. No good.

> +       }
> +
> +       dev_dbg(&dev->dev, "MRST I2C bus %d driver bind success.\n", busnum);
> +       return 0;
> +
> +fail3:
> +       i2c_set_adapdata(adap, NULL);

Not terribly useful, as you're going to free the adapter 2 lines
below.

> +       pci_set_drvdata(dev, NULL);
> +       kfree(adap);
> +fail2:
> +       kfree(mrst);
> +fail1:
> +       iounmap(base);
> +fail0:
> +       pci_release_region(dev, DEF_BAR);
> +exit:
> +       return err;
> +}
> +
> +static void __devexit mrst_i2c_remove(struct pci_dev *dev)
> +{
> +       struct mrst_i2c_private *mrst = (struct mrst_i2c_private *)
> +                                       pci_get_drvdata(dev);

Useless cast.

> +       if (i2c_del_adapter(mrst->adap))
> +               dev_err(&dev->dev, "Failed to delete i2c adapter");
> +
> +       switch (dev->device) {
> +       case 0x0802:
> +               gpio_free(GPIO_I2C_0_SDA);
> +               gpio_free(GPIO_I2C_0_SCL);
> +               break;
> +       case 0x0803:
> +               gpio_free(GPIO_I2C_1_SDA);
> +               gpio_free(GPIO_I2C_1_SCL);
> +               break;
> +       case 0x0804:
> +               gpio_free(GPIO_I2C_2_SDA);
> +               gpio_free(GPIO_I2C_2_SCL);
> +               break;
> +       default:
> +               break;

Useless statement.

> +       }
> +
> +       pci_set_drvdata(dev, NULL);
> +       iounmap(mrst->base);

You have to free mrst->adap too, otherwise you're leaking memory.

> +       kfree(mrst);
> +       pci_release_region(dev, DEF_BAR);
> +}
> +
> +static int __init mrst_i2c_init(void)
> +{
> +       printk(KERN_NOTICE "Moorestown I2C driver %s\n", VERSION);
> +       return pci_register_driver(&mrst_i2c_driver);
> +}
> +
> +static void __exit mrst_i2c_exit(void)
> +{
> +       pci_unregister_driver(&mrst_i2c_driver);
> +}
> +
> +module_init(mrst_i2c_init);
> +module_exit(mrst_i2c_exit);
> +
> +MODULE_AUTHOR("Ba Zheng <zheng.ba-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>");
> +MODULE_DESCRIPTION("I2C driver for Moorestown Platform");
> +MODULE_LICENSE("GPL");
> +MODULE_VERSION(VERSION);
> diff --git a/drivers/i2c/busses/i2c-moorestown.h b/drivers/i2c/busses/i2c-moorestown.h
> new file mode 100755
> index 0000000..e2645c0
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-moorestown.h

What's the point of having a separate file for this? Please move these
definitions into the main driver file directly. And while you're at it,
please fix the horrible indentation of many constants, it's hardly
readable as is.

> @@ -0,0 +1,259 @@
> +#ifndef __I2C_MRST_H
> +#define __I2C_MRST_H
> +
> +#include <linux/i2c.h>
> +
> +struct mrst_i2c_private {
> +       struct i2c_adapter *adap;
> +       /* Register base address */
> +       void __iomem *base;
> +       /* Speed mode */
> +       int speed;
> +};
> +
> +/* Speed mode macros */
> +#define STANDARD       100
> +#define FAST           25
> +#define        HIGH            3
> +
> +/* Control register */
> +#define IC_CON                 0x00
> +#define SLV_DIS                        (1 << 6)        /* Disable slave mode */
> +#define RESTART                        (1 << 5)        /* Send a Restart condition */
> +#define        ADDR_10BIT              (1 << 4)        /* 10-bit addressing */
> +#define        STANDARD_MODE           (1 << 1)        /* standard mode */
> +#define FAST_MODE              (2 << 1)        /* fast mode */
> +#define HIGH_MODE              (3 << 1)        /* high speed mode */
> +#define        MASTER_EN               (1 << 0)        /* Master mode */
> +
> +/* Target address register */
> +#define IC_TAR                 0x04
> +#define IC_TAR_10BIT_ADDR      (1 << 12)       /* 10-bit addressing */
> +#define IC_TAR_SPECIAL         (1 << 11)       /* Perform special I2C cmd */
> +#define IC_TAR_GC_OR_START     (1 << 10)       /* 0: Gerneral Call Address */
> +                                               /* 1: START BYTE */
> +
> +/* Slave Address Register */
> +#define IC_SAR                 0x08            /* Not used in Master mode */
> +
> +/* High Speed Master Mode Code Address Register */
> +#define IC_HS_MADDR            0x0c
> +
> +/* Rx/Tx Data Buffer and Command Register */
> +#define IC_DATA_CMD            0x10
> +#define IC_RD                  (1 << 8)        /* 1: Read 0: Write */
> +
> +/* Standard Speed Clock SCL High Count Register */
> +#define IC_SS_SCL_HCNT         0x14
> +
> +/* Standard Speed Clock SCL Low Count Register */
> +#define IC_SS_SCL_LCNT         0x18
> +
> +/* Fast Speed Clock SCL High Count Register */
> +#define IC_FS_SCL_HCNT         0x1c
> +
> +/* Fast Spedd Clock SCL Low Count Register */
> +#define IC_FS_SCL_LCNT         0x20
> +
> +/* High Speed Clock SCL High Count Register */
> +#define IC_HS_SCL_HCNT         0x24
> +
> +/* High Speed Clock SCL Low Count Register */
> +#define IC_HS_SCL_LCNT         0x28
> +
> +/* Interrupt Status Register */
> +#define IC_INTR_STAT           0x2c            /* Read only */
> +#define R_GEN_CALL             (1 << 11)
> +#define R_START_DET            (1 << 10)
> +#define R_STOP_DET             (1 << 9)
> +#define R_ACTIVITY             (1 << 8)
> +#define R_RX_DONE              (1 << 7)
> +#define        R_TX_ABRT               (1 << 6)
> +#define R_RD_REQ               (1 << 5)
> +#define R_TX_EMPTY             (1 << 4)
> +#define R_TX_OVER              (1 << 3)
> +#define        R_RX_FULL               (1 << 2)
> +#define        R_RX_OVER               (1 << 1)
> +#define R_RX_UNDER             (1 << 0)
> +
> +/* Interrupt Mask Register */
> +#define IC_INTR_MASK           0x30            /* Read and Write */
> +#define M_GEN_CALL             (1 << 11)
> +#define M_START_DET            (1 << 10)
> +#define M_STOP_DET             (1 << 9)
> +#define M_ACTIVITY             (1 << 8)
> +#define M_RX_DONE              (1 << 7)
> +#define        M_TX_ABRT               (1 << 6)
> +#define M_RD_REQ               (1 << 5)
> +#define M_TX_EMPTY             (1 << 4)
> +#define M_TX_OVER              (1 << 3)
> +#define        M_RX_FULL               (1 << 2)
> +#define        M_RX_OVER               (1 << 1)
> +#define M_RX_UNDER             (1 << 0)
> +
> +/* Raw Interrupt Status Register */
> +#define IC_RAW_INTR_STAT       0x34            /* Read Only */
> +#define GEN_CALL               (1 << 11)       /* General call */
> +#define START_DET              (1 << 10)       /* (RE)START occured */
> +#define STOP_DET               (1 << 9)        /* STOP occured */
> +#define ACTIVITY               (1 << 8)        /* Bus busy */
> +#define RX_DONE                        (1 << 7)        /* Not used in Master mode */
> +#define        TX_ABRT                 (1 << 6)        /* Transmit Abort */
> +#define RD_REQ                 (1 << 5)        /* Not used in Master mode */
> +#define TX_EMPTY               (1 << 4)        /* TX FIFO <= threshold */
> +#define TX_OVER                        (1 << 3)        /* TX FIFO overflow */
> +#define        RX_FULL                 (1 << 2)        /* RX FIFO >= threshold */
> +#define        RX_OVER                 (1 << 1)        /* RX FIFO overflow */
> +#define RX_UNDER               (1 << 0)        /* RX FIFO empty */
> +
> +/* Receive FIFO Threshold Register */
> +#define IC_RX_TL               0x38
> +
> +/* Transmit FIFO Treshold Register */
> +#define IC_TX_TL               0x3c
> +
> +/* Clear Combined and Individual Interrupt Register */
> +#define IC_CLR_INTR            0x40
> +#define CLR_INTR               (1 << 0)
> +
> +/* Clear RX_UNDER Interrupt Register */
> +#define IC_CLR_RX_UNDER                0x44
> +#define CLR_RX_UNDER           (1 << 0)
> +
> +/* Clear RX_OVER Interrupt Register */
> +#define IC_CLR_RX_OVER         0x48
> +#define CLR_RX_OVER            (1 << 0)
> +
> +/* Clear TX_OVER Interrupt Register */
> +#define IC_CLR_TX_OVER         0x4c
> +#define CLR_TX_OVER            (1 << 0)
> +
> +#define IC_CLR_RD_REQ          0x50
> +
> +/* Clear TX_ABRT Interrupt Register */
> +#define IC_CLR_TX_ABRT         0x54
> +#define CLR_TX_ABRT            (1 << 0)
> +
> +#define IC_CLR_RX_DONE         0x58
> +
> +
> +/* Clear ACTIVITY Interrupt Register */
> +#define IC_CLR_ACTIVITY                0x5c
> +#define CLR_ACTIVITY           (1 << 0)
> +
> +/* Clear STOP_DET Interrupt Register */
> +#define IC_CLR_STOP_DET                0x60
> +#define CLR_STOP_DET           (1 << 0)
> +
> +/* Clear START_DET Interrupt Register */
> +#define IC_CLR_START_DET       0x64
> +#define CLR_START_DET          (1 << 0)
> +
> +/* Clear GEN_CALL Interrupt Register */
> +#define IC_CLR_GEN_CALL                0x68
> +#define CLR_GEN_CALL           (1 << 0)
> +
> +/* Enable Register */
> +#define IC_ENABLE              0x6c
> +#define ENABLE                 (1 << 0)
> +
> +/* Status Register */
> +#define IC_STATUS              0x70            /* Read Only */
> +#define STAT_SLV_ACTIVITY      (1 << 6)        /* Slave not in idle */
> +#define STAT_MST_ACTIVITY      (1 << 5)        /* Master not in idle */
> +#define STAT_RFF               (1 << 4)        /* RX FIFO Full */
> +#define STAT_RFNE              (1 << 3)        /* RX FIFO Not Empty */
> +#define STAT_TFE               (1 << 2)        /* TX FIFO Empty */
> +#define STAT_TFNF              (1 << 1)        /* TX FIFO Not Full */
> +#define STAT_ACTIVITY          (1 << 0)        /* Activity Status */
> +
> +/* Transmit FIFO Level Register */
> +#define IC_TXFLR               0x74            /* Read Only */
> +#define TXFLR                  (1 << 0)        /* TX FIFO level */
> +
> +/* Receive FIFO Level Register */
> +#define IC_RXFLR               0x78            /* Read Only */
> +#define RXFLR                  (1 << 0)        /* RX FIFO level */
> +
> +/* Transmit Abort Source Register */
> +#define IC_TX_ABRT_SOURCE      0x80
> +#define ABRT_SLVRD_INTX                (1 << 15)
> +#define ABRT_SLV_ARBLOST       (1 << 14)
> +#define ABRT_SLVFLUSH_TXFIFO   (1 << 13)
> +#define        ARB_LOST                (1 << 12)
> +#define ABRT_MASTER_DIS                (1 << 11)
> +#define ABRT_10B_RD_NORSTRT    (1 << 10)
> +#define ABRT_SBYTE_NORSTRT     (1 << 9)
> +#define ABRT_HS_NORSTRT                (1 << 8)
> +#define ABRT_SBYTE_ACKDET      (1 << 7)
> +#define ABRT_HS_ACKDET         (1 << 6)
> +#define ABRT_GCALL_READ                (1 << 5)
> +#define ABRT_GCALL_NOACK       (1 << 4)
> +#define ABRT_TXDATA_NOACK      (1 << 3)
> +#define ABRT_10ADDR2_NOACK     (1 << 2)
> +#define ABRT_10ADDR1_NOACK     (1 << 1)
> +#define ABRT_7B_ADDR_NOACK     (1 << 0)
> +
> +/* Enable Status Register */
> +#define IC_ENABLE_STATUS       0x9c
> +#define IC_EN                  (1 << 0)        /* I2C in an enabled state */
> +
> +/* Component Parameter Register 1*/
> +#define IC_COMP_PARAM_1                0xf4
> +#define APB_DATA_WIDTH         (0x3 << 0)
> +
> +/* GPIO_PINS */
> +#define GPIO_I2C_0_SDA         56
> +#define GPIO_I2C_0_SCL         57
> +
> +#define GPIO_I2C_1_SDA         54
> +#define GPIO_I2C_1_SCL         55
> +
> +#define GPIO_I2C_2_SDA         52
> +#define GPIO_I2C_2_SCL         53
> +
> +/* added by xiaolin --begin */

We really don't care who added this ;)

> +#define SS_MIN_SCL_HIGH         4000
> +#define SS_MIN_SCL_LOW          4700
> +#define FS_MIN_SCL_HIGH         600
> +#define FS_MIN_SCL_LOW          1300
> +#define HS_MIN_SCL_HIGH_100PF   60
> +#define HS_MIN_SCL_LOW_100PF    120
> +
> +enum mrst_i2c_irq {
> +    i2c_irq_none = 0x000,
> +    i2c_irq_rx_under = 0x001,
> +    i2c_irq_rx_over = 0x002,
> +    i2c_irq_rx_full = 0x004,
> +    i2c_irq_tx_over = 0x008,
> +    i2c_irq_tx_empty = 0x010,
> +    i2c_irq_rd_req = 0x020,
> +    i2c_irq_tx_abrt = 0x040,
> +    i2c_irq_rx_done = 0x080,
> +    i2c_irq_activity = 0x100,
> +    i2c_irq_stop_det = 0x200,
> +    i2c_irq_start_det = 0x400,
> +    i2c_irq_gen_call = 0x800,
> +    i2c_irq_all = 0xfff
> +};
> +
> +/* Function declarations */
> +static int mrst_i2c_disable(struct i2c_adapter *);
> +static int __devinit mrst_i2c_hwinit(struct pci_dev *);
> +static u32 mrst_i2c_func(struct i2c_adapter *);
> +static inline int mrst_i2c_invalid_address(const struct i2c_msg *);
> +static inline int mrst_i2c_address_neq(const struct i2c_msg *,
> +                                      const struct i2c_msg *);
> +static int mrst_i2c_xfer(struct i2c_adapter *,
> +                        struct i2c_msg *,
> +                        int);
> +static int __devinit mrst_i2c_probe(struct pci_dev *,
> +                                   const struct pci_device_id *);
> +static void __devexit mrst_i2c_remove(struct pci_dev *);
> +static int __init mrst_i2c_init(void);
> +static void __exit mrst_i2c_exit(void);
> +static int xfer_read(struct i2c_adapter *,
> +                    unsigned char *, int);
> +static int xfer_write(struct i2c_adapter *,
> +                     unsigned char *, int);
> +#endif /* __I2C_MRST_H */
> --
> 1.5.5.1
> 
> 
> >-----Original Message-----
> >From: Wang, Wen W
> >Sent: 2009年5月14日 15:36
> >To: Jean Delvare
> >Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Wang, Wen W
> >Subject: [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform
> >
> >Hi Jean,
> >
> >After a long discussion with other engineers, we finally got parsing I2C device info
> >table code out of the I2C controller driver. Here is a description for the patch:
> >
> >1. Patch for I2C controller driver for Intel low power platform "Moorestown".
> >2. The driver depends on a GPIO driver for Intel Moorestown platform.
> >3. Patch is based on Linux 2.6.30-rc5.
> >4. Patch 1 will:
> >       a. Add "i2c_moorestown.c" and "i2c_moorestown.h" to kernel directory
> >"drivers/i2c/busses"
> >       b. Add items into kernel files "drivers/i2c/busses/Kconfig" and
> >"drivers/i2c/Makefile".
> >
> >Code for parsing I2C device info table and register the table into I2C core are moved
> >into a separate platform driver under arch/ directory per your comments.
> >
> >Thanks
> >Wen

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH 1/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]                   ` <20090615135058.1bf40a75-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2009-06-26  2:41                     ` Wang, Wen W
       [not found]                       ` <0A882F4D99BBF6449D58E61AAFD7EDD62F26B15F-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Wang, Wen W @ 2009-06-26  2:41 UTC (permalink / raw)
  To: Jean Delvare; +Cc: Linux I2C

Hi Jean,

Really appreciate your kindly comments on Moorestown I2C driver! I'm really learning a lot from your comments. :)

Currently I'm working on those comments, but due to other plenty of work, please expect a slow response on that. :(

Another thing needs your help is, can I replace the module_init() function with subsys_initcall() in Moorestown I2C driver? Is it acceptable for I2C subsystem? 
There is a requirement in Moorestown that certain drivers need I2C driver loaded before those drivers. To achieve this, is subsys_initcall() the only way?

Thanks
Wen

>-----Original Message-----
>From: Jean Delvare [mailto:khali@linux-fr.org]
>Sent: 2009年6月15日 19:51
>To: Wang, Wen W
>Cc: Linux I2C
>Subject: Re: [PATCH 1/1] I2C: I2C controller driver for Intel Moorestown platform
>
>Hi Wen,
>
>Sorry for the late reply. Here comes a full review of your driver.
>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]                       ` <0A882F4D99BBF6449D58E61AAFD7EDD62F26B15F-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2009-06-26  7:50                         ` Jean Delvare
       [not found]                           ` <20090626095026.22c5d6c1-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Jean Delvare @ 2009-06-26  7:50 UTC (permalink / raw)
  To: Wang, Wen W; +Cc: Linux I2C

Hi Wen,

On Fri, 26 Jun 2009 10:41:07 +0800, Wang, Wen W wrote:
> Hi Jean,
> 
> Really appreciate your kindly comments on Moorestown I2C driver! I'm really learning a lot from your comments. :)
> 
> Currently I'm working on those comments, but due to other plenty of work, please expect a slow response on that. :(
> 
> Another thing needs your help is, can I replace the module_init() function with subsys_initcall() in Moorestown I2C driver? Is it acceptable for I2C subsystem? 

Yes, using subsys_initcall() is acceptable, a number of i2c bus drivers
for embedded platforms do that already (i2c-pxa and i2c-omap.c for
example.)

> There is a requirement in Moorestown that certain drivers need I2C driver loaded before those drivers. To achieve this, is subsys_initcall() the only way?

I can't say whether this is the only way given than you mentioned no
detail about the requirements, but this is one possible way for sure.

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH 1/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]                           ` <20090626095026.22c5d6c1-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2009-06-26  7:54                             ` Wang, Wen W
       [not found]                               ` <0A882F4D99BBF6449D58E61AAFD7EDD62F26B3F4-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Wang, Wen W @ 2009-06-26  7:54 UTC (permalink / raw)
  To: Jean Delvare; +Cc: Linux I2C

Hi Jean,

Thank you for your confirmation!

Wen

>-----Original Message-----
>From: Jean Delvare [mailto:khali@linux-fr.org]
>Sent: 2009年6月26日 15:50
>To: Wang, Wen W
>Cc: Linux I2C
>Subject: Re: [PATCH 1/1] I2C: I2C controller driver for Intel Moorestown platform
>
>Hi Wen,
>
>On Fri, 26 Jun 2009 10:41:07 +0800, Wang, Wen W wrote:
>> Hi Jean,
>>
>> Really appreciate your kindly comments on Moorestown I2C driver! I'm really
>learning a lot from your comments. :)
>>
>> Currently I'm working on those comments, but due to other plenty of work, please
>expect a slow response on that. :(
>>
>> Another thing needs your help is, can I replace the module_init() function with
>subsys_initcall() in Moorestown I2C driver? Is it acceptable for I2C subsystem?
>
>Yes, using subsys_initcall() is acceptable, a number of i2c bus drivers
>for embedded platforms do that already (i2c-pxa and i2c-omap.c for
>example.)
>
>> There is a requirement in Moorestown that certain drivers need I2C driver loaded
>before those drivers. To achieve this, is subsys_initcall() the only way?
>
>I can't say whether this is the only way given than you mentioned no
>detail about the requirements, but this is one possible way for sure.
>
>--
>Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/1] I2C: I2C controller driver for Intel Moorestown   platform
       [not found]                               ` <0A882F4D99BBF6449D58E61AAFD7EDD62F26B3F4-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2009-12-17 13:28                                 ` Jean Delvare
       [not found]                                   ` <20091217142836.01af265c-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  0 siblings, 1 reply; 26+ messages in thread
From: Jean Delvare @ 2009-12-17 13:28 UTC (permalink / raw)
  To: Wang, Wen W; +Cc: Linux I2C

Hi Wen,

Any news from this I2C controller driver for the Intel Moorestown
platform? I spent quite some time reviewing your code 6 months ago and
am rather sad to see that the code in question did not go anywhere.

Thanks,
-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH 1/1] I2C: I2C controller driver for Intel Moorestown platform
       [not found]                                   ` <20091217142836.01af265c-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2009-12-18  1:37                                     ` Wang, Wen W
  0 siblings, 0 replies; 26+ messages in thread
From: Wang, Wen W @ 2009-12-18  1:37 UTC (permalink / raw)
  To: Jean Delvare; +Cc: Linux I2C

Hi Jean,

Really sorry for this. :(

We are being really busy on some other drivers' development. So very low bandwidth to update the patch though I have addressed part of your comments.

But I will definitely re-submit the driver patch early next year which includes all your comments and another Intel platform compatibility.

Thanks
Wen
>-----Original Message-----
>From: Jean Delvare [mailto:khali@linux-fr.org]
>Sent: 2009年12月17日 21:29
>To: Wang, Wen W
>Cc: Linux I2C
>Subject: Re: [PATCH 1/1] I2C: I2C controller driver for Intel Moorestown platform
>
>Hi Wen,
>
>Any news from this I2C controller driver for the Intel Moorestown
>platform? I spent quite some time reviewing your code 6 months ago and
>am rather sad to see that the code in question did not go anywhere.
>
>Thanks,
>--
>Jean Delvare

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2009-12-18  1:37 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-15 14:23 Questions for submitting driver to I2C subsystem Wang, Wen W
     [not found] ` <0A882F4D99BBF6449D58E61AAFD7EDD610424EB0-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2009-04-16  9:14   ` Jean Delvare
     [not found]     ` <20090416111436.296cdd12-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-04-23  9:00       ` [PATCH 0/1] I2C: I2C controller driver for Intel Moorestown platform Wang, Wen W
     [not found]         ` <0A882F4D99BBF6449D58E61AAFD7EDD6136779F1-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2009-04-23  9:29           ` Jean Delvare
     [not found]             ` <20090423112935.306ba11a-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-04-23  9:55               ` Wang, Wen W
     [not found]                 ` <0A882F4D99BBF6449D58E61AAFD7EDD613677A5B-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2009-04-23 11:22                   ` Jean Delvare
     [not found]                     ` <20090423132224.25553a5b-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-04-30  7:15                       ` Wang, Wen W
2009-04-23  9:04     ` [PATCH 1/1] " Wang, Wen W
2009-04-23 10:19     ` [PATCH 0/2] " Wang, Wen W
     [not found]       ` <0A882F4D99BBF6449D58E61AAFD7EDD613677A65-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2009-04-23 10:22         ` [PATCH 1/2] " Wang, Wen W
     [not found]           ` <0A882F4D99BBF6449D58E61AAFD7EDD613677A69-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2009-04-23 10:25             ` [PATCH 2/2] " Wang, Wen W
2009-05-14  7:35         ` [PATCH 0/1] " Wang, Wen W
     [not found]           ` <0A882F4D99BBF6449D58E61AAFD7EDD62876816C-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2009-05-14  7:39             ` [PATCH 1/1] " Wang, Wen W
     [not found]               ` <0A882F4D99BBF6449D58E61AAFD7EDD628768177-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2009-06-15 11:50                 ` Jean Delvare
     [not found]                   ` <20090615135058.1bf40a75-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-06-26  2:41                     ` Wang, Wen W
     [not found]                       ` <0A882F4D99BBF6449D58E61AAFD7EDD62F26B15F-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2009-06-26  7:50                         ` Jean Delvare
     [not found]                           ` <20090626095026.22c5d6c1-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-06-26  7:54                             ` Wang, Wen W
     [not found]                               ` <0A882F4D99BBF6449D58E61AAFD7EDD62F26B3F4-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2009-12-17 13:28                                 ` Jean Delvare
     [not found]                                   ` <20091217142836.01af265c-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-12-18  1:37                                     ` Wang, Wen W
2009-05-14  7:52             ` [PATCH 0/1] " Jean Delvare
     [not found]               ` <20090514095201.577b17c4-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-05-14 10:50                 ` Wang, Wen W
2009-05-27  2:06                 ` Wang, Wen W
     [not found]                   ` <0A882F4D99BBF6449D58E61AAFD7EDD62EEF13AC-Uz4Je35TzWuiAffOGbnezLfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2009-05-27  6:39                     ` Jean Delvare
     [not found]                       ` <20090527083957.20641ebc-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-06-09  8:45                         ` Jean Delvare
     [not found]                           ` <20090609104555.6d81c106-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2009-06-09  9:00                             ` Wen Wang
     [not found]                               ` <20090609090049.GB28640-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2009-06-09  9:28                                 ` Jean Delvare

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.