

From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
Subject: OKI Semiconductor PCH I2C driver

This driver implements I2C controls for PCH.

Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
Acked-by: Wang Qi <qi.wang@intel.com>

---
 drivers/i2c/busses/Kconfig        |  7 +
 drivers/i2c/busses/Makefile       |  3
 drivers/i2c/busses/pch_common.h   |  146
 drivers/i2c/busses/pch_debug.h    |  60
 drivers/i2c/busses/pch_i2c_hal.c  |  1930
 drivers/i2c/busses/pch_i2c_hal.h  |  337
 drivers/i2c/busses/pch_i2c_main.c |  247
 drivers/i2c/busses/pch_i2c_pci.c  |  583
 drivers/i2c/i2c-dev.c             |  28
+++++++++++++++++++++++++++++++ 9 files changed, yy insertions(+)
diff -urN linux-2.6.33.1/drivers/i2c/busses/Kconfig topcliff-2.6.33.1/drivers/i2c/busses/Kconfig
--- linux-2.6.33.1/drivers/i2c/busses/Kconfig	2010-03-16 01:09:39.000000000 +0900
+++ topcliff-2.6.33.1/drivers/i2c/busses/Kconfig	2010-03-23 10:40:18.000000000 +0900
@@ -7,6 +7,13 @@
 comment "PC SMBus host controller drivers"
 	depends on PCI
 
+config PCH_I2C
+	tristate "PCH I2C"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the SMB
+	  PCH I2C Host controller.
+
 config I2C_ALI1535
 	tristate "ALI 1535"
 	depends on PCI
diff -urN linux-2.6.33.1/drivers/i2c/busses/Makefile topcliff-2.6.33.1/drivers/i2c/busses/Makefile
--- linux-2.6.33.1/drivers/i2c/busses/Makefile	2010-03-16 01:09:39.000000000 +0900
+++ topcliff-2.6.33.1/drivers/i2c/busses/Makefile	2010-03-23 10:40:18.000000000 +0900
@@ -75,3 +75,6 @@
 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
+
+obj-$(CONFIG_PCH_I2C) += pch_i2c.o
+pch_i2c-objs := pch_i2c_main.o pch_i2c_pci.o pch_i2c_hal.o
diff -urN linux-2.6.33.1/drivers/i2c/busses/pch_common.h topcliff-2.6.33.1/drivers/i2c/busses/pch_common.h
--- linux-2.6.33.1/drivers/i2c/busses/pch_common.h	1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/i2c/busses/pch_common.h	2010-03-23 10:40:18.000000000 +0900
@@ -0,0 +1,146 @@
+/*!
+ * @file ioh_common.h
+ * @brief Provides the macro definitions used by all files.
+ * @version 1.0.0.0
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ *	WIPRO 03/07/2009
+ * modified:
+ *	WIPRO 05/08/2009
+ *
+ */
+
+#ifndef __IOH_COMMON_H__
+#define __IOH_COMMON_H__
+
+/*! @ingroup	Global
+@def		    IOH_WRITE8
+@brief			Macro for writing 8 bit data to an io/mem address
+*/
+#define IOH_WRITE8(val, addr)   iowrite8((val), (void __iomem *)(addr))
+/*! @ingroup	Global
+@def		    IOH_LOG
+@brief			Macro for writing 16 bit data to an io/mem address
+*/
+#define IOH_WRITE16(val, addr)  iowrite16((val), (void __iomem *)(addr))
+/*! @ingroup	Global
+@def		    IOH_LOG
+@brief			Macro for writing 32 bit data to an io/mem address
+*/
+#define IOH_WRITE32(val, addr)  iowrite32((val), (void __iomem *)(addr))
+
+/*! @ingroup	Global
+@def		    IOH_READ8
+@brief			Macro for reading 8 bit data from an io/mem address
+*/
+#define IOH_READ8(addr)   ioread8((void __iomem *)(addr))
+/*! @ingroup	Global
+@def		    IOH_READ16
+@brief			Macro for reading 16 bit data from an io/mem address
+*/
+#define IOH_READ16(addr)  ioread16((void __iomem *)(addr))
+/*! @ingroup	Global
+@def		    IOH_READ32
+@brief			Macro for reading 32 bit data from an io/mem address
+*/
+#define IOH_READ32(addr)  ioread32((void __iomem *)(addr))
+/*! @ingroup	Global
+@def		    IOH_WRITE32_F
+@brief			Macro for writing 32 bit data to an io/mem address
+*/
+#define IOH_WRITE32_F(val, addr) do \
+	{ IOH_WRITE32((val), (addr)); (void)IOH_READ32((addr)); } while (0);
+
+/*! @ingroup	Global
+@def		    IOH_WRITE_BYTE
+@brief			Macro for writing 1 byte data to an io/mem address
+*/
+#define IOH_WRITE_BYTE IOH_WRITE8
+/*! @ingroup	Global
+@def		    IOH_WRITE_WORD
+@brief			Macro for writing 1 word data to an io/mem address
+*/
+#define IOH_WRITE_WORD IOH_WRITE16
+/*! @ingroup	Global
+@def		    IOH_WRITE_LONG
+@brief			Macro for writing long data to an io/mem address
+*/
+#define IOH_WRITE_LONG IOH_WRITE32
+
+/*! @ingroup	Global
+@def		    IOH_READ_BYTE
+@brief			Macro for reading 1 byte data from an io/mem address
+*/
+#define IOH_READ_BYTE  IOH_READ8
+/*! @ingroup	Global
+@def		    IOH_READ_WORD
+@brief			Macro for reading 1 word data from an io/mem address
+*/
+#define IOH_READ_WORD  IOH_READ16
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			Macro for reading long data from an io/mem address
+*/
+#define IOH_READ_LONG  IOH_READ32
+
+/* Bit Manipulation Macros */
+
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			macro to set a specified bit(mask) at the
+			specified address
+*/
+#define IOH_SET_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) |\
+							 (bitmask)), (addr))
+
+/*! @ingroup	Global
+@def	    IOH_READ_LONG
+@brief		macro to clear a specified bit(mask) at the specified address
+*/
+#define IOH_CLR_ADDR_BIT(addr, bitmask) IOH_WRITE_LONG((IOH_READ_LONG(addr) &\
+							 ~(bitmask)), (addr))
+
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			macro to set a specified bitmask for a variable
+*/
+#define IOH_SET_BITMSK(var, bitmask) ((var) |= (bitmask))
+
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			macro to clear a specified bitmask for a variable
+*/
+#define IOH_CLR_BITMSK(var, bitmask) ((var) &= (~(bitmask)))
+
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			macro to set a specified bit for a variable
+*/
+#define IOH_SET_BIT(var, bit) ((var) |= (1<<(bit)))
+
+/*! @ingroup	Global
+@def		    IOH_READ_LONG
+@brief			macro to clear a specified bit for a variable
+*/
+#define IOH_CLR_BIT(var, bit) ((var) &= ~(1<<(bit)))
+
+#endif
diff -urN linux-2.6.33.1/drivers/i2c/busses/pch_debug.h topcliff-2.6.33.1/drivers/i2c/busses/pch_debug.h
--- linux-2.6.33.1/drivers/i2c/busses/pch_debug.h	1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/i2c/busses/pch_debug.h	2010-03-23 10:40:18.000000000 +0900
@@ -0,0 +1,60 @@
+/*!
+ * @file ioh_debug.h
+ * @brief Provides the macro definitions used for debugging.
+ * @version 1.0.0.0
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ *	WIPRO 03/07/2009
+ * modified:
+ *	WIPRO 05/08/2009
+ *
+ */
+
+#ifndef __IOH_DEBUG_H__
+#define __IOH_DEBUG_H__
+
+#ifdef MODULE
+#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n",\
+						 THIS_MODULE->name, ##args)
+#else
+#define IOH_LOG(level, fmt, args...) printk(level "%s:" fmt "\n" ,\
+							 __FILE__, ##args)
+#endif
+
+
+#ifdef DEBUG
+	#define IOH_DEBUG(fmt, args...) IOH_LOG(KERN_DEBUG, fmt, ##args)
+#else
+	#define IOH_DEBUG(fmt, args...)
+#endif
+
+#ifdef IOH_TRACE_ENABLED
+	#define IOH_TRACE IOH_DEBUG
+#else
+	#define IOH_TRACE(fmt, args...)
+#endif
+
+#define IOH_TRACE_ENTER IOH_TRACE("Enter %s", __func__)
+#define IOH_TRACE_EXIT 	IOH_TRACE("Exit %s", __func__)
+
+
+#endif
diff -urN linux-2.6.33.1/drivers/i2c/busses/pch_i2c_hal.c topcliff-2.6.33.1/drivers/i2c/busses/pch_i2c_hal.c
--- linux-2.6.33.1/drivers/i2c/busses/pch_i2c_hal.c	1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/i2c/busses/pch_i2c_hal.c	2010-03-23 10:40:18.000000000 +0900
@@ -0,0 +1,1930 @@
+/*!
+* @file		ioh_i2c_hal.c
+* @brief 	This file contains definitions of HAL Layer APIs and
+*		Internal functions
+* @version 0.95
+* @section
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; version 2 of the License.
+*
+* This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+/*
+* History:
+* Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+* All rights reserved.
+*
+* created:
+*	WIPRO 02/20/2009
+* modified:
+*	WIPRO 05/21/2009
+*
+*/
+
+/*includes*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+
+#include "pch_i2c_hal.h"
+#include "pch_common.h"
+#include "pch_debug.h"
+
+/**
+ *macro definition
+ */
+
+/*! @ingroup	I2C_HALLayer
+@def 		IOH_I2CSADR
+@brief 		I2CSADR register offset
+*/
+#define IOH_I2CSADR	(0x00)	/* I2C slave address register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CCTL
+@brief 		I2CCTL register offset
+*/
+#define IOH_I2CCTL	(0x04)	/* I2C control register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CSR
+@brief 		I2CSR register offset
+*/
+#define IOH_I2CSR	(0x08)	/* I2C status register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CDR
+@brief 		I2CDR register offset
+*/
+#define IOH_I2CDR	(0x0C)	/* I2C data register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CMON
+@brief 		I2CMON register offset
+*/
+#define IOH_I2CMON	(0x10)	/* I2C bus monitor register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CBC
+@brief 		I2CBC register offset
+*/
+#define IOH_I2CBC	(0x14)	/* I2C bus transfer rate setup counter */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CMOD
+@brief 		I2CMOD register offset
+*/
+#define IOH_I2CMOD	(0x18)	/* I2C mode register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CBUFSLV
+@brief 		I2CBUFSLV register offset
+*/
+#define IOH_I2CBUFSLV	(0x1C)	/* I2C buffer mode slave address register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CBUFSUB
+@brief 		I2CBUFSUB register offset
+*/
+#define IOH_I2CBUFSUB	(0x20)	/* I2C buffer mode subaddress register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CBUFFOR
+@brief 		I2CBUFFOR register offset
+*/
+#define IOH_I2CBUFFOR	(0x24)	/* I2C buffer mode format register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CBUFCTL
+@brief 		I2CBUFCTL register offset
+*/
+#define IOH_I2CBUFCTL	(0x28)	/* I2C buffer mode control register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CBUFMSK
+@brief 		I2CBUFMSK register offset
+*/
+#define IOH_I2CBUFMSK	(0x2C)	/* I2C buffer mode interrupt mask register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CBUFSTA
+@brief 		I2CBUFSTA register offset
+*/
+#define IOH_I2CBUFSTA	(0x30)	/* I2C buffer mode status register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CBUFLEV
+@brief 		I2CBUFLEV register offset
+*/
+#define IOH_I2CBUFLEV	(0x34)	/* I2C buffer mode level register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CESRFOR
+@brief 		I2CESRFOR register offset
+*/
+#define IOH_I2CESRFOR	(0x38)	/* EEPROM software reset mode format register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CESRCTL
+@brief 		I2CESRCTL register offset
+*/
+#define IOH_I2CESRCTL	(0x3C) /* EEPROM software reset mode control register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CESRMSK
+@brief 		I2CESRMSK register offset
+*/
+#define IOH_I2CESRMSK	(0x40)	/* EEPROM software reset mode
+				 * interrupt mask register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CESRSTA
+@brief 		I2CESRSTA register offset
+*/
+#define IOH_I2CESRSTA	(0x44)	/* EEPROM software reset mode status register */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CTMR
+@brief 		I2CTMR register offset
+*/
+#define IOH_I2CTMR	(0x48)	/* I2C timer register  */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CSRST
+@brief 		I2CSRST register offset
+*/
+#define IOH_I2CSRST	(0xFC)	/* I2C reset register  */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CNF
+@brief 		I2CNF register offset
+*/
+#define IOH_I2CNF	(0xF8)	/* I2C noise filter register  */
+
+/*! @ingroup 	I2C_HALLayer
+@def 		BUS_IDLE_TIMEOUT
+@brief 		Time out value when waiting for Bus Idle
+*/
+#define BUS_IDLE_TIMEOUT	(20)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_I2CCTL_I2CMEN
+@brief 		Bitmask to enable I2CMEN bit
+*/
+#define IOH_I2CCTL_I2CMEN 	(0x0080)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		TEN_BIT_ADDR_DEFAULT
+@brief 		Default bits to be added for 10 bit addressing
+*/
+#define TEN_BIT_ADDR_DEFAULT 	(0xF000)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		TEN_BIT_ADDR_MASK
+@brief 		10 bit address mask
+*/
+#define TEN_BIT_ADDR_MASK	(0xF0)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_START
+@brief 		Set the start bit in Normal mode
+*/
+#define IOH_START		(0x0020)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_ESR_START
+@brief 		Bitmask to set Start bit in EEPROM Software Reset mode
+*/
+#define IOH_ESR_START 		(0x0001)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_BUFF_START
+@brief 		Bitmask to set Start bit in Buffer mode
+*/
+#define IOH_BUFF_START 		(0x1)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_REPSTART
+@brief 		Bitmask to set repeated start bit
+*/
+#define IOH_REPSTART		(0x0004)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_ACK
+@brief 		Ack bit position in I2CCTL register
+*/
+#define IOH_ACK			(0x0008)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_GETACK
+@brief 		Mask to extract the ack bit
+*/
+#define IOH_GETACK 		(0x0001)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		CLR_REG
+@brief 		Mask for register reset
+*/
+#define CLR_REG 		(0x0)
+/*! @ingroup 	I2C_HALLayer
+@def 		I2C_RD
+@brief 		Set read bit in I2CDR with slave address
+*/
+#define I2C_RD			(0x1)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CMCF_BIT
+@brief 		Mask for I2CMCF bit
+*/
+#define I2CMCF_BIT		(0x0080)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CMIF_BIT
+@brief 		Mask for  I2CMIF bit
+*/
+#define I2CMIF_BIT		(0x0002)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CMAL_BIT
+@brief 		Mask for I2CMAL bit
+*/
+#define I2CMAL_BIT		(0x0010)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMFI_BIT
+@brief 		Mask for I2CBMFI bit
+*/
+#define I2CBMFI_BIT		(0x0001)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMAL_BIT
+@brief 		Mask for I2CBMAL bit
+*/
+#define I2CBMAL_BIT		(0x0002)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMNA_BIT
+@brief 		Mask for I2CBMNA bit
+*/
+#define I2CBMNA_BIT 		(0x0004)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMTO_BIT
+@brief 		Mask for I2CBMTO bit
+*/
+#define I2CBMTO_BIT 		(0x0008)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMIS_BIT
+@brief 		Mask for I2CBMIS bit
+*/
+#define I2CBMIS_BIT 		(0x0010)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CESRFI_BIT
+@brief 		Mask for I2CESRFI bit
+*/
+#define I2CESRFI_BIT		(0X0001)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CESRTO_BIT
+@brief 		Mask for I2CESRTO bit
+*/
+#define I2CESRTO_BIT 		(0x0002)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CESRFIIE_BIT
+@brief 		Mask for I2CESRFIIE bit
+*/
+#define I2CESRFIIE_BIT 		(0x1)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CESRTOIE_BIT
+@brief 		Mask for I2CESRTOIE bit
+*/
+#define I2CESRTOIE_BIT  	(0x2)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMDZ_BIT
+@brief 		Mask for I2CBMDZ bit
+*/
+#define I2CBMDZ_BIT		(0x0040)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMAG_BIT
+@brief 		Mask for I2CBMAG bit
+*/
+#define I2CBMAG_BIT		(0x0020)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CMBB_BIT
+@brief 		Mask for I2CMBB bit
+*/
+#define I2CMBB_BIT		(0x0020)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		BUFFER_MODE_MASK
+@brief 		Status bit mask in buffer mode
+*/
+#define BUFFER_MODE_MASK	(I2CBMFI_BIT | I2CBMAL_BIT | I2CBMNA_BIT | \
+				I2CBMTO_BIT | I2CBMIS_BIT)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2C_ADDR_MSK
+@brief 		Mask to get the 8 LSB bits in 10 bit addressing
+*/
+#define I2C_ADDR_MSK		(0xFF)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2C_MSB_2B_MSK
+@brief 		Mask to get the 2 MSB bits in 10 bit addressing
+*/
+#define I2C_MSB_2B_MSK		(0x300)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		FAST_MODE_CLK
+@brief 		Fast mode clock in KHz
+*/
+#define FAST_MODE_CLK		(400)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		FAST_MODE_EN
+@brief 		Enable the fast mode
+*/
+#define FAST_MODE_EN		(0x0001)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		SUB_ADDR_LEN_MAX
+@brief 		Maximum sub address length
+*/
+#define SUB_ADDR_LEN_MAX	(4)
+
+/*! @ingroup	I2C_HALLayer
+@def 		BUF_LEN_MAX
+@brief 		Maximum buffer length in buffer mode
+*/
+#define BUF_LEN_MAX		(32)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_BUFFER_MODE
+@brief 		To enable the buffer mode
+*/
+#define IOH_BUFFER_MODE		(0x1)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		EEPROM_SW_RST_MODE
+@brief 		Mask to enable the EEPROM Software Reset mode
+*/
+#define EEPROM_SW_RST_MODE	(0x0002)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		NORMAL_INTR_ENBL
+@brief 		Mask to enable the I2C interrupts in normal mode
+*/
+#define NORMAL_INTR_ENBL	(0x0300)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		EEPROM_RST_INTR_ENBL
+@brief 		Mask to enable I2CESRFI, I2CESRTO interrupts
+		in EEPROM Software Reset mode
+*/
+#define EEPROM_RST_INTR_ENBL 	(I2CESRFIIE_BIT | I2CESRTOIE_BIT)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		EEPROM_RST_INTR_DISBL
+@brief 		Mask to disable interrupts in EEPROM Software Reset mode
+*/
+#define EEPROM_RST_INTR_DISBL 	(0x0)
+
+/*! @ingroup	I2C_HALLayer
+@def 		BUFFER_MODE_INTR_ENBL
+@brief 		Mask to enable I2CBMIS,I2CBMTO,I2CBMNA,I2CBMAL,I2CBMFI
+		interrupts in Buffer mode
+*/
+#define BUFFER_MODE_INTR_ENBL	(0x001F)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		BUFFER_MODE_INTR_DISBL
+@brief 		Mask to disable all interrupts in Buffer mode
+*/
+#define BUFFER_MODE_INTR_DISBL	(0x0)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		NORMAL_MODE
+@brief 		Specifies Normal mode
+*/
+#define NORMAL_MODE		(0x0)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		BUFFER_MODE
+@brief 		Specifies Buffer mode
+*/
+#define BUFFER_MODE		(0x1)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		EEPROM_SR_MODE
+@brief 		Specifies EEPROM software reset mode
+*/
+#define EEPROM_SR_MODE		(0x2)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2C_TX_MODE
+@brief 		Specifies Master transmission mode
+*/
+#define I2C_TX_MODE 		(0x0010)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_BUF_TX
+@brief 		Specifies Buffer transmission mode
+*/
+#define IOH_BUF_TX 		(0xFFF7)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		IOH_BUF_RD
+@brief 		Specifies Buffer reception mode
+*/
+#define IOH_BUF_RD		(0x0008)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2C_ERROR_MASK
+@brief 		Mask for errors in all modes
+*/
+#define I2C_ERROR_MASK	(I2CESRTO_EVENT | I2CBMIS_EVENT | I2CBMTO_EVENT | \
+			I2CBMNA_EVENT | I2CBMAL_EVENT | I2CMAL_EVENT)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CMAL_EVENT
+@brief 		MAL bit position in event flag
+*/
+#define I2CMAL_EVENT 		(0x0001)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CMCF_EVENT
+@brief 		MCF bit position in event flag
+*/
+#define I2CMCF_EVENT		(0x0002)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMFI_EVENT
+@brief 		I2CBMFI bit position in event flag
+*/
+#define I2CBMFI_EVENT 		(0x0004)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMAL_EVENT
+@brief 		I2CBMAL bit position in event flag
+*/
+#define I2CBMAL_EVENT 		(0x0008)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMNA_EVENT
+@brief 		I2CBMNA bit position in event flag
+*/
+#define I2CBMNA_EVENT		(0x0010)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMTO_EVENT
+@brief 		I2CBMTO bit position in event flag
+*/
+#define I2CBMTO_EVENT 		(0x0020)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CBMIS_EVENT
+@brief 		I2CBMIS bit position in event flag
+*/
+#define I2CBMIS_EVENT 		(0x0040)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CESRFI_EVENT
+@brief 		I2CESRFI bit position in event flag
+*/
+#define I2CESRFI_EVENT 		(0x0080)
+
+/*! @ingroup 	I2C_HALLayer
+@def 		I2CESRTO_EVENT
+@brief 		I2CESRTO bit position in event flag
+*/
+#define I2CESRTO_EVENT 		(0x0100)
+
+/*
+ * wait queue head
+ */
+
+/*! @ingroup 	I2C_UtilitiesAPI
+@var 		ioh_i2c_event
+@brief  	Wait queue head
+@remarks	This global variable is used to synchronize
+		data handling with interrupts
+@see		- ioh_i2c_init
+		- ioh_i2c_cb
+*/
+static wait_queue_head_t ioh_i2c_event;
+
+/* Function prototypes */
+
+/*! @ingroup 	I2C_UtilitiesAPI
+@fn 		ioh_i2c_start(struct i2c_algo_ioh_data * adap)
+@brief  	Function to generate start condition in normal mode
+*/
+static void ioh_i2c_start(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup 	I2C_UtilitiesAPI
+@fn 		ioh_i2c_buff_mode_start(struct i2c_algo_ioh_data * adap)
+@brief  	Function to generate start condition in buffer mode
+*/
+static void ioh_i2c_buff_mode_start(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup 	I2C_UtilitiesAPI
+@fn 		ioh_i2c_eeprom_swrst_start(struct i2c_algo_ioh_data * adap)
+@brief  	Function to generate start condition in EEPROM Software
+		Reset mode
+*/
+static void ioh_i2c_eeprom_swrst_start(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup 	I2C_UtilitiesAPI
+@fn 		ioh_i2c_stop(struct i2c_algo_ioh_data *adap)
+@brief  	Function to generate stop condition in normal mode
+*/
+static void ioh_i2c_stop(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup 	I2C_UtilitiesAPI
+@fn 		ioh_i2c_repstart(struct i2c_algo_ioh_data *adap)
+@brief  	Function to generate repeated start condition in normal mode
+*/
+static void ioh_i2c_repstart(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup 	I2C_UtilitiesAPI
+@fn 		ioh_i2c_getack(struct i2c_algo_ioh_data *adap)
+@brief  	Function to confirm ACK/NACK
+*/
+static s32 ioh_i2c_getack(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup 	I2C_UtilitiesAPI
+@fn 		ioh_i2c_sendack(struct i2c_algo_ioh_data *adap)
+@brief  	Function to send ACK
+*/
+static void ioh_i2c_sendack(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup 	I2C_UtilitiesAPI
+@fn 		ioh_i2c_sendnack(struct i2c_algo_ioh_data *adap)
+@brief  	Function to send NACK
+*/
+static void ioh_i2c_sendnack(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup 	I2C_UtilitiesAPI
+@fn 		ioh_i2c_wait_for_bus_idle
+		(struct i2c_algo_ioh_data *adap,s32 timeout)
+@brief  	Function to check the status of bus
+*/
+static s32 ioh_i2c_wait_for_bus_idle(struct i2c_algo_ioh_data *adap,
+				     s32 timeout);
+
+/*! @ingroup 	I2C_UtilitiesAPI
+@fn 		ioh_i2c_wait_for_xfer_complete(struct i2c_algo_ioh_data *adap)
+@brief  	Function to wait till transfer complete.
+*/
+static s32 ioh_i2c_wait_for_xfer_complete(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup 	I2C_HALLayerAPI
+  @fn		ioh_i2c_init(struct i2c_algo_ioh_data * adap)
+  @remarks	Implements the hardware initialization of I2C module.
+		The main tasks performed by this method are:
+		- Clear I2CCTL,I2CMOD,I2CBUFFOR,I2CBUFSLV,I2CBUFSUB,I2CBUFMSK,
+		  I2CESRFOR,I2CESRMSK registers.
+		- Set I2CMEN in I2CCTL to 1.
+		- Set bus speed based on module parameter.
+		- Enable required interrupts.
+		- Initialize wait queue head.
+  @note		This function always returns @ref IOH_I2C_SUCCESS
+  @param  	adap	[@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval 	s32
+		- @ref	IOH_I2C_SUCCESS	Function returns successfully.
+  @see      	- ioh_i2c_probe
+		- ioh_i2c_resume
+ <hr>
+  */
+s32 ioh_i2c_init(struct i2c_algo_ioh_data *adap)
+{
+	u32 ioh_i2cbc;
+	u32 ioh_i2ctmr;
+	u32 reg_value = 0;
+
+#ifndef FPGA
+	/*reset I2C controller */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CSRST, 0x1);
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CSRST, 0x0);
+#endif
+	/* Initialize I2C registers */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CCTL, CLR_REG);
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CMOD, CLR_REG);
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFFOR, CLR_REG);
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFSLV, CLR_REG);
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFSUB, CLR_REG);
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFMSK, CLR_REG);
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CESRFOR, CLR_REG);
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CESRMSK, CLR_REG);
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CNF, 0x21);
+	IOH_DEBUG
+	    ("Cleared the registers IOH_I2CCTL,IOH_I2CMOD,IOH_I2CBUFFOR\n,"
+	     "IOH_I2CBUFSLV,IOH_I2CBUFSUB,IOH_I2CBUFMSK,"
+	     "\nIOH_I2CESRFOR,IOH_I2CESRMSK\n");
+
+	reg_value |= IOH_I2CCTL_I2CMEN;
+	adap->set_reg_bit((adap->ioh_i2c_base_address), IOH_I2CCTL,
+			  IOH_I2CCTL_I2CMEN);
+
+	ioh_i2c_speed = (ioh_i2c_speed == 400) ? 400 : 100;
+
+	if (ioh_i2c_speed == FAST_MODE_CLK) {
+		reg_value |= FAST_MODE_EN;
+		IOH_DEBUG("Fast mode enabled\n");
+	}
+
+	ioh_i2c_clk = (ioh_i2c_clk <= 0
+		       || ioh_i2c_clk > IOH_I2C_MAX_CLK) ? 62500 : ioh_i2c_clk;
+
+	ioh_i2cbc = ((ioh_i2c_clk) + (ioh_i2c_speed * 4)) / (ioh_i2c_speed * 8);
+	/* Set transfer speed in I2CBC */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBC, ioh_i2cbc);
+
+	ioh_i2ctmr = (ioh_i2c_clk) / 8;
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CTMR, ioh_i2ctmr);
+
+	reg_value |= NORMAL_INTR_ENBL;	/* Enable interrupts in normal mode */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CCTL, reg_value);
+
+	IOH_DEBUG("In ioh_i2c_init: I2CCTL =%x\n",
+		  (adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+	IOH_DEBUG("In ioh_i2c_init: ioh_i2cbc =%x\n", ioh_i2cbc);
+	IOH_DEBUG("In ioh_i2c_init: ioh_i2ctmr =%x\n", ioh_i2ctmr);
+
+	IOH_DEBUG("Enable interrupts\n");
+	init_waitqueue_head(&ioh_i2c_event);
+	return IOH_I2C_SUCCESS;
+}
+
+/*! @ingroup 	I2C_HALLayerAPI
+  @fn  		ioh_i2c_writebytes(struct i2c_adapter *i2c_adap ,
+			struct i2c_msg *msgs, u32 last, u32 first)
+  @remarks  	Function to write data to I2C bus in normal mode.
+		The main tasks performed by this method are:
+		- Enable transmission mode.
+		- Send out the slave address.
+		- Wait for Bus idle and send out Start signal
+		- Perform data write operation.
+		- Send stop or repeat start as necessary, depending on whether
+		  the current message is the last message or not.
+		- Return with number of bytes transferred successfully or
+		  the error code
+  @param  	i2c_adap [@ref IN] contains reference to the struct i2c_adapter
+  @param 	msgs	 [@ref IN] contains reference to i2c_msg structure
+  @param 	last	 [@ref IN] specifies whether last message or not
+			   In the case of compound mode it will be
+			   1 for last message, otherwise 0.
+  @param 	first	 [@ref IN] specifies whether first message or not
+			   1 for first message otherwise 0.
+  @retval	s32
+		- Number of bytes transferred successfully
+		- @ref IOH_I2C_FAIL	@ref ioh_i2c_wait_for_bus_idle,
+					@ref ioh_i2c_wait_for_xfer_complete,
+					@ref ioh_i2c_getack fails
+		- -ERESTARTSYS
+		 @ref ioh_i2c_wait_for_xfer_complete was interrupted by a signal
+  @see		ioh_i2c_xfer
+ <hr>
+ */
+s32 ioh_i2c_writebytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
+				u32 last, u32 first)
+{
+
+	struct i2c_algo_ioh_data *adap = i2c_adap->algo_data;
+
+	u8 *buf;
+	u32 length;
+	u32 addr;
+	u32 addr_2_msb;
+	u32 addr_8_lsb;
+	s32 wrcount = IOH_I2C_FAIL;
+	length = msgs->len;
+	buf = msgs->buf;
+	addr = msgs->addr;
+	/* enable master tx */
+	adap->set_reg_bit((adap->ioh_i2c_base_address), IOH_I2CCTL,
+			  I2C_TX_MODE);
+
+	IOH_DEBUG("In ioh_i2c_writebytes : I2CCTL = %x\n",
+		  (adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+	IOH_DEBUG("In ioh_i2c_writebytes : msgs->len = %d\n", length);
+
+	if (first) {
+		if (ioh_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) ==
+		    IOH_I2C_FAIL) {
+			return IOH_I2C_FAIL;
+		}
+	}
+
+	if ((msgs->flags & I2C_M_TEN) != false) {
+		addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7);
+		adap->writereg((adap->ioh_i2c_base_address), IOH_I2CDR,
+			       (addr_2_msb | TEN_BIT_ADDR_MASK));
+
+		if (first)
+			ioh_i2c_start(adap);
+		if ((ioh_i2c_wait_for_xfer_complete(adap) == IOH_I2C_SUCCESS) &&
+		    (ioh_i2c_getack(adap) == IOH_I2C_SUCCESS)) {
+			addr_8_lsb = (addr & I2C_ADDR_MSK);
+			adap->writereg((adap->ioh_i2c_base_address), IOH_I2CDR,
+				       (addr_8_lsb));
+
+		} else {
+			ioh_i2c_stop(adap);
+			return IOH_I2C_FAIL;
+		}
+	} else {
+		/* set 7 bit slave address and R/W bit as 0 */
+		adap->writereg((adap->ioh_i2c_base_address), IOH_I2CDR,
+			       ((addr) << 1));
+		if (first)
+			ioh_i2c_start(adap);
+	}
+
+	if ((ioh_i2c_wait_for_xfer_complete(adap) == IOH_I2C_SUCCESS) &&
+	    (ioh_i2c_getack(adap) == IOH_I2C_SUCCESS)) {
+		for (wrcount = 0; wrcount < length; ++wrcount) {
+			/* write buffer value to I2C data register */
+			adap->writereg((adap->ioh_i2c_base_address), IOH_I2CDR,
+				       buf[wrcount]);
+			IOH_DEBUG
+			  ("ioh_i2c_writebytes : writing %x to Data register\n",
+			   buf[wrcount]);
+
+			if (ioh_i2c_wait_for_xfer_complete(adap) !=
+			    IOH_I2C_SUCCESS) {
+				wrcount = IOH_I2C_FAIL;
+				break;
+			}
+
+			IOH_DEBUG("ioh_i2c_wait_for_xfer_complete return %d",
+				  IOH_I2C_SUCCESS);
+
+			if (ioh_i2c_getack(adap)) {
+				wrcount = IOH_I2C_FAIL;
+				break;
+			}
+		}
+
+		/* check if this is the last message */
+		if (last)
+			ioh_i2c_stop(adap);
+		else
+			ioh_i2c_repstart(adap);
+	} else {
+		ioh_i2c_stop(adap);
+	}
+
+	IOH_DEBUG(KERN_INFO, "ioh_i2c_writebytes return=%d\n", wrcount);
+
+	return wrcount;
+}
+
+/*! @ingroup 	I2C_HALLayerAPI
+  @fn  		ioh_i2c_readbytes(struct i2c_adapter *i2c_adap,
+			struct i2c_msg *msgs, u32 last, u32 first)
+  @remarks 	Function to read data  from I2C bus in normal mode.
+		The main tasks performed by this method are:
+		- Enable Reception mode.
+		- Send out the slave address.
+		- Wait for Bus idle and send out Start signal
+		- Perform data reads.
+		- Send stop or repeat start as necessary, depending on whether
+		  the current
+		  message read is the last message or not
+		- Return with number of bytes read (if successful) or
+		  the error code
+  @param  	i2c_adap [@ref IN] contains reference to the struct i2c_adapter
+  @param 	msgs	 [@ref INOUT] contains reference to i2c_msg structure
+  @param 	last	 [@ref IN] specifies whether last message or not
+  @param 	first	 [@ref IN] specifies whether first message or not
+  @retval 	s32	- Number of Bytes read successfully
+		- @ref IOH_I2C_FAIL    @ref ioh_i2c_wait_for_bus_idle,
+			@ref ioh_i2c_wait_for_xfer_complete,
+			@ref ioh_i2c_getack fails
+		- -ERESTARTSYS
+		 @ref ioh_i2c_wait_for_xfer_complete was interrupted by a signal
+  @see		ioh_i2c_xfer
+ <hr>
+ */
+s32 ioh_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
+			u32 last, u32 first)
+{
+
+	struct i2c_algo_ioh_data *adap = i2c_adap->algo_data;
+
+	u8 *buf;
+	u32 count = IOH_I2C_FAIL;
+	u32 length;
+	u32 addr;
+	u32 addr_2_msb;
+	length = msgs->len;
+	buf = msgs->buf;
+	addr = msgs->addr;
+
+	/* enable master reception */
+	adap->clr_reg_bit((adap->ioh_i2c_base_address), IOH_I2CCTL,
+			  I2C_TX_MODE);
+
+	if (first) {
+		if (ioh_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) ==
+		    IOH_I2C_FAIL) {
+			return IOH_I2C_FAIL;
+		}
+	}
+
+	if ((msgs->flags & I2C_M_TEN) != false) {
+		addr_2_msb = (((addr & I2C_MSB_2B_MSK) >> 7) | (I2C_RD));
+		adap->writereg((adap->ioh_i2c_base_address), IOH_I2CDR,
+			       (addr_2_msb | TEN_BIT_ADDR_MASK));
+
+	} else {
+		/* 7 address bits + R/W bit */
+		addr = (((addr) << 1) | (I2C_RD));
+		adap->writereg((adap->ioh_i2c_base_address), IOH_I2CDR, addr);
+	}
+
+	/* check if it is the first message */
+	if (first == true)
+		ioh_i2c_start(adap);
+
+	if ((ioh_i2c_wait_for_xfer_complete(adap) == IOH_I2C_SUCCESS)
+	    && (ioh_i2c_getack(adap) == IOH_I2C_SUCCESS)) {
+		IOH_DEBUG("ioh_i2c_wait_for_xfer_complete return %d",
+			  IOH_I2C_SUCCESS);
+
+		if (length == 0) {
+
+			ioh_i2c_stop(adap);
+			(void)adap->readreg((adap->ioh_i2c_base_address),
+					    IOH_I2CDR);
+
+			count = length;
+		} else {
+			int read_index = 0;
+			int loop;
+			ioh_i2c_sendack(adap);
+
+			/* Dummy read */
+
+			for (loop = 1; loop < length; loop++) {
+				buf[read_index] =
+				    adap->readreg((adap->ioh_i2c_base_address),
+						  IOH_I2CDR);
+
+				if (loop != 1)
+					read_index++;
+
+				if (ioh_i2c_wait_for_xfer_complete(adap) !=
+				    IOH_I2C_SUCCESS) {
+					ioh_i2c_stop(adap);
+					return IOH_I2C_FAIL;
+				}
+
+			}	/* end for */
+
+			ioh_i2c_sendnack(adap);
+
+			buf[read_index] =
+			    adap->readreg((adap->ioh_i2c_base_address),
+					  IOH_I2CDR);
+
+			if (length != 1)
+				read_index++;
+
+			if (ioh_i2c_wait_for_xfer_complete(adap) ==
+			    IOH_I2C_SUCCESS) {
+				if (last)
+					ioh_i2c_stop(adap);
+				else
+					ioh_i2c_repstart(adap);
+
+				buf[read_index++] =
+				    adap->readreg((adap->ioh_i2c_base_address),
+						  IOH_I2CDR);
+				count = read_index;
+			}
+
+		}
+	} else {
+		ioh_i2c_stop(adap);
+	}
+
+	return count;
+}
+
+/*! @ingroup	I2C_HALLayerAPI
+  @fn  		ioh_i2c_entcb(s32(*ioh_i2c_ptr)(struct i2c_algo_ioh_data *adap))
+  @remarks   	Function to register call back function.
+		The main tasks performed by this method are:
+		- Validate ioh_i2c_ptr
+		- Update the reference of the callback function in the callback
+		  function pointer.
+  @param  	ioh_i2c_ptr [@ref IN] Contains reference to call back function
+  @retval 	None
+  @see       	ioh_i2c_probe
+ <hr>
+ */
+void ioh_i2c_entcb(s32(*ioh_i2c_ptr) (struct i2c_algo_ioh_data *adap))
+{
+	if (ioh_i2c_ptr != NULL) {
+		IOH_DEBUG("value in ioh_i2c_ptr = %p", ioh_i2c_ptr);
+		/* set the handler call back function */
+		ioh_i2c_cbr = ioh_i2c_ptr;
+		IOH_DEBUG("value updated in ioh_i2c_cbr = %p", ioh_i2c_cbr);
+		IOH_DEBUG("Invoked ioh_i2c_entcb successfully");
+
+	}
+}
+
+/*! @ingroup	I2C_HALLayerAPI
+  @fn  		 	ioh_i2c_handler(int irq,void * pData)
+  @remarks   	This function implements the interrupt handler for
+		the IOH I2C controller.
+		The main tasks performed by this method are:
+		- Invoke callback function.
+		- Based on return value of callback function,
+		  return IRQ_NONE or IRQ_HANDLED
+  @param  	irq 	[@ref IN] irq number
+  @param 	pData	[@ref IN] cookie passed back to the handler function
+  @retval 	irqreturn_t
+		- IRQ_NONE		Not our interrupt
+		- IRQ_HANDLED	Interrupt serviced
+  @see		 	ioh_i2c_probe
+ <hr>
+ */
+irqreturn_t ioh_i2c_handler(int irq, void *pData)
+{
+	s32 ret = 0;
+	u32 i;
+
+	struct adapter_info *adap_info = (struct adapter_info *)pData;
+	/* invoke the call back  */
+
+	if (ioh_i2c_cbr != NULL) {
+		for (i = 0; i < IOH_I2C_MAX_CHN; i++)
+			ret |= (ioh_i2c_cbr) (&adap_info->ioh_i2c_data[i]);
+	} else {
+		IOH_LOG(KERN_ERR, " Call back pointer null ...");
+	}
+
+	IOH_DEBUG("ioh_i2c_cb return = %d\n", ret);
+
+	if (ret == IOH_I2C_EVENT_SET)
+		IOH_DEBUG(" ioh_i2c_handler return IRQ_HANDLED");
+	else
+		IOH_DEBUG("ioh_i2c_handler return IRQ_NONE");
+
+	return (ret == IOH_I2C_EVENT_SET) ? (IRQ_HANDLED) : (IRQ_NONE);
+}
+
+/*! @ingroup	I2C_HALLayerAPI
+  @fn  		ioh_i2c_buffer_read
+			(struct i2c_adapter * i2c_adap,struct i2c_msg *msgs)
+  @remarks   	Function to read data  from I2C bus in buffer mode.
+		The main tasks performed by this method are:
+		- Enable Buffer Mode.
+		- Set timeout interval in I2CTMR register.
+		- Enable buffer mode interrupts.
+		- Set the I2C Slave Address in the I2CBUFSLV register.
+		- Set the number of bytes, transmission mode and
+		  sub-address length in I2CBUFFOR register.
+		- Perform the data read.
+		- Disable buffer mode interrupts.
+  @param  	i2c_adap [@ref IN]  contains reference to the struct i2c_adapter
+  @param 	msgs	 [@ref INOUT] contains reference to i2c_msg structure
+  @retval 	s32
+		- @ref IOH_I2C_SUCCESS	Function returns successfully
+		- @ref IOH_I2C_FAIL		@ref ioh_i2c_wait_for_bus_idle,
+		  @ref ioh_i2c_wait_for_xfer_complete,
+		  @ref ioh_i2c_getack fails
+		- -ERESTARTSYS
+		 @ref ioh_i2c_wait_for_xfer_complete was interrupted by a signal
+  @see		ioh_i2c_xfer
+ <hr>
+ */
+s32 ioh_i2c_buffer_read(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs)
+{
+
+	struct i2c_algo_ioh_data *adap = i2c_adap->algo_data;
+
+	u32 loop;
+	u32 rdcount = 0;
+	u32 length;
+	u32 i2cbufsub = 0;
+	u32 addr;
+	u32 i2cbufslv_7_lsb;
+	u32 i2cbufslv_10_9_bit;
+	u32 msglen;
+	/* initialize to invalid length, so that no sub address is tx-ed */
+	u32 subaddrlen = 5;
+	u32 i2cmod_prev;
+	s32 i;
+	u32 time_interval = i2c_adap->timeout;
+	u32 i2ctmr;
+	s32 retvalue = IOH_I2C_FAIL;
+	u8 *buf;
+
+	length = msgs->len;
+	buf = msgs->buf;
+	addr = msgs->addr;
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFMSK,
+		BUFFER_MODE_INTR_ENBL);
+
+	/* get the current value of I2C mod register */
+	i2cmod_prev = adap->readreg((adap->ioh_i2c_base_address), IOH_I2CMOD);
+
+	/* enable buffer mode */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CMOD,
+		IOH_BUFFER_MODE);
+
+	time_interval = (time_interval <= 10) ? (time_interval) : (10);
+
+	/* value of I2CT = (Timeout interval * PCLK frequency)/ 8 */
+	i2ctmr = (time_interval * (ioh_i2c_clk)) / 8;
+
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CTMR, i2ctmr);
+
+	/* if 10 bit addressing is selected */
+
+	if ((msgs->flags & I2C_M_TEN) != false) {
+		/* get the 8 LSBits */
+		i2cbufslv_7_lsb = (addr & I2C_ADDR_MSK);
+
+		/* get the 2 MSBits */
+		i2cbufslv_10_9_bit = ((addr & I2C_MSB_2B_MSK) << 1);
+
+		adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFSLV,
+				(TEN_BIT_ADDR_DEFAULT | i2cbufslv_7_lsb |
+				i2cbufslv_10_9_bit));
+	} else {
+		adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFSLV,
+				((addr & I2C_ADDR_MSK) << 1));
+	}
+
+	/* get sub address length, restrict to 4 bytes max */
+	subaddrlen =
+	    (buf[0] <= SUB_ADDR_LEN_MAX) ? (buf[0]) : (SUB_ADDR_LEN_MAX);
+
+	for (i = (subaddrlen - 1); i >= 0; i--) {
+		/* frame the sub address based on the length */
+		i2cbufsub |= (((u32) buf[2 - i]) << (8 * i));
+	}
+
+	msglen = length - (subaddrlen + 1);
+
+	loop = (subaddrlen + 1);
+
+	/* write the sub address to the reg */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFSUB, i2cbufsub);
+	/* clear buffers */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFLEV, CLR_REG);
+
+	rdcount = (msglen <= BUF_LEN_MAX) ? (msglen) : (BUF_LEN_MAX);
+
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFFOR,
+		((rdcount << 4) | (IOH_BUF_RD) | (subaddrlen)));
+
+	do {
+		if (ioh_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) ==
+			IOH_I2C_FAIL) {
+			break;
+		}
+
+		ioh_i2c_buff_mode_start(adap);
+
+		IOH_DEBUG("buffer mode start");
+
+		if ((adap->readreg((adap->ioh_i2c_base_address),
+				   IOH_I2CBUFSTA) & I2CBMDZ_BIT) != 0) {
+			IOH_DEBUG("buffer read error 1");
+			break;
+		}
+
+		if (ioh_i2c_wait_for_xfer_complete(adap) == IOH_I2C_FAIL) {
+			IOH_DEBUG("buffer read error2");
+			break;
+		}
+
+		IOH_DEBUG("ioh_i2c_wait_for_xfer_complete return %d",
+				IOH_I2C_SUCCESS);
+
+		retvalue = rdcount;
+
+		for (; rdcount > 0; rdcount--, loop++) {
+			buf[loop] =
+			adap->readreg((adap->ioh_i2c_base_address),
+					IOH_I2CDR);
+
+		}
+	} while (0);
+
+	/* disable buffer mode interrupts */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFMSK,
+			BUFFER_MODE_INTR_DISBL);
+	/* restore the I2CMOD register */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CMOD, i2cmod_prev);
+
+	return retvalue;
+}
+
+/*! @ingroup 	I2C_HALLayerAPI
+  @fn  		ioh_i2c_buffer_write
+			(struct i2c_adapter * i2c_adap,struct i2c_msg * msgs)
+  @remarks 	Function to write data to I2C bus in buffer mode.
+		The main tasks performed by this method are:
+		- Enable Buffer Mode.
+		- Set timeout interval in I2CTMR register.
+		- Enable buffer mode interrupts.
+		- Set the I2C Slave Address in the I2CBUFSLV register.
+		- Set the number of bytes, transmission mode and
+		  subaddress length in I2CBUFFOR register.
+		- Perform data transfer.
+		- Disable the buffer mode interrupts.
+  @param  	i2c_adap [@ref IN] contains reference to the struct i2c_adapter
+  @param 	msgs	 [@ref INOUT] contains reference to i2c_msg structure
+  @retval    	s32
+		- @ref IOH_I2C_SUCCESS  Function returns successfully
+		- @ref IOH_I2C_FAIL    @ref ioh_i2c_wait_for_bus_idle,
+		  @ref ioh_i2c_wait_for_xfer_complete,
+		  @ref ioh_i2c_getack fails
+		- -ERESTARTSYS
+		 @ref ioh_i2c_wait_for_xfer_complete was interrupted by a signal
+  @see		ioh_i2c_xfer
+ <hr>
+ */
+s32 ioh_i2c_buffer_write(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs)
+{
+	struct i2c_algo_ioh_data *adap = i2c_adap->algo_data;
+
+	u32 loop = 0;
+	u32 wrcount = 0;
+	u32 msglen;
+	u32 i2cbufsub = 0;
+	u32 addr;
+	u32 i2cbufslv_7_lsb;
+	u32 i2cbufslv_10_9_bit;
+
+	/* initialize to invalid length, so that no sub address is tx-ed */
+	u32 subaddrlen = 5;
+	u32 i2cmod_prev;
+	s32 i;
+	u32 time_interval = i2c_adap->timeout;
+	u32 i2ctmr;
+	s32 retvalue = IOH_I2C_FAIL;
+	u8 *buf;
+
+	msglen = msgs->len;
+	buf = msgs->buf;
+	addr = msgs->addr;
+
+	/* get the current value of I2C mod register */
+	i2cmod_prev = adap->readreg((adap->ioh_i2c_base_address), IOH_I2CMOD);
+	/* enable buffer mode */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CMOD,
+			IOH_BUFFER_MODE);
+
+	time_interval = (time_interval <= 10) ? (time_interval) : (10);
+	/* value of I2CT = (Timeout interval * PCLK frequency)/ 8 */
+	i2ctmr = (time_interval * (ioh_i2c_clk)) / 8;
+
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CTMR, i2ctmr);
+
+	/* enable buffer mode interrupts */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFMSK,
+			BUFFER_MODE_INTR_ENBL);
+
+	/* if 10 bit addressing is selected */
+
+	if ((msgs->flags & I2C_M_TEN) != false) {
+		IOH_DEBUG("ioh_i2c_buffer_write...ten bit addressing");
+		/* get the 8 LSBits */
+		i2cbufslv_7_lsb = (addr & I2C_ADDR_MSK);
+
+		/* get the 2 MSBits */
+		i2cbufslv_10_9_bit = ((addr & I2C_MSB_2B_MSK) << 1);
+
+		adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFSLV,
+				(TEN_BIT_ADDR_DEFAULT | i2cbufslv_7_lsb |
+				i2cbufslv_10_9_bit));
+	} else {
+		adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFSLV,
+			((addr & I2C_ADDR_MSK) << 1));
+
+	}
+
+	/* get sub address length, restrict to 4 bytes max */
+	subaddrlen =
+		(buf[0] <= SUB_ADDR_LEN_MAX) ? (buf[0]) : (SUB_ADDR_LEN_MAX);
+
+	for (i = (subaddrlen - 1); i >= 0; i--) {
+		/* frame the sub address based on the length */
+		i2cbufsub |= (((u32) buf[2 - i]) << (8 * i));
+	}
+
+	/* subaddrlen bytes + the 1st field  */
+	loop = subaddrlen + 1;
+
+	msglen = msglen - loop;
+
+	/* write the sub address to the reg */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFSUB, i2cbufsub);
+
+	/* clear buffers */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFLEV, CLR_REG);
+
+	msglen = (msglen < BUF_LEN_MAX) ? (msglen) : (BUF_LEN_MAX);
+
+	for (wrcount = 0; wrcount < msglen; wrcount++) {
+		adap->writereg((adap->ioh_i2c_base_address), IOH_I2CDR,
+			buf[loop]);
+		IOH_DEBUG("Buffer mode %x", (buf[loop] & 0xff));
+		loop++;
+	}
+
+	/* set the number of bytes, transmission mode and sub address length */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFFOR,
+		((((wrcount << 4) & (IOH_BUF_TX)) | (subaddrlen))));
+
+	do {
+		if ((ioh_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT)) ==
+		    IOH_I2C_FAIL) {
+			break;
+		}
+
+		/* issue start bits */
+		ioh_i2c_buff_mode_start(adap);
+
+		if (((adap->readreg((adap->ioh_i2c_base_address),
+				IOH_I2CBUFSTA)) & (I2CBMDZ_BIT |
+						I2CBMAG_BIT)) != false) {
+			break;
+		}
+
+		if (ioh_i2c_wait_for_xfer_complete(adap) == IOH_I2C_FAIL)
+			break;
+
+		IOH_DEBUG("ioh_i2c_wait_for_xfer_complete return %d",
+			  IOH_I2C_SUCCESS);
+		retvalue = wrcount;
+	} while (0);
+
+	/* disable buffer mode interrupts */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFMSK,
+		       BUFFER_MODE_INTR_DISBL);
+	/* restore the I2CMOD register */
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CMOD, i2cmod_prev);
+
+	return retvalue;
+}
+
+/*! @ingroup	I2C_HALLayerAPI
+  @fn  		ioh_i2c_eeprom_sw_reset
+			(struct i2c_adapter * i2c_adap,struct i2c_msg *msgs)
+  @remarks 	Function for triggering EEPROM software reset.
+		The main tasks performed by this method are:
+		- Enable EEPROM software reset mode.
+		- Enable the required interrupts.
+		- Update timeout value in I2CTMR register.
+		- Invoke @ref ioh_i2c_eeprom_swrst_start to
+		  send software reset pattern.
+		- Disable interrupts.
+  @param  	i2c_adap [@ref IN] contains reference to the struct i2c_adapter
+  @param 	msgs	 [@ref IN] contains reference to i2c_msg structure
+  @retval 	s32
+		- @ref IOH_I2C_SUCCESS	Function returns successfully
+		- i@ref IOH_I2C_FAIL    @ref ioh_i2c_wait_for_bus_idle,
+					@ref ioh_i2c_wait_for_xfer_complete,
+		- -ERESTARTSYS
+		 @ref ioh_i2c_wait_for_xfer_complete was interrupted by a signal
+  @see      	ioh_i2c_xfer
+ <hr>
+ */
+s32 ioh_i2c_eeprom_sw_reset(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs)
+{
+
+	struct i2c_algo_ioh_data *adap = i2c_adap->algo_data;
+
+	u32 time_interval = i2c_adap->timeout;
+	u32 i2ctmr;
+	u32 i2cmod_prev;
+	u32 ioh_pattern;
+
+	s32 ret_val = IOH_I2C_FAIL;	/* init return value to error */
+
+	/* get the current value of I2C mod register */
+	i2cmod_prev = adap->readreg((adap->ioh_i2c_base_address), IOH_I2CMOD);
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CMOD, CLR_REG);
+	adap->set_reg_bit((adap->ioh_i2c_base_address), IOH_I2CMOD,
+			EEPROM_SW_RST_MODE);
+
+	IOH_DEBUG("ioh_i2c_eeprom_sw_reset : I2CMOD %x\n",
+		adap->readreg((adap->ioh_i2c_base_address), IOH_I2CMOD));
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CESRMSK,
+		EEPROM_RST_INTR_ENBL);
+
+	time_interval = (time_interval <= 10) ? (time_interval) : (10);
+
+	/* value of I2CT = (Timeout interval * PCLK frequency)/ 8 */
+	i2ctmr = (time_interval * (ioh_i2c_clk)) / 8;
+
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CTMR, i2ctmr);
+
+	/* get the EEPROM reset pattern */
+	ioh_pattern = (u32) (*(msgs->buf));
+
+	/* mode 1 & 2 are used for buffer mode selection */
+	ioh_pattern -= 2;
+
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CESRFOR,
+		ioh_pattern);
+
+	IOH_DEBUG("ioh_i2c_eeprom_sw_reset : I2CESRFOR %x\n",
+		adap->readreg((adap->ioh_i2c_base_address), IOH_I2CESRFOR));
+
+	if (ioh_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) ==
+		IOH_I2C_SUCCESS) {
+
+		ioh_i2c_eeprom_swrst_start(adap);
+		ret_val = ioh_i2c_wait_for_xfer_complete(adap);
+
+		IOH_DEBUG("ioh_i2c_wait_for_xfer_complete return =%d\n",
+			ret_val);
+		adap->writereg((adap->ioh_i2c_base_address), IOH_I2CMOD,
+			i2cmod_prev);
+		adap->writereg((adap->ioh_i2c_base_address), IOH_I2CESRMSK,
+			EEPROM_RST_INTR_DISBL);
+	}
+
+	IOH_DEBUG("ioh_i2c_eeprom_sw_reset return=%d\n", ret_val);
+
+	return ret_val;
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_cb(struct i2c_algo_ioh_data * adap)
+  @remarks   	Interrupt handler Call back function.
+		The main tasks performed by this method are:
+		- Get the current operation mode.
+		- For the current mode ,check if any of the required interrupt
+		  bits are set.
+		- Invoke wake_up_interruptible function to unblock the functions
+		  waiting for these events.
+  @param  	adap [@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval 	s32
+		- @ref IOH_I2C_EVENT_SET Valid I2C event recognized and flagged
+		- @ref IOH_I2C_EVENT_NONE No valid I2C event
+  @see		ioh_i2c_probe
+ <hr>
+ */
+s32 ioh_i2c_cb(struct i2c_algo_ioh_data *adap)
+{
+	u32 reg_val;
+	u32 i2c_mode;
+	u32 i2c_interrupt = false;
+
+	reg_val = adap->readreg((adap->ioh_i2c_base_address), IOH_I2CMOD);
+	/* get the current mode of operation */
+	i2c_mode = reg_val & (BUFFER_MODE | EEPROM_SR_MODE);
+
+	switch (i2c_mode) {
+
+	case NORMAL_MODE:
+		{
+			reg_val =
+			    adap->readreg((adap->ioh_i2c_base_address),
+					  IOH_I2CSR);
+			reg_val &= (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT);
+
+			if (reg_val != 0) {
+
+				if (I2CMAL_BIT & reg_val) {
+					adap->ioh_i2c_event_flag |=
+					    I2CMAL_EVENT;
+				}
+
+				if (I2CMCF_BIT & reg_val) {
+					adap->ioh_i2c_event_flag |=
+					    I2CMCF_EVENT;
+				}
+
+				/* clear the applicable bits */
+				adap->clr_reg_bit((adap->ioh_i2c_base_address),
+						  IOH_I2CSR, reg_val);
+
+				IOH_DEBUG("ioh_i2c_cb : IOH_I2CSR = %x\n",
+					  (adap->
+					   readreg(adap->ioh_i2c_base_address,
+						   IOH_I2CSR)));
+
+				i2c_interrupt = true;
+			}
+
+			break;
+		}
+
+	case BUFFER_MODE:
+		{
+			reg_val =
+			    adap->readreg((adap->ioh_i2c_base_address),
+					  IOH_I2CBUFSTA);
+			reg_val &= BUFFER_MODE_MASK;
+			if (reg_val != 0) {
+				/* there is a co-relation between the buffer
+				 * mode interrupt flags' bit */
+				/* positions and the flag positions in event
+				 * flag. for e.g. I2CBMFI is at position */
+				/* 0 in the I2CBUFSTA register. its position
+				 * in the event flag is 2, hence left shifting
+				 */
+				adap->ioh_i2c_event_flag |= ((reg_val) << 2);
+
+				/* clear the applicable bits */
+				adap->clr_reg_bit((adap->ioh_i2c_base_address),
+						  IOH_I2CBUFSTA, reg_val);
+
+				IOH_DEBUG("ioh_i2c_cb : IOH_I2CBUFSTA = %x\n",
+					  (adap->
+					   readreg(adap->ioh_i2c_base_address,
+						   IOH_I2CBUFSTA)));
+
+				i2c_interrupt = true;
+			}
+
+			break;
+
+		}
+
+	case EEPROM_SR_MODE:
+		{
+			reg_val =
+			    adap->readreg((adap->ioh_i2c_base_address),
+					  IOH_I2CESRSTA);
+			reg_val &= (I2CESRFI_BIT | I2CESRTO_BIT);
+			if (reg_val != 0) {
+
+				adap->ioh_i2c_event_flag |= ((reg_val) << 7);
+
+				/* clear the applicable bits */
+				adap->clr_reg_bit((adap->ioh_i2c_base_address),
+						  IOH_I2CESRSTA, reg_val);
+
+				IOH_DEBUG("ioh_i2c_cb : IOH_I2CESRSTA = %x\n",
+					  (adap->
+					   readreg(adap->ioh_i2c_base_address,
+						   IOH_I2CESRSTA)));
+
+				i2c_interrupt = true;
+			}
+
+			break;
+		}
+
+	default:
+		{
+			break;
+		}
+	}			/* end switch */
+
+	if (i2c_interrupt == true)
+		wake_up_interruptible(&ioh_i2c_event);
+
+	return ((i2c_interrupt ==
+		true) ? (IOH_I2C_EVENT_SET) : (IOH_I2C_EVENT_NONE));
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_start(struct i2c_algo_ioh_data * adap)
+  @remarks  	The main tasks performed by this method are:
+		- Generate I2C start condition in normal mode
+		  by setting I2CCTL.I2CMSTA to 1.
+  @param  	adap 	[@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval 	None
+  @see		- ioh_i2c_readbytes
+		- ioh_i2c_writebytes
+ <hr>
+ */
+static void ioh_i2c_start(struct i2c_algo_ioh_data *adap)
+{
+	IOH_DEBUG("In ioh_i2c_start : I2CCTL = %x\n",
+		(adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+	adap->set_reg_bit((adap->ioh_i2c_base_address), IOH_I2CCTL, IOH_START);
+	IOH_DEBUG(" Invoke ioh_i2c_start successfully \n");
+	IOH_DEBUG("In ioh_i2c_start : I2CCTL = %x\n",
+		(adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_buff_mode_start(struct i2c_algo_ioh_data * adap)
+  @remarks  	The main tasks performed by this method are:
+		- Generate I2C start condition in buffer mode
+		  by setting I2CBUFCTL.I2CBMSTA to 1.
+  @param  	adap [@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval 	None
+  @see	    	- ioh_i2c_buffer_read
+		- ioh_i2c_buffer_write
+ <hr>
+ */
+static void ioh_i2c_buff_mode_start(struct i2c_algo_ioh_data *adap)
+{
+	IOH_DEBUG("In ioh_i2c_buff_mode_start : I2CBUFCTL = %x\n",
+		(adap->readreg(adap->ioh_i2c_base_address, IOH_I2CBUFCTL)));
+	adap->set_reg_bit((adap->ioh_i2c_base_address), IOH_I2CBUFCTL,
+			IOH_BUFF_START);
+
+	IOH_DEBUG(" Invoke ioh_i2c_buff_mode_start successfully \n");
+	IOH_DEBUG("In ioh_i2c_buff_mode_start : I2CBUFCTL = %x\n",
+		(adap->readreg(adap->ioh_i2c_base_address, IOH_I2CBUFCTL)));
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_eeprom_swrst_start(struct i2c_algo_ioh_data * adap)
+  @remarks  	The main tasks performed by this method are:
+		- Generate I2C start condition in EEPROM sw reset mode
+		  by setting I2CESRCTL.I2CSTA to 1.
+  @param  	adap [@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval 	None
+  @see      	ioh_i2c_eeprom_sw_reset
+ <hr>
+ */
+static void ioh_i2c_eeprom_swrst_start(struct i2c_algo_ioh_data *adap)
+{
+	IOH_DEBUG("In ioh_i2c_eeprom_swrst_start : I2CESRCTL = %x\n",
+		(adap->readreg(adap->ioh_i2c_base_address, IOH_I2CESRCTL)));
+	adap->set_reg_bit((adap->ioh_i2c_base_address), IOH_I2CESRCTL,
+			IOH_ESR_START);
+
+	IOH_DEBUG(" Invoked ioh_i2c_eeprom_swrst_start successfully\n");
+	IOH_DEBUG("In ioh_i2c_eeprom_swrst_start : I2CESRCTL = %x\n",
+		(adap->readreg(adap->ioh_i2c_base_address, IOH_I2CESRCTL)));
+
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_stop(struct i2c_algo_ioh_data *adap)
+  @remarks  	Function to generate stop condition in normal mode.
+		The main tasks performed by this method are:
+		- Generate I2C stop condition by setting I2CCTL.I2CMSTA to 0.
+  @param  	adap [@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval 	None
+  @see		- ioh_i2c_readbytes
+		- ioh_i2c_writebytes
+ <hr>
+ */
+static void ioh_i2c_stop(struct i2c_algo_ioh_data *adap)
+{
+	IOH_DEBUG("In ioh_i2c_stop : I2CCTL = %x\n",
+		(adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+	/* clear the start bit */
+	adap->clr_reg_bit((adap->ioh_i2c_base_address), IOH_I2CCTL, IOH_START);
+	IOH_DEBUG(" Invoke ioh_i2c_stop successfully \n");
+	IOH_DEBUG("In ioh_i2c_stop : I2CCTL = %x\n",
+		(adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_repstart(struct i2c_algo_ioh_data *adap)
+  @remarks  	Function to generate repeated start condition in normal mode.
+		The main tasks performed by this method are:
+		- Generate repeated start condition by setting using
+		  I2CCTL.I2CRSTA to 1.
+  @param  	adap [@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval 	None
+  @see	    	- ioh_i2c_readbytes
+		- ioh_i2c_writebytes
+ <hr>
+ */
+static void ioh_i2c_repstart(struct i2c_algo_ioh_data *adap)
+{
+	IOH_DEBUG("In ioh_i2c_repstart : I2CCTL = %x\n",
+		(adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+	adap->set_reg_bit((adap->ioh_i2c_base_address), IOH_I2CCTL,
+			IOH_REPSTART);
+
+	IOH_DEBUG(" Invoke ioh_i2c_repstart successfully \n");
+	IOH_DEBUG("In ioh_i2c_repstart : I2CCTL = %x\n",
+		(adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_getack(struct i2c_algo_ioh_data *adap)
+  @remarks  	Function to confirm ACK/NACK.
+		The main tasks performed by this method are:
+		- Get the ACK status from I2CSR.
+		- Return success if ACK received or failure otherwise.
+  @param  	adap [@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval 	s32
+		- @ref IOH_I2C_SUCCESS Acknowledgement was received.
+		- @ref IOH_I2C_FAIL No acknowledgement received.
+  @see      	- ioh_i2c_readbytes
+		- ioh_i2c_writebytes
+ <hr>
+ */
+static s32 ioh_i2c_getack(struct i2c_algo_ioh_data *adap)
+{
+	u32 reg_val;
+	reg_val =
+		(adap->readreg((adap->ioh_i2c_base_address), IOH_I2CSR) &
+		IOH_GETACK);
+
+	if (reg_val == 0)
+		IOH_DEBUG("ioh_i2c_getack : return%d \n", IOH_I2C_SUCCESS);
+	else
+		IOH_DEBUG("ioh_i2c_getack : return%d \n", IOH_I2C_FAIL);
+
+	return (((reg_val) == 0) ? (IOH_I2C_SUCCESS) : (IOH_I2C_FAIL));
+
+}
+
+/*! @ingroup 	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_sendack(struct i2c_algo_ioh_data *adap)
+  @remarks  	Function to send ACK.
+		The main tasks performed by this method are:
+		- Clear the I2C TXAK bit in I2CCTL register .
+  @param  	adap [@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval 	None
+  @see		ioh_i2c_readbytes
+ <hr>
+ */
+static void ioh_i2c_sendack(struct i2c_algo_ioh_data *adap)
+{
+	IOH_DEBUG("In ioh_i2c_sendack : I2CCTL = %x\n",
+		  (adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+	adap->clr_reg_bit((adap->ioh_i2c_base_address), IOH_I2CCTL, IOH_ACK);
+
+	IOH_DEBUG("Invoke ioh_i2c_sendack successfully\n");
+	IOH_DEBUG("In ioh_i2c_sendack : I2CCTL = %x\n",
+		(adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_sendnack(struct i2c_algo_ioh_data *adap)
+  @remarks  	Function to send NACK.
+		The main tasks performed by this method are:
+		- Set the I2C TXAK bit in I2CCTL register .
+  @param  	adap [@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval 	None
+  @see      	ioh_i2c_readbytes
+ <hr>
+ */
+static void ioh_i2c_sendnack(struct i2c_algo_ioh_data *adap)
+{
+	IOH_DEBUG("In ioh_i2c_sendnack : I2CCTL = %x\n",
+		  (adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+	adap->set_reg_bit((adap->ioh_i2c_base_address), IOH_I2CCTL, IOH_ACK);
+	IOH_DEBUG("Invoke ioh_i2c_sendnack successfully\n");
+	IOH_DEBUG("In ioh_i2c_sendnack : I2CCTL = %x\n",
+		  (adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_wait_for_bus_idle
+			(struct i2c_algo_ioh_data *adap,s32 timeout)
+  @remarks 	Function to check the status of bus.
+		The main tasks performed by this method are:
+		- Get the status of Bus Busy.
+		- If bus is busy sleep for 1 msec and again check.
+		- Repeat until bus is free or timeout happens.
+  @param  	adap 	[@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @param  	timeout 	[@ref IN] waiting time counter (us)
+  @retval   	s32
+		- @ref IOH_I2C_SUCCESS	The function returns successfully.
+		- @ref IOH_I2C_FAIL	The bus is still idle.
+  @see		- ioh_i2c_readbytes
+		- ioh_i2c_writebytes
+		- ioh_i2c_buffer_read
+		- ioh_i2c_buffer_write
+		- ioh_i2c_eeprom_sw_reset
+ <hr>
+  */
+static s32 ioh_i2c_wait_for_bus_idle(struct i2c_algo_ioh_data *adap,
+				     s32 timeout)
+{
+	u32 reg_value;
+
+	/* get the status of bus busy */
+	reg_value =
+	    (adap->readreg((adap->ioh_i2c_base_address), IOH_I2CSR) &
+	     (I2CMBB_BIT));
+
+	while ((timeout != 0) && (reg_value != 0)) {
+		msleep(1);	/* wait for 100 ms */
+		reg_value =
+		    (adap->readreg((adap->ioh_i2c_base_address),
+				   IOH_I2CSR) & (I2CMBB_BIT));
+		timeout--;
+	}
+
+	IOH_DEBUG("In ioh_i2c_wait_for_bus_idle : I2CSR = %x\n",
+		  adap->readreg((adap->ioh_i2c_base_address), IOH_I2CSR));
+
+	if (timeout == 0) {
+		IOH_LOG(KERN_ERR, "ioh_i2c_wait_for_bus_idle :return%d\n",
+			IOH_I2C_FAIL);
+	} else {
+		IOH_DEBUG("ioh_i2c_wait_for_bus_idle : return %d\n",
+			  IOH_I2C_SUCCESS);
+	}
+
+	return ((timeout <= 0) ? (IOH_I2C_FAIL) : (IOH_I2C_SUCCESS));
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_wait_for_xfer_complete(struct i2c_algo_ioh_data * adap)
+  @remarks	This functions initiates a wait for the transfer complete event
+  @param  	adap 	[@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval 	s32
+		- @ref IOH_I2C_SUCCESS	Function returns successfully.
+		- @ref IOH_I2C_FAIL	Any error occurs.
+		- -ERESTARTSYS		wait_event_interruptible_timeout
+					API was interrupted
+  @see		- ioh_i2c_readbytes
+		- ioh_i2c_writebytes
+		- ioh_i2c_buffer_read
+		- ioh_i2c_buffer_write
+		- ioh_i2c_eeprom_sw_reset
+ <hr>
+*/
+static s32 ioh_i2c_wait_for_xfer_complete(struct i2c_algo_ioh_data *adap)
+{
+
+	u32 temp_flag;
+	s32 ret = IOH_I2C_FAIL;
+	ret =
+	    wait_event_interruptible_timeout(ioh_i2c_event,
+					     (adap->ioh_i2c_event_flag != 0),
+					     msecs_to_jiffies(50));
+
+	IOH_DEBUG
+	    ("adap->ioh_i2c_event_flag in ioh_i2c_wait_for_xfer_complete=%x",
+	     adap->ioh_i2c_event_flag);
+	temp_flag = adap->ioh_i2c_event_flag;
+	adap->ioh_i2c_event_flag = 0;
+
+	if (ret == 0) {
+		IOH_LOG(KERN_ERR, "ioh_i2c_wait_for_xfer_complete : Timeout\n");
+	} else if (ret < 0) {
+		IOH_LOG(KERN_ERR,
+			"ioh_i2c_wait_for_xfer_complete  failed : "
+			"Interrupted by other signal\n");
+		ret = -ERESTARTSYS;
+	} else if ((temp_flag & I2C_ERROR_MASK) == 0) {
+		ret = IOH_I2C_SUCCESS;
+	} else {
+		IOH_LOG(KERN_ERR,
+			"ioh_i2c_wait_for_xfer_complete failed : "
+			"Error in transfer\n");
+	}
+
+	IOH_DEBUG(KERN_ERR, "ioh_i2c_wait_for_xfer_complete returns %d\n", ret);
+
+	return ret;
+}
+
+/*! @ingroup 	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_writereg(u32 addr,u32 offset,u32 val)
+  @remarks  	Function for writing data to register.
+		The main tasks performed by this method are:
+		- Compute the target address by adding the offset to
+		  the base address.
+		- Write the specified value to the target address.
+  @param  	addr 	[@ref IN] Base address for the I2C channel
+  @param  	offset 	[@ref IN] offset for the register
+  @param  	val	 	[@ref IN] Value to be written
+  @retval 	None
+  @see  	ioh_i2c_probe
+ <hr>
+ */
+void ioh_i2c_writereg(u32 addr, u32 offset, u32 val)
+{
+	IOH_WRITE_LONG(val, (addr + offset));
+}
+
+/*! @ingroup 	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_readreg(u32 addr,u32 offset)
+  @remarks  	Function for reading data from register.
+		The main tasks performed by this method are:
+		- Compute the target address by adding the offset to
+		  the base address.
+		- Read the register value and return the same.
+  @param  	addr 	[@ref IN] Base address for the I2C channel
+  @param  	offset 	[@ref IN] offset for the register
+  @retval	u32
+		The content of the register that is read.
+  @see		ioh_i2c_probe
+ <hr>
+ */
+u32 ioh_i2c_readreg(u32 addr, u32 offset)
+{
+	u32 ret;
+	ret = IOH_READ_LONG(addr + offset);
+	return ret;
+}
+
+/*! @ingroup 	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_setbit(u32 addr,u32 offset,u32 bitmask)
+  @remarks  	Function to set particular bit in register.
+		The main tasks performed by this method are:
+		- Compute the target address by adding the offset
+		  to the base address.
+		- Read the register value at the target address.
+		- Perform logical OR with bitmask and write back
+		  to the target address.
+  @param  	addr 	[@ref IN] Base address for the I2C channel
+  @param  	offset 	[@ref IN] offset for the register
+  @param  	bitmask [@ref IN] bit position
+  @retval	None
+  @see      	ioh_i2c_probe
+ <hr>
+ */
+void ioh_i2c_setbit(u32 addr, u32 offset, u32 bitmask)
+{
+	IOH_WRITE_LONG(((IOH_READ_LONG(addr + offset)) | (bitmask)),
+			(addr + offset));
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_clrbit(u32 addr,u32 off,u32 bitmask)
+  @remarks   	Function to reset particular bit in register.
+		The main tasks performed by this method are:
+		- Compute the target address by adding the offset
+		  to the base address.
+		- Read the register value at the target address.
+		- Perform logical AND with bitmask and write back
+		  to the target address.
+  @param  	addr 	[@ref IN] Base address for the I2C channel
+  @param  	offset	[@ref IN] offset for the register
+  @param  	bitmask	[@ref IN] bit position
+  @retval	None
+  @see		ioh_i2c_probe
+ <hr>
+ */
+void ioh_i2c_clrbit(u32 addr, u32 offset, u32 bitmask)
+{
+	IOH_WRITE_LONG(((IOH_READ_LONG(addr + offset)) & (~(bitmask))),
+		       (addr + offset));
+}
+
+/*! @ingroup 	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_disbl_int(struct i2c_algo_ioh_data * adap)
+  @remarks 	Function to disable IOH I2C interrupts.
+		The main tasks performed by this method are:
+		- Disable the following interrupts:
+			MAL,MCF,I2CESRFI,I2CESRTO,I2CBMIS,I2CBMTO,I2CBMNA,
+			I2CBMAL and I2CBMFI.
+  @param  	adap  [@ref IN] Contains reference to struct i2c_algo_ioh_data
+  @retval	None
+  @see	    	- ioh_i2c_remove
+		- ioh_i2c_suspend
+ <hr>
+*/
+void ioh_i2c_disbl_int(struct i2c_algo_ioh_data *adap)
+{
+
+	adap->clr_reg_bit((adap->ioh_i2c_base_address), IOH_I2CCTL,
+			  NORMAL_INTR_ENBL);
+
+	IOH_DEBUG("ioh_i2c_disbl_int : I2CCTL = %x\n",
+		  (adap->readreg(adap->ioh_i2c_base_address, IOH_I2CCTL)));
+
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CESRMSK,
+		       EEPROM_RST_INTR_DISBL);
+
+	IOH_DEBUG("ioh_i2c_disbl_int : IOH_I2CESRMSK = %x\n",
+		  (adap->readreg(adap->ioh_i2c_base_address, IOH_I2CESRMSK)));
+
+	adap->writereg((adap->ioh_i2c_base_address), IOH_I2CBUFMSK,
+		       BUFFER_MODE_INTR_DISBL);
+
+	IOH_DEBUG("ioh_i2c_disbl_int : IOH_I2CBUFMSK = %x\n",
+		  (adap->readreg(adap->ioh_i2c_base_address, IOH_I2CBUFMSK)));
+
+}
diff -urN linux-2.6.33.1/drivers/i2c/busses/pch_i2c_hal.h topcliff-2.6.33.1/drivers/i2c/busses/pch_i2c_hal.h
--- linux-2.6.33.1/drivers/i2c/busses/pch_i2c_hal.h	1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/i2c/busses/pch_i2c_hal.h	2010-03-23 10:40:18.000000000 +0900
@@ -0,0 +1,337 @@
+#ifndef __IOH_I2C_HAL_H__
+#define __IOH_I2C_HAL_H__
+/*!
+* @file ioh_i2c_hal.h
+* @brief This file provides the function prototypes and macros to the I2C module.
+* @version 0.95
+* @section
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; version 2 of the License.
+*
+* This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+/*
+* History:
+* Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+* All rights reserved.
+*
+* created:
+*	WIPRO 02/20/2009
+* modified:
+*	WIPRO 05/21/2009
+*
+*/
+
+/*! @defgroup 	I2C*/
+
+/*! @defgroup	I2C_Global
+@ingroup	I2C
+@brief		This group describes the global entities within
+		the module.
+@remarks	This group includes all the global data structures
+		used within the modules. These are mainly used to
+		store the device related information which is used
+		through out the module.
+<hr>
+*/
+
+/*! @defgroup	I2C_PCILayer
+@ingroup	I2C
+@brief		This group describes the PCI layer interface
+		functionalities.
+@remarks	This group contains the functions and data structures
+		that are used to interface the module with PCI Layer
+		subsystem of the Kernel.
+<hr>
+*/
+
+/*! @defgroup	I2C_InterfaceLayer
+@ingroup	I2C
+@brief		This group describes the Driver interface functionalities.
+@remarks	This group contains the data structures and functions used
+		to interface the module driver with the kernel subsystem.
+<hr>
+*/
+
+/*! @defgroup	I2C_HALLayer
+@ingroup	I2C
+@brief		This group describes the hardware specific functionalities.
+@remarks	This group contains the functions and data structures used
+		by the module to communicate with the hardware. These
+		functions are device specific and designed according to the
+		device specifications.
+<hr>
+*/
+
+/*! @defgroup	I2C_Utilities
+@ingroup	I2C
+@brief		This group describes the utility functionalities.
+@remarks	This group contains the functions and data structures used
+		to assist the other functionalities in their operations.
+<hr>
+*/
+
+/*! @defgroup	I2C_PCILayerAPI
+@ingroup	I2C_PCILayer
+@brief		This group contains the API(functions) used as the PCI
+		interface between the Kernel subsystem and the module.
+<hr>
+*/
+
+/*! @defgroup	I2C_PCILayerFacilitators
+@ingroup	I2C_PCILayer
+@brief		This group contains the data structures used by the PCI
+		Layer APIs for their functionalities.
+<hr>
+*/
+
+/*! @defgroup	I2C_InterfaceLayerAPI
+@ingroup	I2C_InterfaceLayer
+@brief		This group contains the API(functions) used as the Driver
+		interface between the Kernel subsystem and the module.
+<hr>
+*/
+
+/*! @defgroup	I2C_InterfaceLayerFacilitators
+@ingroup	I2C_InterfaceLayer
+@brief		This group contains the data structures used by the Driver
+		interface APIs for their functionalities.
+<hr>
+*/
+
+/*! @defgroup	I2C_HALLayerAPI
+@ingroup	I2C_HALLayer
+@brief		This group contains the APIs(functions) used to interact with
+		the hardware. These APIs act as an interface between the
+		hardware and the other driver functions.
+<hr>
+*/
+
+/*! @defgroup	I2C_UtilitiesAPI
+@ingroup	I2C_Utilities
+@brief		This group contains the APIs(functions) used by other functions.
+<hr>
+*/
+
+/*includes*/
+#include <linux/irqreturn.h>
+
+/*! @ingroup I2C_Global
+@def 	IOH_I2C_SUCCESS
+@brief 	Success status code
+*/
+#define IOH_I2C_SUCCESS		(0)
+
+/*! @ingroup I2C_Global
+@def 	IOH_I2C_FAIL
+@brief 	Error status code
+*/
+#define IOH_I2C_FAIL		(-1)
+
+/*! @ingroup I2C_Global
+@def 	IOH_I2C_MAX_CHN
+@brief 	Maximum I2C channels available
+*/
+#define IOH_I2C_MAX_CHN 	(1)
+
+/*! @ingroup I2C_Global
+@def 	IOH_I2C_EVENT_SET
+@brief 	I2C Interrupt Event Set Status
+*/
+#define IOH_I2C_EVENT_SET 	(0)
+
+/*! @ingroup I2C_Global
+@def 	IOH_I2C_EVENT_NONE
+@brief 	I2C Interrupt Event Clear Status
+*/
+#define IOH_I2C_EVENT_NONE (1)
+
+/*! @ingroup I2C_Global
+@def 	IOH_I2C_MAX_CLK
+@brief 	Maximum peripheral Clock speed supported in MHz
+*/
+#define IOH_I2C_MAX_CLK	(100000)
+
+
+/* flag for Buffer mode enable */
+#define IOH_BUFFER_MODE_ENABLE		(0x0002)
+
+/* flag for EEPROM SW RST enable */
+#define IOH_EEPROM_SW_RST_MODE_ENABLE	(0x0008)
+
+/* for mode selection */
+#define I2C_MODE_SEL 	(0x711)
+
+/*structures*/
+/*! @ingroup	I2C_HALLayer
+@struct 	i2c_algo_ioh_data
+@brief 		This structure contains references to methods implementing
+		I2C driver functionalities.
+@note 		The concerned details should be provided during
+		the data transfer.
+@see  		- ioh_i2c_init
+		- ioh_i2c_entcb
+		- ioh_i2c_cb
+		- ioh_i2c_disbl_int
+*/
+
+struct i2c_algo_ioh_data {
+
+	struct adapter_info *p_adapter_info;
+	/**< stores the reference to adapter_info structure*/
+
+	struct i2c_adapter ioh_i2c_adapter;
+	/**< stores the reference to i2c_adapter structure*/
+
+	u32 ioh_i2c_base_address; /**< specifies the remapped base address*/
+	int ioh_i2c_buff_mode_en; /**< specifies if buffer mode is enabled*/
+	u32 ioh_i2c_event_flag; /**< specifies occurrence of interrupt events*/
+
+	bool ioh_i2c_xfer_in_progress;
+	/**< specifies whether the transfer is completed */
+
+	void (*writereg) (u32 addr, u32 off, u32 val);
+	/**< stores the reference to register write function*/
+
+	u32(*readreg) (u32 addr, u32 off);
+	/**< stores the reference to register read function*/
+
+	void (*set_reg_bit) (u32 addr, u32 off, u32 bitmsk);
+	/**< stores the reference to register bit setting function*/
+
+	void (*clr_reg_bit) (u32 addr, u32 off, u32 bitmsk);
+	/**< stores the reference to register bit clearing function*/
+};
+
+/*! @ingroup	I2C_HALLayer
+@struct 	adapter_info
+@brief 		This structure holds the adapter information
+		for the IOH i2c controller.
+@note 		This structure contains instances of struct i2c_algo_ioh_data
+		for the available I2C channels and also a variable for saving
+		the suspend status.
+@see  		- ioh_i2c_probe
+		- ioh_i2c_remove
+		- ioh_i2c_suspend
+		- ioh_i2c_resume
+*/
+
+struct adapter_info {
+
+	struct i2c_algo_ioh_data ioh_i2c_data[IOH_I2C_MAX_CHN];
+	/**< stores a list of i2c_algo_ioh_data;
+	 there will be as many elements as maximum I2C channels*/
+
+	bool ioh_i2c_suspended;
+	/**< specifies whether the system is suspended or not*/
+};
+
+/**global variables*/
+extern int ioh_i2c_speed;
+extern int ioh_i2c_clk;
+extern s32(*ioh_i2c_cbr) (struct i2c_algo_ioh_data *);
+
+extern struct i2c_algorithm ioh_i2c_algorithm;
+
+/* Function prototypes */
+/*! @ingroup I2C_HALLayerAPI
+@fn 		s32 ioh_i2c_init(struct i2c_algo_ioh_data *adap)
+@brief  	Function to initialize IOH I2C hardware
+*/
+s32 ioh_i2c_init(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup I2C_HALLayerAPI
+@fn 		s32 ioh_i2c_writebytes(struct i2c_adapter *i2c_adap ,
+		struct i2c_msg *msgs,u32 last, u32 first)
+@brief  	Function for data write in normal mode
+*/
+s32 ioh_i2c_writebytes(struct i2c_adapter *i2c_adap,
+		       struct i2c_msg *msgs, u32 last, u32 first);
+
+/*! @ingroup I2C_HALLayerAPI
+@fn 		s32 ioh_i2c_readbytes(struct i2c_adapter *i2c_adap ,
+		struct i2c_msg *msgs,u32 last, u32 first)
+@brief  	Function for data read in normal mode
+*/
+s32 ioh_i2c_readbytes(struct i2c_adapter *i2c_adap,
+		      struct i2c_msg *msgs, u32 last, u32 first);
+
+/*! @ingroup I2C_HALLayerAPI
+@fn 		s32 ioh_i2c_eeprom_sw_reset(struct i2c_adapter * i2c_adap,
+		struct i2c_msg *msgs)
+@brief  	Function for triggering EEPROM software reset mode
+*/
+s32 ioh_i2c_eeprom_sw_reset(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs);
+
+/*! @ingroup I2C_HALLayerAPI
+@fn 		s32 ioh_i2c_buffer_write
+		(struct i2c_adapter * i2c_adap,struct i2c_msg *msgs)
+@brief  	Function for data write in buffer mode
+*/
+s32 ioh_i2c_buffer_write(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs);
+
+/*! @ingroup I2C_HALLayerAPI
+@fn 		s32 ioh_i2c_buffer_read
+		(struct i2c_adapter * i2c_adap,struct i2c_msg *msgs)
+@brief  	Function for data read in buffer mode
+*/
+s32 ioh_i2c_buffer_read(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs);
+
+/*! @ingroup I2C_HALLayerAPI
+@fn 		irqreturn_t ioh_i2c_handler(int irq,void *pData)
+@brief  	Interrupt handler
+*/
+irqreturn_t ioh_i2c_handler(int irq, void *pData);
+
+/*! @ingroup I2C_HALLayerAPI
+@fn 		void ioh_i2c_entcb
+		(s32(*ioh_i2c_ptr)(struct i2c_algo_ioh_data *adap))
+@brief  	Function for registering the interrupt handler call back
+*/
+void ioh_i2c_entcb(s32(*ioh_i2c_ptr) (struct i2c_algo_ioh_data *adap));
+
+/*! @ingroup I2C_UtilitiesAPI
+@fn 		s32 ioh_i2c_cb(struct i2c_algo_ioh_data * adap)
+@brief  	Call back function invoked from interrupt handler
+*/
+s32 ioh_i2c_cb(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup I2C_UtilitiesAPI
+@fn 		void ioh_i2c_disbl_int(struct i2c_algo_ioh_data *adap)
+@brief  	Function for disabling the interrupt
+*/
+void ioh_i2c_disbl_int(struct i2c_algo_ioh_data *adap);
+
+/*! @ingroup I2C_UtilitiesAPI
+@fn 		void ioh_i2c_writereg(u32 addr,u32 off,u32 val)
+@brief  	Function for writing data to register
+*/
+void ioh_i2c_writereg(u32 addr, u32 off, u32 val);
+
+/*! @ingroup I2C_UtilitiesAPI
+@fn 		u32 ioh_i2c_readreg(u32 addr,u32 off)
+@brief  	Function for reading data from register
+*/
+u32 ioh_i2c_readreg(u32 addr, u32 off);
+
+/*! @ingroup I2C_UtilitiesAPI
+@fn 		void ioh_i2c_setbit(u32 addr,u32 off,u32 bitmsk)
+@brief  	Function to set a particular bit in a register
+*/
+void ioh_i2c_setbit(u32 addr, u32 off, u32 bitmsk);
+
+/*! @ingroup I2C_UtilitiesAPI
+@fn 		void ioh_i2c_clrbit(u32 addr,u32 off,u32 bitmsk)
+@brief  	Function to clear a particular bit in a register
+*/
+void ioh_i2c_clrbit(u32 addr, u32 off, u32 bitmsk);
+#endif
diff -urN linux-2.6.33.1/drivers/i2c/busses/pch_i2c_main.c topcliff-2.6.33.1/drivers/i2c/busses/pch_i2c_main.c
--- linux-2.6.33.1/drivers/i2c/busses/pch_i2c_main.c	1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/i2c/busses/pch_i2c_main.c	2010-03-23 10:40:18.000000000 +0900
@@ -0,0 +1,247 @@
+/*!
+ * @file	ioh_i2c_main.c
+ * @brief 	This file contains the definitions
+ * 		of Interface Layer APIs for IOH I2C driver.
+ * @version 0.95
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+ * All rights reserved.
+ *
+ * created:
+ *	WIPRO 02/20/2009
+ * modified:
+ *	WIPRO 05/21/2009
+ *
+ */
+
+/*includes*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/stat.h>
+#include <linux/interrupt.h>
+
+#include "pch_i2c_hal.h"
+#include "pch_common.h"
+#include "pch_debug.h"
+
+/* Function prototypes */
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn 		ioh_i2c_func(struct i2c_adapter *adap)
+  @brief  	This function returns the functionalities supported
+		by I2C driver.
+  */
+static u32 ioh_i2c_func(struct i2c_adapter *adap);
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn 		ioh_i2c_xfer(struct i2c_adapter *i2c_adap,
+				struct i2c_msg *msgs,s32 num)
+  @brief  	This function handles data transfer through I2C bus
+  */
+static s32 ioh_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
+			s32 num);
+
+/*structures*/
+
+/*! @ingroup	I2C_Global
+  @struct 	ioh_i2c_algorithm
+  @brief 	This an instance of the kernel structure i2c_algorithm structure
+		and it stores the properties of the IOH I2C algorithm driver.
+  @note 	This structure stores the references of the @ref ioh_i2c_xfer
+		and @ref ioh_i2c_func functions.
+  @see 		ioh_i2c_probe
+  */
+
+struct i2c_algorithm ioh_i2c_algorithm = {
+	.master_xfer = ioh_i2c_xfer,
+	.functionality = ioh_i2c_func
+};
+
+/*! @ingroup 	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_func(struct i2c_adapter *adap)
+  @brief 	Function return the functionality of the I2C driver
+  @remarks 	Returns (I2C_FUNC_I2C) | (I2C_FUNC_SMBUS_EMUL) |
+			(I2C_FUNC_10BIT_ADDR)
+  @param  	adap 	[@ref IN] Contains reference to i2c_adapter structure
+  @retval 	u32
+		- Bitwise OR of the feature status codes supported
+		  by this algorithm driver.
+  @see       	ioh_i2c_algorithm
+  */
+static u32 ioh_i2c_func(struct i2c_adapter *adap)
+{
+	u32 ret;
+	ret = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
+	return ret;
+}
+
+/*! @ingroup	I2C_UtilitiesAPI
+  @fn  		ioh_i2c_xfer(struct i2c_adapter *i2c_adap,
+		struct i2c_msg *msgs,s32 num)
+  @brief  	Function to transfer data through I2C bus
+  @remarks  	Function to transfer data through I2C bus
+		The main tasks performed by this method are:
+		- Check if system is suspended.
+		- If EEPROM software reset command is received,
+		  then invoke function ioh_i2c_eeprom_sw_reset.
+		- If Buffer mode selection command is received,
+		  check the value of msgs[0]->buf[0]. If set,
+		  enable buffer mode, by setting the variable
+		  adap->ioh_i2c_buff_mode_en. Otherwise reset the flag.
+		- If no special command, perform the requested
+		  data transfer operation.
+  @note     	The master transfer function ioh_i2c_xfer
+		is invoked by the Linux I2C core, whenever
+		communication/data transfer with the IOH I2C
+		driver is necessary. The Linux I2C core
+		ensures that the function is called with
+		valid parameters only.
+  @param  	i2c_adap [@ref IN] contains reference to the struct i2c_adapter
+  @param 	msgs	 [@ref IN] contains reference to i2c_msg structure
+  @param 	num	 [@ref IN] number of messages
+  @retval 	s32
+		- @ref IOH_I2C_SUCCESS
+			Function returns successfully for EEPROM sw reset mode,
+			buffer mode selection commands.
+		- The number of bytes transferred for successful operation
+		  of read/write calls.
+		- @ref IOH_I2C_FAIL
+			Any error occurs during the execution of the function.
+  @see		ioh_i2c_algorithm
+  <hr>
+  */
+
+static s32 ioh_i2c_xfer(struct i2c_adapter *i2c_adap,
+			struct i2c_msg *msgs, s32 num)
+{
+
+	struct i2c_msg *pmsg;
+	u32 i = 0;
+	u32 status;
+	u32 msglen;
+	u32 subaddrlen;
+	s32 ret = IOH_I2C_FAIL;
+
+	struct i2c_algo_ioh_data *adap = i2c_adap->algo_data;
+
+	if (adap->p_adapter_info->ioh_i2c_suspended == false) {
+		IOH_DEBUG("ioh_i2c_xfer "
+			"adap->p_adapter_info->ioh_i2c_suspended is %d\n",
+			adap->p_adapter_info->ioh_i2c_suspended);
+		/* transfer not completed */
+		adap->ioh_i2c_xfer_in_progress = true;
+		IOH_DEBUG("	adap->ioh_i2c_xfer_in_progress is %d\n",
+				adap->ioh_i2c_xfer_in_progress);
+		pmsg = &msgs[0];
+		status = pmsg->flags;
+		/* special commands for IOH I2C driver */
+		if ((status &
+		    (IOH_EEPROM_SW_RST_MODE_ENABLE | IOH_BUFFER_MODE_ENABLE))
+		     != false) {
+			if ((status & IOH_EEPROM_SW_RST_MODE_ENABLE) != false) {
+				/* check whether EEPROM sw reset is enabled */
+				IOH_DEBUG("ioh_i2c_xfer invoking "
+					  "ioh_i2c_eeprom_sw_reset\n");
+				IOH_DEBUG("After invoking "
+					  "I2C_MODE_SEL :flag= 0x%x\n", status);
+				ret = ioh_i2c_eeprom_sw_reset(i2c_adap, pmsg);
+			} else {
+				adap->ioh_i2c_buff_mode_en =
+				    (pmsg->buf[0] == 1) ?
+				    (IOH_BUFFER_MODE_ENABLE) : (pmsg->buf[0]);
+				ret = IOH_I2C_SUCCESS;
+			}
+			/* transfer completed */
+			adap->ioh_i2c_xfer_in_progress = false;
+			IOH_DEBUG("adap->ioh_i2c_xfer_in_progress is %d\n",
+				  adap->ioh_i2c_xfer_in_progress);
+			IOH_DEBUG(KERN_INFO,
+				  "After mode selection "
+				  "ioh_i2c_xfer return = %d\n", ret);
+			return ret;
+		}
+		for (i = 0; i < num; i++) {
+			pmsg = &msgs[i];
+			pmsg->flags |= adap->ioh_i2c_buff_mode_en;
+			status = pmsg->flags;
+			IOH_DEBUG("After invoking I2C_MODE_SEL :flag= 0x%x\n",
+				  status);
+			/* calculate sub address length and message length */
+			/* these are applicable only for buffer mode */
+			subaddrlen = pmsg->buf[0];
+			/* calculate actual message length excluding
+			 * the sub address fields */
+			msglen = (pmsg->len) - (subaddrlen + 1);
+
+			if (((status & IOH_BUFFER_MODE_ENABLE) != false)
+			    && (msglen != 0)) {
+				/* Buffer mode cannot be used for transferring
+				 * 0 byte data. Hence when buffer mode is
+				 * enabled and 0 byte transfer is requested,
+				 * normal mode transfer will be used */
+				if ((status & (I2C_M_RD)) != false) {
+					IOH_DEBUG(KERN_INFO,
+						  "ioh_i2c_xfer invoking "
+						  "ioh_i2c_buffer_read\n");
+					ret =
+					    ioh_i2c_buffer_read(i2c_adap, pmsg);
+				} else {
+					IOH_DEBUG(KERN_INFO,
+						  "ioh_i2c_xfer invoking "
+						  "ioh_i2c_buffer_write\n");
+					ret =
+					   ioh_i2c_buffer_write(i2c_adap, pmsg);
+				}
+			} else {
+				if ((status & (I2C_M_RD)) != false) {
+					IOH_DEBUG(KERN_INFO,
+						  "ioh_i2c_xfer invoking "
+						  "ioh_i2c_readbytes\n");
+					ret =
+					    ioh_i2c_readbytes(i2c_adap, pmsg,
+							      (i + 1 == num),
+							      (i == 0));
+				} else {
+					IOH_DEBUG(KERN_INFO,
+						  "ioh_i2c_xfer invoking "
+						  "ioh_i2c_writebytes\n");
+					ret =
+					    ioh_i2c_writebytes(i2c_adap, pmsg,
+							       (i + 1 == num),
+							       (i == 0));
+				}
+			}
+
+		}
+
+		adap->ioh_i2c_xfer_in_progress = false;	/* transfer completed */
+
+		IOH_DEBUG("	adap->ioh_i2c_xfer_in_progress is %d\n",
+			  adap->ioh_i2c_xfer_in_progress);
+	}
+	IOH_DEBUG(KERN_INFO, "ioh_i2c_xfer return:%d\n\n\n\n", ret);
+
+	return ret;
+}
diff -urN linux-2.6.33.1/drivers/i2c/busses/pch_i2c_pci.c topcliff-2.6.33.1/drivers/i2c/busses/pch_i2c_pci.c
--- linux-2.6.33.1/drivers/i2c/busses/pch_i2c_pci.c	1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/i2c/busses/pch_i2c_pci.c	2010-03-23 10:40:18.000000000 +0900
@@ -0,0 +1,583 @@
+/*!
+* @file		ioh_i2c_pci.c
+* @brief 	This file contains the definitions of I2C_PCILayer APIs.
+* @version 0.95
+* @section
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; version 2 of the License.
+*
+* This program is distributed in the hope that 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+/*
+* History:
+* Copyright (C) 2008 OKI SEMICONDUCTOR Co., LTD.
+* All rights reserved.
+*
+* created:
+*	WIPRO 02/20/2009
+* modified:
+*	WIPRO 05/21/2009
+*
+*/
+
+/*includes*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/stat.h>
+#include <linux/interrupt.h>
+
+#include "pch_i2c_hal.h"
+#include "pch_common.h"
+#include "pch_debug.h"
+
+/**
+ *macro definition
+ */
+
+/*! @ingroup 	I2C_PCILayer
+@def 		PCI_DEVICE_ID_IOH_I2C
+@brief 		Device ID of the device supported by IOH I2C
+		driver in GE configuration.
+*/
+#define PCI_DEVICE_ID_IOH_I2C	(0x8817)
+
+/*
+ * variable declaration
+ */
+/*! @ingroup 	I2C_Global
+@var		ioh_i2c_speed
+@brief		specifies I2C bus speed in Kbps
+@note		This parameter is provided as module parameter
+		while loading the driver. If no value is provided,
+		by default the speed is set to 100 kbps.
+@see		ioh_i2c_init
+<hr>
+*/
+int ioh_i2c_speed = 100;
+
+/*! @ingroup 	I2C_Global
+@var		ioh_i2c_clock
+@brief		specifies I2C clock speed in KHz
+@note		This parameter is provided as module parameter
+		while inserting the driver. If no value is provided,
+		by default the speed is set to 62500KHz.
+@see		ioh_i2c_init
+<hr>
+*/
+/* int ioh_i2c_clk = 62500; */
+int ioh_i2c_clk = 50000;
+
+/*! @ingroup 	I2C_Global
+@var 		ioh_i2c_cbr
+@brief  	I2C_Global function pointer to save reference to
+		callback function
+@see		ioh_i2c_entcb
+<hr>
+*/
+s32(*ioh_i2c_cbr) (struct i2c_algo_ioh_data *);
+
+/*! @ingroup 	I2C_Global
+@var		MODULE_NAME
+@brief		I2C_Global variable storing the name of this driver
+@see 		ioh_i2c_probe
+<hr>
+*/
+#define MODULE_NAME "pch_i2c"	/* name for the driver */
+
+/* Function prototypes */
+/*! @ingroup 	I2C_PCILayerAPI
+@fn 		ioh_i2c_probe(struct pci_dev *pdev,
+				const struct pci_device_id *id)
+@brief  	This function implements the probe routine
+		for IOH I2C driver module
+*/
+static int __devinit ioh_i2c_probe(struct pci_dev *pdev,
+				   const struct pci_device_id *id);
+
+/*! @ingroup 	I2C_PCILayerAPI
+@fn 		ioh_i2c_remove(struct pci_dev *pdev)
+@brief  	This function implements the remove routine
+		for IOH I2C driver module.
+*/
+static void __devexit ioh_i2c_remove(struct pci_dev *pdev);
+
+/*! @ingroup 	I2C_PCILayerAPI
+@fn 		ioh_i2c_suspend(struct pci_dev* pdev,pm_message_t state)
+@brief      	This function implements the suspend routine
+		for IOH I2C driver module
+*/
+static int ioh_i2c_suspend(struct pci_dev *pdev, pm_message_t state);
+
+/*! @ingroup 	I2C_PCILayerAPI
+@fn 		ioh_i2c_resume(struct pci_dev* pdev)
+@brief  	This function implements the resume routine
+		for IOH I2C driver module
+*/
+static int ioh_i2c_resume(struct pci_dev *pdev);
+
+/*structures*/
+/*! @ingroup	I2C_PCILayerFacilitators
+@struct 	ioh_i2c_pcidev_id
+@brief 		Store information of supported PCI devices
+@note 		This is an instance of pci_device_id structure and
+		holds information of the PCI devices that are supported
+		by this driver
+@see		ioh_i2c_pcidriver
+*/
+
+static struct pci_device_id __devinitdata ioh_i2c_pcidev_id[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_IOH_I2C)},
+	{0,}
+};
+
+/*! @ingroup	I2C_PCILayerFacilitators
+@struct 	ioh_i2c_pcidriver
+@brief 		Store the references of PCI driver interfaces to kernel
+@note 		This is an instance of pci_driver and this structure specifies
+		the driver details to be registered with the kernel
+@see		- ioh_i2c_pci_init
+		- ioh_i2c_pci_exit
+<hr>
+*/
+
+static struct pci_driver ioh_i2c_pcidriver = {
+	.name = "ioh_i2c",
+	.id_table = ioh_i2c_pcidev_id,
+	.probe = ioh_i2c_probe,
+	.remove = __devexit_p(ioh_i2c_remove),
+#ifdef CONFIG_PM
+	.suspend = ioh_i2c_suspend,
+	.resume = ioh_i2c_resume
+#endif
+};
+
+/*! @ingroup 	I2C_PCILayerAPI
+  @fn  		ioh_i2c_probe(struct pci_dev *pdev, const struct
+				pci_device_id *id)
+  @remarks  	The main tasks performed by this method are:
+		- Allocate memory for driver private data.
+		- Enable the PCI device.
+		- Reserve the PCI regions.
+		- Map the device address of the IO BAR.
+		- Register the interrupt handler.
+		- Initialize the members in adap_info->ioh_i2c_data.
+		- Register the ioh_i2c_adapter.
+		- Initialize the IOH I2C hardware.
+  @note		This function is invoked by the PCI core when a device is
+		found for this driver to control
+  @param  	pdev 	[@ref IN] contains reference to
+			PCI device descriptor for the peripheral
+  @param 	id	[@ref IN] contains reference to
+			the pci_device_id table of matching peripheral
+  @retval 	int
+		- @ref IOH_I2C_SUCCESS	Function returns successfully.
+		- -EIO 	  pci_enable_device fails
+		- -EINVAL pci_enable_device/request_irq fails
+		- -EBUSY  pci_request_regions/request_irq fails
+		- -ENOMEM i2c_add_adapter/request_irq/pci_iomap/kzalloc fails
+		- -EAGAIN i2c_add_adapter fails
+		- -ENOSYS request_irq fails
+ @see		ioh_i2c_pcidriver
+ <hr>
+ */
+static int __devinit ioh_i2c_probe(struct pci_dev *pdev,
+				const struct pci_device_id *id)
+{
+
+	int i;
+	u32 base_addr;
+	s32 ret = IOH_I2C_SUCCESS;
+
+	IOH_DEBUG("Enterred in i2c_probe\n");
+
+	do {
+		struct adapter_info *adap_info =
+		    kzalloc((sizeof(struct adapter_info)), GFP_KERNEL);
+		if (adap_info == NULL) {
+			IOH_LOG(KERN_ERR, "Memory allocation failed FAILED");
+			ret = -ENOMEM;
+			break;
+		}
+
+		IOH_DEBUG
+		    ("Function kzalloc invoked successfully "
+		    "and adap_info valu = %p\n",
+		     adap_info);
+
+		ret = pci_enable_device(pdev);
+
+		if (ret) {
+			IOH_LOG(KERN_ERR, "pci_enable_device FAILED");
+			kfree(adap_info);
+			break;
+		}
+
+		IOH_DEBUG("pci_enable_device returns %d\n", ret);
+
+		ret = pci_request_regions(pdev, MODULE_NAME);
+		if (ret) {
+			IOH_LOG(KERN_ERR, "pci_request_regions FAILED");
+			pci_disable_device(pdev);
+			kfree(adap_info);
+			break;
+		}
+
+		IOH_DEBUG("pci_request_regions returns %d\n", ret);
+
+		/* Wipro 1/13/2010 Use Mem BAR */
+		base_addr = (unsigned long)pci_iomap(pdev, 1, 0);
+
+		if (base_addr == 0) {
+			IOH_LOG(KERN_ERR, "pci_iomap FAILED");
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			kfree(adap_info);
+			ret = -ENOMEM;
+			break;
+		}
+
+		IOH_DEBUG("pci_iomap invoked successfully\n");
+
+		ioh_i2c_entcb(ioh_i2c_cb);
+		IOH_DEBUG("ioh_i2c_entcb invoked successfully\n");
+
+		for (i = 0; i < IOH_I2C_MAX_CHN; i++) {
+			adap_info->ioh_i2c_data[i].p_adapter_info = adap_info;
+			adap_info->ioh_i2c_data[i].writereg = ioh_i2c_writereg;
+			adap_info->ioh_i2c_data[i].readreg = ioh_i2c_readreg;
+			adap_info->ioh_i2c_data[i].set_reg_bit = ioh_i2c_setbit;
+			adap_info->ioh_i2c_data[i].clr_reg_bit = ioh_i2c_clrbit;
+
+			adap_info->ioh_i2c_data[i].ioh_i2c_adapter.owner =
+			    THIS_MODULE;
+			adap_info->ioh_i2c_data[i].ioh_i2c_adapter.class =
+			    I2C_CLASS_HWMON;
+			strcpy(adap_info->ioh_i2c_data[i].ioh_i2c_adapter.name,
+			       "ioh_i2c");
+			adap_info->ioh_i2c_data[i].ioh_i2c_adapter.algo =
+			    &ioh_i2c_algorithm;
+			adap_info->ioh_i2c_data[i].ioh_i2c_adapter.algo_data =
+			    &adap_info->ioh_i2c_data[i];
+
+			/* (i * 0x80) + base_addr; */
+			adap_info->ioh_i2c_data[i].ioh_i2c_base_address =
+			    base_addr;
+
+			adap_info->ioh_i2c_data[i].ioh_i2c_adapter.dev.parent =
+			    &pdev->dev;
+
+			ret =
+			    i2c_add_adapter(&
+					    (adap_info->ioh_i2c_data[i].
+					     ioh_i2c_adapter));
+
+			if (ret) {
+				IOH_LOG(KERN_ERR, "i2c_add_adapter FAILED");
+
+				pci_iounmap(pdev, (void *)base_addr);
+				pci_release_regions(pdev);
+				pci_disable_device(pdev);
+				kfree(adap_info);
+				break;
+			}
+
+			IOH_DEBUG("i2c_add_adapter returns %d for channel-%d\n",
+				  ret, i);
+			(void)ioh_i2c_init(&adap_info->ioh_i2c_data[i]);
+			IOH_DEBUG("ioh_i2c_init invoked successfully \n");
+
+		}
+
+		if (ret)
+			break;
+
+		ret = request_irq(pdev->irq, &ioh_i2c_handler, IRQF_SHARED,
+				  MODULE_NAME, (void *)adap_info);
+
+		if (ret) {
+			IOH_DEBUG("request_irq Failed\n");
+
+			for (i = 0; i < IOH_I2C_MAX_CHN; i++) {
+				i2c_del_adapter(&
+						(adap_info->
+						 ioh_i2c_data
+						 [i].ioh_i2c_adapter));
+			}
+
+			pci_iounmap(pdev, (void *)base_addr);
+
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			kfree(adap_info);
+			break;
+		}
+
+		IOH_DEBUG("request_irq returns %d\n", ret);
+
+		IOH_DEBUG("ioh_i2c_probe returns %d\n", IOH_I2C_SUCCESS);
+		pci_set_drvdata(pdev, (void *)adap_info);
+		return IOH_I2C_SUCCESS;
+	} while (0);
+
+	return ret;
+}
+
+/*! @ingroup	I2C_PCILayerAPI
+  @fn  		ioh_i2c_remove(struct pci_dev *pdev)
+  @remarks  	The main tasks performed by this method are:
+		- Disable interrupts.
+		- Unregister interrupt handler.
+		- Unregister i2c_adapter.
+		- Release IO memory.
+		- Release PCI regions.
+		- Disable PCI device.
+  @note		This function is invoked when the IOH I2C driver module is
+		unloaded from the system using rmmod command or when the
+		IOH I2C device is removed from the system.
+  @param  	pdev 	[@ref INOUT] contains reference to
+			PCI device descriptor for the peripheral
+  @retval 	None
+  @see		ioh_i2c_pcidriver
+  <hr>
+  */
+
+static void __devexit ioh_i2c_remove(struct pci_dev *pdev)
+{
+	int i;
+
+	struct adapter_info *adap_info = pci_get_drvdata(pdev);
+
+	IOH_DEBUG(" invoked function pci_get_drvdata successfully\n");
+
+	for (i = 0; i < IOH_I2C_MAX_CHN; i++) {
+		ioh_i2c_disbl_int(&adap_info->ioh_i2c_data[i]);
+
+		if (i == (IOH_I2C_MAX_CHN - 1)) {
+			free_irq(pdev->irq, (void *)adap_info);
+			IOH_DEBUG("  free_irq invoked successfully\n");
+		}
+
+		i2c_del_adapter(&(adap_info->ioh_i2c_data[i].ioh_i2c_adapter));
+
+		IOH_DEBUG(" invoked i2c_del_adapter successfully\n");
+
+	}
+
+	if (adap_info->ioh_i2c_data[0].ioh_i2c_base_address) {
+		pci_iounmap(pdev,
+			    (void *)adap_info->ioh_i2c_data[0].
+			    ioh_i2c_base_address);
+		IOH_DEBUG(" pci_iounmap invoked successfully\n");
+		adap_info->ioh_i2c_data[0].ioh_i2c_base_address = 0;
+	}
+
+	pci_set_drvdata(pdev, NULL);
+
+	pci_release_regions(pdev);
+	IOH_DEBUG("  pci_release_regions invoked successfully\n");
+
+	pci_disable_device(pdev);
+	kfree(adap_info);
+	IOH_DEBUG("  pci_disable_device invoked successfully\n");
+	IOH_DEBUG("  ioh_i2c_remove invoked successfully\n");
+}
+
+#ifdef CONFIG_PM
+
+/*! @ingroup	I2C_PCILayerAPI
+  @fn  		ioh_i2c_suspend(struct pci_dev* pdev,pm_message_t state)
+  @remarks  	The main tasks performed by this method are:
+		- Wait for any transfer in progress to complete.
+		- Disable interrupts.
+		- Save PCI device state.
+		- Disable PM notifications.
+		- Disable the PCI device.
+		- Move the device to D3Hot power state.
+  @note		This function is invoked by the kernel when the system is
+		transitioning to low power state.
+  @param  	pdev 	[@ref INOUT]
+		contains reference to PCI device descriptor for the peripheral
+  @param 	state	[@ref IN]
+		Represents the low power state the system is transitioning to.
+  @retval 	int
+		- @ref IOH_I2C_SUCCESS	Function returns successfully.
+		- -ENOMEM	pci_save_state fails.
+  @see		ioh_i2c_pcidriver
+ */
+static int ioh_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+
+	int i;
+	int ret;
+
+	struct adapter_info *adap_info = pci_get_drvdata(pdev);
+
+	IOH_DEBUG(" invoked function pci_get_drvdata successfully\n");
+
+	adap_info->ioh_i2c_suspended = true;
+
+	for (i = 0; i < IOH_I2C_MAX_CHN; i++) {
+		while ((adap_info->ioh_i2c_data[i].ioh_i2c_xfer_in_progress ==
+			true)) {
+			/* It is assumed that any pending transfer will
+			 * be completed after the delay
+			 */
+			msleep(1);
+		}
+		/* Disable the i2c interrupts */
+		ioh_i2c_disbl_int(&adap_info->ioh_i2c_data[i]);
+	}
+
+	IOH_DEBUG("I2CSR = %x\n",
+		  ioh_i2c_readreg(adap_info->
+				  ioh_i2c_data[0].ioh_i2c_base_address, 0x08));
+	IOH_DEBUG("I2CBUFSTA = %x\n",
+		  ioh_i2c_readreg(adap_info->
+				  ioh_i2c_data[0].ioh_i2c_base_address, 0x30));
+	IOH_DEBUG("I2CESRSTA = %x\n",
+		  ioh_i2c_readreg(adap_info->
+				  ioh_i2c_data[0].ioh_i2c_base_address, 0x44));
+
+	IOH_DEBUG(" invoked function ioh_i2c_disbl_int successfully\n");
+
+	ret = pci_save_state(pdev);
+
+	if (ret) {
+		IOH_LOG(KERN_ERR, "pci_save_state failed\n");
+		return ret;
+	}
+
+	IOH_DEBUG("Invoked pci_save_state successfully\n");
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	IOH_DEBUG("Invoked pci_enable_wake successfully\n");
+
+	pci_disable_device(pdev);
+	IOH_DEBUG("Invoked pci_disable_device successfully\n");
+
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	IOH_DEBUG("Invoked pci_set_power_state successfully\n");
+	IOH_DEBUG("ioh_i2c_suspend returns %d\n", IOH_I2C_SUCCESS);
+
+	return IOH_I2C_SUCCESS;
+
+}
+
+/*! @ingroup	I2C_PCILayerAPI
+  @fn  		ioh_i2c_resume(struct pci_dev* pdev)
+  @remarks  	The main tasks performed by this method are:
+		- Move device to D0 power state.
+		- Restore PCI device state.
+		- Enable the PCI device state.
+		- Disable PM notifications.
+		- Initialize IOH I2C device.
+  @note		This function is invoked by the kernel when the system is
+		transitioning to normal power state from a lower power state.
+  @param  	pdev 	[@ref INOUT]
+		contains reference to PCI device descriptor for the peripheral
+  @retval	int
+		- @ref IOH_I2C_SUCCESS	Function returns successfully.
+		- -EIO 		pci_enable_device fails.
+		- -EINVAL 	pci_enable_device fails.
+  @see		ioh_i2c_pcidriver
+  <hr>
+ */
+static int ioh_i2c_resume(struct pci_dev *pdev)
+{
+
+	struct adapter_info *adap_info = pci_get_drvdata(pdev);
+	int i;
+
+	IOH_DEBUG(" invoked function pci_get_drvdata successfully\n");
+
+	pci_set_power_state(pdev, PCI_D0);
+	IOH_DEBUG("Invoked pci_set_power_state successfully\n");
+
+	pci_restore_state(pdev);
+	IOH_DEBUG("Invoked pci_restore_state successfully\n");
+
+	if (pci_enable_device(pdev) < 0) {
+		IOH_LOG(KERN_ERR,
+			"pci_enable_device failed in ioh_i2c_resume\n");
+		return -EIO;
+	}
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+
+	IOH_DEBUG("Invoked pci_enable_wake successfully\n");
+
+	for (i = 0; i < IOH_I2C_MAX_CHN; i++)
+		(void)ioh_i2c_init(&adap_info->ioh_i2c_data[i]);
+
+	IOH_DEBUG("Invoked ioh_i2c_init successfully\n");
+
+	adap_info->ioh_i2c_suspended = false;
+
+	IOH_DEBUG("ioh_i2c_resume return %d\n", IOH_I2C_SUCCESS);
+	return IOH_I2C_SUCCESS;
+}
+
+#endif
+
+/*! @ingroup	I2C_InterfaceLayerAPI
+  @fn  		ioh_i2c_pci_init(void)
+  @brief	This function implements the module entry point.
+  @remarks  	This function invoked at module insertion
+		The main task performed by this method:
+		- Register the PCI driver with PCI core
+		using pci_register_driver API.
+  @param  		None
+  @retval   		int
+			-  0 		Function returns successfully.
+			- -EEXIST	pci_register_driver fails
+			- -EINVAL	pci_register_driver fails
+			- -ENOMEM	pci_register_driver fails
+ <hr>
+ */
+static int __init ioh_i2c_pci_init(void)
+{
+
+	IOH_DEBUG
+	    ("ioh_i2c_pci_init : Invoked pci_register_driver successfully\n");
+	return pci_register_driver(&ioh_i2c_pcidriver);
+}
+
+/*! @ingroup	I2C_InterfaceLayerAPI
+  @fn  		ioh_i2c_pci_exit(void)
+  @brief 	This function implements the module exit point.
+  @remarks	This function is invoked when IOH I2C driver module is being
+		removed from the system. The main task performed by this method:
+		- Unregister the PCI driver with PCI core using
+		the pci_unregister_driver API
+  @param  		None
+  @retval 		None
+ */
+static void __exit ioh_i2c_pci_exit(void)
+{
+	IOH_DEBUG
+	("ioh_i2c_pci_exit : Invoked pci_unregister_driver successfully \n ");
+	pci_unregister_driver(&ioh_i2c_pcidriver);
+
+}
+
+MODULE_DESCRIPTION("IOH I2C PCI Driver");
+MODULE_LICENSE("GPL");
+module_init(ioh_i2c_pci_init);
+module_exit(ioh_i2c_pci_exit);
+module_param(ioh_i2c_speed, int, (S_IRUSR | S_IWUSR));
+module_param(ioh_i2c_clk, int, (S_IRUSR | S_IWUSR));
diff -urN linux-2.6.33.1/drivers/i2c/i2c-dev.c topcliff-2.6.33.1/drivers/i2c/i2c-dev.c
--- linux-2.6.33.1/drivers/i2c/i2c-dev.c	2010-03-16 01:09:39.000000000 +0900
+++ topcliff-2.6.33.1/drivers/i2c/i2c-dev.c	2010-03-24 11:21:29.000000000 +0900
@@ -36,7 +36,7 @@
 #include <linux/i2c-dev.h>
 #include <linux/jiffies.h>
 #include <asm/uaccess.h>
-
+#include "busses/pch_i2c_hal.h"
 static struct i2c_driver i2cdev_driver;
 
 /*
@@ -147,6 +147,11 @@
 	if (tmp==NULL)
 		return -ENOMEM;
 
+	if (copy_from_user(tmp, buf, count)) {
+		kfree(tmp);
+		return -EFAULT;
+	}
+
 	pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n",
 		iminor(file->f_path.dentry->d_inode), count);
 
@@ -372,6 +377,12 @@
 	struct i2c_client *client = (struct i2c_client *)file->private_data;
 	unsigned long funcs;
 
+	unsigned long ioh_mode;
+	int ret;
+
+	struct i2c_msg msg;
+	unsigned char msgbuf[1];
+
 	dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",
 		cmd, arg);
 
@@ -427,6 +438,22 @@
 		 */
 		client->adapter->timeout = msecs_to_jiffies(arg * 10);
 		break;
+	case I2C_MODE_SEL:
+		ioh_mode = arg;
+
+		if (ioh_mode <= 4) {
+			msgbuf[0] = ioh_mode;
+			msg.buf = msgbuf;
+			msg.len = 1;
+			msg.flags = (ioh_mode <=1) ? \
+					(IOH_BUFFER_MODE_ENABLE) : \
+					(IOH_EEPROM_SW_RST_MODE_ENABLE);
+			ret = i2c_transfer(client->adapter, &msg, 1);
+		} else {
+			printk(KERN_ERR "I2C mode sel:Invalid mode \n");
+			ret = -EINVAL;
+		}
+		return ret;
 	default:
 		/* NOTE:  returning a fault code here could cause trouble
 		 * in buggy userspace code.  Some old kernel bugs returned
