[PATCH 2/2] I2C: I2C controller driver for Intel Moorestown platform

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>From 84ad2b6f3e80eca16e9f87eae5389569b9eeed13 Mon Sep 17 00:00:00 2001
From: Wen Wang <wen.w.wang@xxxxxxxxx>
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@xxxxxxxxx>
---
 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@xxxxxxxxxxxxxxx; 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@xxxxxxxxx>
>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@xxxxxxxxx>
>
>---
> 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@xxxxxxxxx>");
>+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@xxxxxxxxxxxxxxx; 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
?韬{.n?????%??檩??w?{.n???{炳-?)?骅w*jg????????G??⒏⒎?:+v????????????"??????

[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux