summaryrefslogtreecommitdiffstats
path: root/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-i2c.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-i2c.patch')
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-i2c.patch3435
1 files changed, 3435 insertions, 0 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-i2c.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-i2c.patch
new file mode 100644
index 0000000..e6f6f67
--- /dev/null
+++ b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-i2c.patch
@@ -0,0 +1,3435 @@
+
+
+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
OpenPOWER on IntegriCloud