Files
poky/meta/recipes-kernel/linux/linux-netbook-2.6.33.2/linux-2.6.34-pch-gpio.patch

2701 lines
78 KiB
Diff

From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
Subject: OKI Semiconductor PCH GPIO driver
This driver implements GPIO controls for PCH.
Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
Acked-by: Wang Qi <qi.wang@intel.com>
---
drivers/gpio/Kconfig |
drivers/gpio/Makefile |
drivers/gpio/pch_gpio/Makefile |
drivers/gpio/pch_gpio/pch_common.h |
drivers/gpio/pch_gpio/pch_debug.h |
drivers/gpio/pch_gpio/pch_gpio_hal.c |
drivers/gpio/pch_gpio/pch_gpio_hal.h |
drivers/gpio/pch_gpio/pch_gpio_main.c |
drivers/gpio/pch_gpio/pch_gpio_main.h |
drivers/gpio/pch_gpio/pch_gpio_pci.c |
+++++++++++++++++++++++++++++++ 10 files changed, yy insertions(+)(-)
diff -urN linux-2.6.33.1/drivers/gpio/Kconfig topcliff-2.6.33.1/drivers/gpio/Kconfig
--- linux-2.6.33.1/drivers/gpio/Kconfig 2010-03-16 01:09:39.000000000 +0900
+++ topcliff-2.6.33.1/drivers/gpio/Kconfig 2010-04-01 10:58:31.000000000 +0900
@@ -87,6 +87,13 @@
comment "I2C GPIO expanders:"
+config PCH_GPIO
+ tristate "PCH GPIO"
+ depends on PCI
+ help
+ If you say yes to this option, support will be included for the SMB
+ PCH GPIO Host controller.
+
config GPIO_MAX732X
tristate "MAX7319, MAX7320-7327 I2C Port Expanders"
depends on I2C
diff -urN linux-2.6.33.1/drivers/gpio/Makefile topcliff-2.6.33.1/drivers/gpio/Makefile
--- linux-2.6.33.1/drivers/gpio/Makefile 2010-03-16 01:09:39.000000000 +0900
+++ topcliff-2.6.33.1/drivers/gpio/Makefile 2010-04-01 10:58:31.000000000 +0900
@@ -22,3 +22,4 @@
obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o
+obj-$(CONFIG_PCH_GPIO) += pch_gpio/
diff -urN linux-2.6.33.1/drivers/gpio/pch_gpio/Makefile topcliff-2.6.33.1/drivers/gpio/pch_gpio/Makefile
--- linux-2.6.33.1/drivers/gpio/pch_gpio/Makefile 1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/gpio/pch_gpio/Makefile 2010-04-01 10:58:31.000000000 +0900
@@ -0,0 +1,7 @@
+ifeq ($(CONFIG_GPIO_DEBUG_CORE),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_PCH_GPIO) += pch_gpio.o
+pch_gpio-objs := pch_gpio_hal.o pch_gpio_main.o pch_gpio_pci.o
+
diff -urN linux-2.6.33.1/drivers/gpio/pch_gpio/pch_common.h topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_common.h
--- linux-2.6.33.1/drivers/gpio/pch_gpio/pch_common.h 1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_common.h 2010-04-01 10:58:31.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/gpio/pch_gpio/pch_debug.h topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_debug.h
--- linux-2.6.33.1/drivers/gpio/pch_gpio/pch_debug.h 1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_debug.h 2010-04-01 10:58:31.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/gpio/pch_gpio/pch_gpio_hal.c topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_hal.c
--- linux-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_hal.c 1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_hal.c 2010-04-01 10:58:31.000000000 +0900
@@ -0,0 +1,595 @@
+/*!
+ * @file ioh_gpio_hal.c
+ * @brief Provides all the implementation of the interfaces pertaining to the
+ * HAL.
+ * @version 0.92
+ * @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 01/05/2010
+ * Added the interfaces provided by the gpio module.
+ *
+ */
+
+/*includes*/
+#include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include "pch_common.h"
+#include "pch_debug.h"
+#include "pch_gpio_main.h"
+#include "pch_gpio_hal.h"
+
+/* mask for interrupt mode configuration */
+#define GPIO_INT_MODE_MSK (0xF)
+
+/* mask for interrupt mode bit position */
+#define GPIO_INT_MODE_POS (0x4)
+
+/* interrupt mode valid value */
+#define GPIO_INT_MODE_VALID (0x4)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def BITS_32
+ @brief Corresponds to the 32 bit position.
+*/
+#define BITS_32 (32)
+
+
+/*! @ingroup GPIO_Global
+ @var ioh_gpio_cbr
+ @brief The global variable for storing the callback function pointer.
+ @remarks This variable is used to store the function pointer
+ to the callback function of the GPIO module.
+
+ @see
+ - ioh_gpio_cb_register
+*/
+void (*ioh_gpio_cbr) (u32);
+
+/*! @ingroup GPIO_HALLayer
+ struct ioh_gpio_reg_data
+ @brief The register data.
+*/
+struct ioh_gpio_reg_data {
+ u32 ien_reg; /**< To store contents of IEN register. */
+ u32 imask_reg; /**< To store contents of IMASK register. */
+ u32 po_reg; /**< To store contents of PO register. */
+ u32 pm_reg; /**< To store contents of PM register. */
+ u32 im0_reg; /**< To store contents of IM0 register. */
+ u32 im1_reg; /**< To store contents of IM1 register. */
+} ioh_gpio_reg;
+
+/*functions implementations*/
+/*! @ingroup GPIO_HALLayerAPI
+@fn void ioh_gpio_cb_register(void(*ioh_gpio_ptr)(u32))
+@brief Registers the callback function.
+@remarks This function registers the callback function used
+ by the gpio module. The main task performed by this
+ function is:
+ - If the function argument is non NULL, update the
+ same in the global callback pointer variable
+ @ref ioh_gpio_cbr.
+@param ioh_gpio_cb_register [@ref INOUT]
+ Contains the reference of the function pointer
+@retval None
+@see
+ - ioh_gpio_int_mode
+*/
+void ioh_gpio_cb_register(void (*ioh_gpio_ptr) (u32))
+{
+ if (ioh_gpio_ptr != NULL) {
+
+ init_waitqueue_head(&ioh_gpio_event);
+ IOH_DEBUG
+ (" In ioh_gpio_cb_register: value of ioh_gpio_ptr = %p\n",
+ ioh_gpio_ptr);
+ ioh_gpio_cbr = ioh_gpio_ptr;
+ IOH_DEBUG("ioh_gpio_cb_register Registered callback\n");
+ IOH_DEBUG
+ ("In ioh_gpio_cb_register : value of ioh_gpio_cbr =%p\n",
+ ioh_gpio_cbr);
+ }
+
+}
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn void ioh_gpio_int_mode(struct ioh_gpio_reqt * gpio_reqt)
+@remarks Implements the functionality of disabling or enabling interrupts.
+ The main tasks performed by this function are:
+ - If the request is for disabling the interrupts, then the
+ corresponding bits in the IEN register are set to 0.
+ - If the request is for enabling the interrupts, then the
+ corresponding bits in the IEN register are set to 1.
+
+@param gpio_reqt [@ref INOUT]
+ Contains the reference of the ioh_gpio_reqt structure
+@retval s32
+ - @ref IOH_GPIO_SUCCESS --> If the operation is successful.
+ - -EINVAL --> Failure.
+@see
+ - ioh_gpio_dir_mode
+*/
+s32 ioh_gpio_int_mode(struct ioh_gpio_reqt *gpio_reqt)
+{
+ u32 ioh_pins;
+ u32 base_addr;
+ u32 i;
+ u32 ien_val;
+ u64 temp;
+ u64 mode_val;
+
+ /* initialize locals */
+ ioh_pins = gpio_reqt->pins;
+ base_addr = ioh_gpio_base_address;
+ ien_val = IOH_READ_LONG(base_addr + IOH_IEN);
+
+ /* Disable applicable bits in IEN register */
+ ien_val &= (~ioh_pins);
+ IOH_WRITE_LONG(ien_val, (base_addr + IOH_IEN));
+ IOH_DEBUG("ioh_gpio_int_mode wrote %x to IOH_IEN\n", ien_val);
+
+ /* Reading the modes of all the 12 pins. */
+ mode_val = ((((u64) IOH_READ_LONG(base_addr + IOH_IM1)) << BITS_32) |
+ (IOH_READ_LONG(base_addr + IOH_IM0)));
+
+ /* enable interrupts */
+ if (gpio_reqt->enable == 1) {
+ IOH_DEBUG("ioh_gpio_int_mode Enabling interrupts\n");
+
+ for (i = 0; i < GPIO_NUM_PINS; i++) {
+ /*GPIO_NUM_PINS = max num. pins for the GPIO port. */
+ if (ioh_pins & (1 << i)) {
+ /*If interrupt for the pin has to be enabled. */
+ /* int. mode setting for each pin is specified
+ by 3 bits
+ 000 Generates an interrupt
+ at the falling edge.
+ 001 Generates an interrupt
+ at the rising edge.
+ 010 Generates an interrupt
+ at the input of a L level.
+ 011 Generates an interrupt
+ at the input of a H level.
+ 100 Generates an interrupt
+ at both edges (rising edge/falling edge).
+ */
+ /* Clear the existing interrupt mode
+ setting for the current pin. */
+ mode_val &=
+ ~(((u64) GPIO_INT_MODE_MSK) <<
+ (i * GPIO_INT_MODE_POS));
+
+ /* Update the new setting. */
+ temp =
+ (gpio_reqt->
+ mode) & (((u64) GPIO_INT_MODE_MSK) << (i *
+ GPIO_INT_MODE_POS));
+
+ mode_val |= temp;
+
+ if (((temp >> (i * GPIO_INT_MODE_POS)) >
+ GPIO_INT_MODE_VALID)) {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_int_mode Invalid\
+ mode selection for "
+ "pin %d\n", i);
+ return -EINVAL;
+ }
+ IOH_DEBUG
+ ("ioh_gpio_int_mode Interrupt enabled\
+ for pin %d \n",
+ i);
+ } else {
+ IOH_DEBUG
+ ("ioh_gpio_int_mode Interrupt not enabled\
+ for pin %d \n",
+ i);
+ }
+ }
+ /* Set the mode register IM0 */
+ IOH_WRITE_LONG(((u32) (mode_val & BIT_MASK_32)),
+ (base_addr + IOH_IM0));
+ IOH_DEBUG("ioh_gpio_int_mode wrote %x to IOH_IM0\n",
+ ((u32) (mode_val & BIT_MASK_32)));
+
+ /* Set the mode register IM1 */
+ IOH_WRITE_LONG(((u32) (mode_val >> BITS_32)),
+ (base_addr + IOH_IM1));
+ IOH_DEBUG("ioh_gpio_int_mode wrote %x to IOH_IM1\n",
+ ((u32) (mode_val >> BITS_32)));
+
+ /* Clear the status */
+ IOH_WRITE_LONG(ioh_pins, (base_addr + IOH_ICLR));
+ IOH_DEBUG("ioh_gpio_int_mode wrote %x to IOH_ICLR\n",
+ ioh_pins);
+ IOH_DEBUG("ioh_gpio_int_mode value in to IOH_ISTATUS %x\n",
+ IOH_READ_LONG(base_addr + IOH_ISTATUS));
+
+ /* Clear the mask register */
+ IOH_WRITE_LONG(ioh_pins, (base_addr + IOH_IMASKCLR));
+ IOH_DEBUG("ioh_gpio_int_mode wrote %x to IOH_IMASKCLR\n",
+ ioh_pins);
+
+ ien_val = (ien_val | ioh_pins);
+
+ /*Enable applicable bits in IEN register */
+ IOH_WRITE_LONG(ien_val, (base_addr + IOH_IEN));
+ IOH_DEBUG("ioh_gpio_int_mode wrote %x to IOH_IEN\n", ien_val);
+
+ }
+
+ /* disable interrupts */
+ else {
+ IOH_DEBUG("ioh_gpio_int_mode Disabling interrupts\n");
+ /* Clear the status */
+ IOH_WRITE_LONG(ioh_pins, (base_addr + IOH_ICLR));
+ IOH_DEBUG("ioh_gpio_int_mode wrote %x to IOH_ICLR\n",
+ ioh_pins);
+
+ /* Set the mask register */
+ IOH_WRITE_LONG(ioh_pins, (base_addr + IOH_IMASK));
+ IOH_DEBUG("ioh_gpio_int_mode wrote %x to IOH_IMASK\n",
+ ioh_pins);
+
+ /* IEN bits are already disabled initially */
+
+ }
+ IOH_DEBUG("ioh_gpio_int_mode returning=%d\n", IOH_GPIO_SUCCESS);
+ return IOH_GPIO_SUCCESS;
+}
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn void ioh_gpio_dir_mode(struct ioh_gpio_reqt * gpio_reqt)
+@remarks Implements the functionalities for setting GPIO pin
+ directions[input/output].
+ The main tasks performed by this function are:
+ - Reads the current value of PM register
+ - If input mode is specified @ref GPIO_IN, performs logical
+ AND between the present PM register value and the 1's
+ complement of gpio_reqt->pins (@ref ioh_gpio_reqt) and
+ updates the value in the PM register.
+ - Else performs logical OR between the present PM register value
+ and gpio_reqt->pins (@ref ioh_gpio_reqt) and updates the value
+ in the PM register.
+
+@param gpio_reqt [@ref INOUT] Contains the reference of
+ the ioh_gpio_reqt structure
+@retval None
+@see
+ - ioh_gpio_read
+*/
+void ioh_gpio_dir_mode(struct ioh_gpio_reqt *gpio_reqt)
+{
+ u32 ioh_pm_regval;
+ u32 ioh_pins;
+ u32 base_addr;
+
+ base_addr = ioh_gpio_base_address;
+ ioh_pm_regval = IOH_READ_LONG(base_addr + IOH_PM);
+ ioh_pins = gpio_reqt->pins;
+
+ /* input mode */
+ if (gpio_reqt->mode == GPIO_IN) {
+ IOH_DEBUG("ioh_gpio_dir_mode GPIO_IN\n");
+ (ioh_pm_regval &= (~ioh_pins));
+ } else {
+ ioh_pm_regval |= ioh_pins;
+ IOH_DEBUG("ioh_gpio_dir_mode GPIO_OUT\n");
+ }
+
+ IOH_WRITE_LONG(ioh_pm_regval, (base_addr + IOH_PM));
+ IOH_DEBUG("ioh_gpio_dir_mode wrote %x to IOH_PM\n", ioh_pm_regval);
+}
+
+/*! @ingroup GPIO_HALLayerAPI
+ @fn int ioh_gpio_read(struct ioh_gpio_reqt * gpio_reqt)
+ @remarks Implements the register read functionality of the
+ gpio module.
+ The main tasks performed by this function are:
+ - Reads the value from PI[Port Input] Register.
+ Masks the value with 0xff and updates the value in
+ gpio_reqt->pins
+ (@ref ioh_gpio_reqt).
+
+ @param gpio_reqt [@ref INOUT]
+ Contains the reference of the ioh_gpio_reqt structure
+ @retval s32
+ - @ref IOH_GPIO_SUCCESS -->
+ If the operation is successful.
+ @see
+ - IOCTL_GPIO_READ
+*/
+s32 ioh_gpio_read(struct ioh_gpio_reqt *gpio_reqt)
+{
+
+ gpio_reqt->pins =
+ (ioh_gpio_bit_mask & IOH_READ_LONG(ioh_gpio_base_address + IOH_PI));
+ return IOH_GPIO_SUCCESS;
+
+}
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn int ioh_gpio_write(struct ioh_gpio_reqt * gpio_reqt)
+@remarks Implements the register write functionality of the gpio module.
+ The main tasks performed by this function are:
+- Masks gpio_reqt->pins (@ref ioh_gpio_reqt) with 0xFF to
+ retrieve the valid 8 bits.
+- Reads the current value of PO register
+- If (gpio_reqt->mode == GPIO_LOW), performs logical AND
+ between the present PM register value and the 1.s complement
+ of gpio_reqt->pins and updates the value in the PO register.
+- Else, (gpio_reqt->mode != GPIO_LOW; implies Output High), performs
+ logical OR between the present PO register value and gpio_reqt->pins
+ and updates the value in the PO register.
+
+ @param gpio_reqt [@ref INOUT]
+ Contains the reference of the ioh_gpio_reqt structure
+ @retval s32
+ - @ref IOH_GPIO_SUCCESS
+ --> If the operation is successful.
+ @see
+ - IOCTL_GPIO_WRITE
+*/
+s32 ioh_gpio_write(struct ioh_gpio_reqt *gpio_reqt)
+{
+ u32 reg_val;
+
+ reg_val = IOH_READ_LONG(ioh_gpio_base_address + IOH_PO);
+
+ if (gpio_reqt->mode == GPIO_LOW) {
+ reg_val &= ~(gpio_reqt->pins);
+ IOH_DEBUG("ioh_gpio_write GPIO_LOW\n");
+ } else {
+ reg_val |= gpio_reqt->pins;
+ IOH_DEBUG("ioh_gpio_write GPIO_HIGH\n");
+ }
+
+ IOH_WRITE_LONG(reg_val, ioh_gpio_base_address + IOH_PO);
+ IOH_DEBUG("ioh_gpio_write writing value=%x\n", reg_val);
+
+ IOH_DEBUG("ioh_gpio_write returning %d\n", IOH_GPIO_SUCCESS);
+ return IOH_GPIO_SUCCESS;
+}
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn irqreturn_t ioh_gpio_handler(int irq,void * pData)
+@remarks Implements the interrupt handler functionality of the gpio module.
+The main tasks performed by this function are:
+- Reads the IDISP register
+- If IDISP register content is zero, then returns IRQ_NONE.
+- Else clears the Interrupt status by writing to the ICLR register,
+ invokes the call back function specified by @ref ioh_gpio_cbr
+ with the value of IDISP as parameter and returns IRQ_HANDLED.
+
+@param irq [@ref INOUT] Contains the irq value
+@param pData [@ref INOUT] Contains the reference to the base
+ gpio address.
+@retval irqreturn_t
+ - IRQ_HANDLED --> If GPIO hardware is responsible
+ for the interrupt.
+ - IRQ_NONE --> Non-GPIO interrupt.
+*/
+irqreturn_t ioh_gpio_handler(int irq, void *pData)
+{
+ irqreturn_t ret = IRQ_NONE;
+ u32 base_addr = ioh_gpio_base_address;
+ u32 ioh_idisp_regval;
+
+ ioh_idisp_regval =
+ (ioh_gpio_bit_mask & IOH_READ_LONG(base_addr + IOH_IDISP));
+ if (ioh_idisp_regval != 0) {
+ /*invoke the callback */
+ (*ioh_gpio_cbr) (ioh_idisp_regval);
+
+ IOH_DEBUG
+ ("ioh_gpio_handler : ioh_gpio_cb invoked successfully %d\n",
+ ret);
+ /*clear the interrupt */
+ IOH_LOG(KERN_ERR, "Value at idisp 8 = %x",
+ (IOH_READ_LONG(base_addr + IOH_IDISP)));
+ IOH_LOG(KERN_ERR, "Value at pin 8 = %x",
+ ((IOH_READ_LONG(base_addr + IOH_PI) & 0x80)));
+
+ IOH_WRITE_LONG(ioh_idisp_regval, (base_addr + IOH_ICLR));
+
+ ret = IRQ_HANDLED;
+ IOH_DEBUG("ioh_gpio_handler returns IRQ_HANDLED\n");
+ } else {
+
+ IOH_DEBUG("ioh_gpio_handler returns IRQ_NONE\n");
+ }
+ return ret;
+}
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn void ioh_gpio_cb(u32 value)
+@brief The interrupt handler callback function.
+@remarks The main tasks performed by this function are:
+ - Updates the GPIO event flag with the parameter value.
+ This sets the appropriate event flag bits based on the
+ bits set in IDISP register.
+ - Wakes up the blocking ioctl call @ref IOCTL_GPIO_NOTIFY.
+
+@param value [@ref INOUT] Contains the value data
+@retval None
+@see
+ - ioh_gpio_cb_register
+*/
+void ioh_gpio_cb(u32 value)
+{
+ /* update the event flag */
+ ioh_gpio_event_flag = value;
+
+ IOH_DEBUG
+ ("ioh_gpio_cb : event flag value = %x\tIDISP register value = %x\n",
+ ioh_gpio_event_flag,
+ (IOH_READ_LONG(ioh_gpio_base_address + IOH_IDISP)));
+ wake_up_interruptible(&ioh_gpio_event);
+}
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn void ioh_gpio_save_reg_conf(void)
+@remarks Save register configuration and disable interrupts.
+ The main tasks performed by this function are:
+ - Read the registers PM, PO, IEN, IM0, IM1 and IMASK
+ and stores the values for further use.
+ - Disables the interrupts by clearing IEN register.
+
+@param None
+@retval None
+@see
+ - ioh_gpio_suspend
+*/
+void ioh_gpio_save_reg_conf(void)
+{
+ u32 base_addr = ioh_gpio_base_address;
+ IOH_DEBUG("ioh_gpio_save_reg_conf ENTRY\n");
+ /* to store contents of IEN register */
+ ioh_gpio_reg.ien_reg = IOH_READ_LONG(base_addr + IOH_IEN);
+
+ /* to store contents of IMASK register */
+ ioh_gpio_reg.imask_reg = IOH_READ_LONG(base_addr + IOH_IMASK);
+
+ /* to store contents of PO register */
+ ioh_gpio_reg.po_reg = IOH_READ_LONG(base_addr + IOH_PO);
+
+ /* to store contents of PM register */
+ ioh_gpio_reg.pm_reg = IOH_READ_LONG(base_addr + IOH_PM);
+
+ /* to store contents of IM0 register */
+ ioh_gpio_reg.im0_reg = IOH_READ_LONG(base_addr + IOH_IM0);
+
+ /* to store contents of IM1 register */
+ ioh_gpio_reg.im1_reg = IOH_READ_LONG(base_addr + IOH_IM1);
+
+ IOH_DEBUG
+ ("ioh_gpio_save_reg_conf : IOH_IEN=%x, IOH_IMASK=%x, IOH_PO=%x,"
+ "IOH_PM=%x, IOH_IM0=%x, IOH_IM1=%x\n",
+ IOH_READ_LONG(base_addr + IOH_IEN),
+ IOH_READ_LONG(base_addr + IOH_IMASK),
+ IOH_READ_LONG(base_addr + IOH_PO),
+ IOH_READ_LONG(base_addr + IOH_PM),
+ IOH_READ_LONG(base_addr + IOH_IM0),
+ IOH_READ_LONG(base_addr + IOH_IM1));
+
+ IOH_DEBUG("ioh_gpio_save_reg_conf : ioh_gpio_reg.ien_reg=%x, "
+ "ioh_gpio_reg.imask_reg=%x, ioh_gpio_reg.po_reg=%x,\
+ ioh_gpio_reg.pm_reg=%x,"
+ "ioh_gpio_reg.im0_reg=%x, ioh_gpio_reg.im1_reg=%x\n",
+ ioh_gpio_reg.ien_reg, ioh_gpio_reg.imask_reg,
+ ioh_gpio_reg.po_reg, ioh_gpio_reg.pm_reg,
+ ioh_gpio_reg.im0_reg, ioh_gpio_reg.im1_reg);
+
+ /* Disable all gpio interrupts */
+ IOH_WRITE_LONG(0, (base_addr + IOH_IEN));
+ IOH_DEBUG("ioh_gpio_save_reg_conf disabled interrupts\n");
+}
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn void ioh_gpio_restore_reg_conf(void)
+@remarks This function restores the register configuration of the
+ GPIO device. The main task performed by this function
+ is:
+ - Restores the previous register values into the registers
+ PM, PO, IEN, IM0, IM1 and IMASK.
+
+@param None
+@retval None
+@see
+ - ioh_gpio_resume
+*/
+void ioh_gpio_restore_reg_conf(void)
+{
+ u32 base_addr = ioh_gpio_base_address;
+ IOH_DEBUG("ioh_gpio_restore_reg_conf ENTRY\n");
+ /* to store contents of IEN register */
+ IOH_WRITE_LONG(ioh_gpio_reg.ien_reg, base_addr + IOH_IEN);
+
+ /* to store contents of IMASK register */
+ IOH_WRITE_LONG(ioh_gpio_reg.imask_reg, base_addr + IOH_IMASK);
+
+ /* to store contents of IMASK register */
+ IOH_WRITE_LONG(~ioh_gpio_reg.imask_reg, base_addr + IOH_IMASKCLR);
+
+ /* to store contents of PO register */
+ IOH_WRITE_LONG(ioh_gpio_reg.po_reg, base_addr + IOH_PO);
+
+ /* to store contents of PM register */
+ IOH_WRITE_LONG(ioh_gpio_reg.pm_reg, base_addr + IOH_PM);
+
+ /* to store contents of IM0 register */
+ IOH_WRITE_LONG(ioh_gpio_reg.im0_reg, base_addr + IOH_IM0);
+
+ /* to store contents of IM1 register */
+ IOH_WRITE_LONG(ioh_gpio_reg.im1_reg, base_addr + IOH_IM1);
+
+ IOH_DEBUG
+ ("ioh_gpio_save_reg_conf : ioh_gpio_reg.ien_reg=%x,\
+ ioh_gpio_reg.imask_reg=%x,"\
+ "ioh_gpio_reg.po_reg=%x, ioh_gpio_reg.pm_reg=%x,\
+ ioh_gpio_reg.im0_reg=%x,"\
+ "ioh_gpio_reg.im1_reg=%x\n", ioh_gpio_reg.ien_reg,
+ ioh_gpio_reg.imask_reg, ioh_gpio_reg.po_reg, ioh_gpio_reg.pm_reg,
+ ioh_gpio_reg.im0_reg, ioh_gpio_reg.im1_reg);
+
+ IOH_DEBUG
+ ("ioh_gpio_save_reg_conf : IOH_IEN=%x, IOH_IMASK=%x, IOH_PO=%x,\
+ IOH_PM=%x, IOH_IM0=%x, IOH_IM1=%x\n",\
+ IOH_READ_LONG(base_addr + IOH_IEN),
+ IOH_READ_LONG(base_addr + IOH_IMASK),
+ IOH_READ_LONG(base_addr + IOH_PO),
+ IOH_READ_LONG(base_addr + IOH_PM),
+ IOH_READ_LONG(base_addr + IOH_IM0),
+ IOH_READ_LONG(base_addr + IOH_IM1));
+
+ IOH_DEBUG("ioh_gpio_restore_reg_conf enabled interrupts\n");
+}
+
+/*! @ingroup GPIO_HALLayerAPI
+ @fn u32 ioh_gpio_readreg(int offset)
+ @brief Reads the register.
+ @remarks This function reads the register located at
+ the passed offset and returns the read value.
+ @param Offset [@reg IN] The offset to be read.
+ @retval u32 --> Register value
+
+*/
+u32 ioh_gpio_readreg(int offset)
+{
+ u32 reg_val;
+ reg_val = (IOH_READ_LONG(ioh_gpio_base_address + offset));
+ IOH_DEBUG("ioh_gpio_readreg read reg=%x,value=%x\n",
+ (ioh_gpio_base_address + offset), reg_val);
+ return reg_val;
+}
+
+int ioh_gpio_writereg(int offset, u32 val)
+{
+ IOH_WRITE_LONG(val, ioh_gpio_base_address + offset);
+ IOH_DEBUG("%s read reg=%x,value=%x\n", __func__,
+ (ioh_gpio_base_address + offset), val);
+ return 0;
+}
diff -urN linux-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_hal.h topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_hal.h
--- linux-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_hal.h 1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_hal.h 2010-04-01 10:58:31.000000000 +0900
@@ -0,0 +1,170 @@
+/*!
+ * @file ioh_gpio_hal.h
+ * @brief Provides all the interfaces pertaining to the HAL.
+ * @version 0.92
+ * @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 01/05/2010
+ * Added the interfaces provided by the HAL.
+ *
+ */
+
+#ifndef __IOH_GPIO_HAL_H__
+#define __IOH_GPIO_HAL_H__
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_IEN
+ @brief Offset for IEN register.
+*/
+#define IOH_IEN (0x00)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_ISTATUS
+ @brief Offset for ISTATUS register.
+*/
+#define IOH_ISTATUS (0x04)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_IDISP
+ @brief Offset for IDISP register.
+*/
+#define IOH_IDISP (0x08)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_ICLR
+ @brief Offset for ICLR register.
+*/
+#define IOH_ICLR (0x0C)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_IMASK
+ @brief Offset for IMASK register.
+*/
+#define IOH_IMASK (0x10)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_IMASKCLR
+ @brief Offset for IMASKCLR register.
+*/
+#define IOH_IMASKCLR (0x14)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_PO
+ @brief Offset for IMASKCLR register.
+*/
+#define IOH_PO (0x18)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_PI
+ @brief Offset for PI register.
+*/
+#define IOH_PI (0x1C)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_PM
+ @brief Offset for PM register.
+*/
+#define IOH_PM (0x20)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_IM0
+ @brief Offset for IM0 register.
+*/
+#define IOH_IM0 (0x24)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_IM1
+ @brief Offset for IM1 register.
+*/
+#define IOH_IM1 (0x28)
+
+/* exported function prototypes */
+/*! @ingroup GPIO_HALLayerAPI
+ @fn void ioh_gpio_cb(int)
+ @brief Interrupt handler callback function
+*/
+void ioh_gpio_cb(u32);
+
+/*! @ingroup GPIO_HALLayerAPI
+ @fn void ioh_gpio_cb_register(void(*ioh_gpio_cbr)(u32))
+ @brief Interrupt handler callback register function
+*/
+void ioh_gpio_cb_register(void (*ioh_gpio_cbr) (u32));
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn s32 ioh_gpio_int_mode(struct ioh_gpio_reqt * gpio_reqt)
+@brief This function sets the interrupt mode for each of the GPIO input pins
+*/
+s32 ioh_gpio_int_mode(struct ioh_gpio_reqt *gpio_reqt);
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn void ioh_gpio_dir_mode(struct ioh_gpio_reqt * gpio_reqt)
+@brief Provides the functionality of setting gpio pin directions[input/output]
+*/
+void ioh_gpio_dir_mode(struct ioh_gpio_reqt *gpio_reqt);
+
+/*! @ingroup GPIO_HALLayerAPI
+ @fn s32 ioh_gpio_read(struct ioh_gpio_reqt * gpio_reqt)
+ @brief Provides the functionality of reading GPIO pin status
+*/
+s32 ioh_gpio_read(struct ioh_gpio_reqt *gpio_reqt);
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn s32 ioh_gpio_write(struct ioh_gpio_reqt * gpio_reqt)
+@brief Provides the functionality of writing data to the GPIO port
+*/
+s32 ioh_gpio_write(struct ioh_gpio_reqt *gpio_reqt);
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn irqreturn_t ioh_gpio_handler(int irq,void * pData)
+@brief Provides the functionality of handling interrupts from GPIO h/w
+*/
+irqreturn_t ioh_gpio_handler(int irq, void *pData);
+
+/*! @ingroup GPIO_HALLayerAPI
+@fn void ioh_gpio_save_reg_conf(void)
+@brief Saves register configuration and also disables GPIO interrupts
+*/
+void ioh_gpio_save_reg_conf(void);
+
+/*! @ingroup GPIO_HALLayerAPI
+ @fn void ioh_gpio_restore_reg_conf(void)
+ @brief Restores register configuration
+*/
+void ioh_gpio_restore_reg_conf(void);
+
+/*! @ingroup GPIO_HALLayerAPI
+ @fn u32 ioh_gpio_readreg(int offset)
+ @brief Function to read the value of a GPIO register
+*/
+u32 ioh_gpio_readreg(int offset);
+int ioh_gpio_writereg(int offset, u32 val);
+
+/* global variables */
+extern u32 ioh_gpio_base_address;
+extern u32 ioh_gpio_event_flag;
+extern wait_queue_head_t ioh_gpio_event;
+extern u32 ioh_gpio_bit_mask;
+
+#endif
diff -urN linux-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_main.c topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_main.c
--- linux-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_main.c 1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_main.c 2010-04-01 11:41:01.000000000 +0900
@@ -0,0 +1,420 @@
+/*!
+ * @file ioh_gpio_main.c
+ * @brief Provides all the implementation of the interfaces pertaining to the
+ * GPIO module.
+ * @version 0.92
+ * @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 01/05/2010
+ * Added the interfaces provided by the GPIO module.
+ *
+ */
+
+/* includes */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+
+#include "pch_common.h"
+#include "pch_debug.h"
+#include "pch_gpio_main.h"
+#include "pch_gpio_hal.h"
+
+#define MODULE_NAME "ioh_gpio"
+
+DEFINE_SPINLOCK(ioh_gpio_lock); /* for spin lock */
+u32 ioh_gpio_event_flag; /* flag for event */
+s32 ioh_gpio_opencount; /* check whether opened or not */
+
+/*spinlock_t ioh_gpio_lock = SPIN_LOCK_UNLOCKED; for spin lock */
+wait_queue_head_t ioh_gpio_event; /* wait queue head */
+
+/*! @ingroup GPIO_InterfaceLayerFacilitators
+ @struct ioh_gpio_fops
+ @brief Instance of the Kernel structure file_operations.
+*/
+const struct file_operations ioh_gpio_fops = {
+ .owner = THIS_MODULE,
+ .open = ioh_gpio_open,
+ .release = ioh_gpio_release,
+ .ioctl = ioh_gpio_ioctl,
+};
+
+/*function implementations*/
+
+/*! @ingroup GPIO_InterfaceLayerAPI
+@fn int ioh_gpio_open( struct inode *inode,struct file *file)
+@remarks The main tasks performed by this function are:
+- Ensures that the device is not opened before by checking the open count.
+ If it is already opened, then returns EBUSY status code.
+- Registers the interrupt handler by invoking request_irq.
+ If this fails then returns its error code.
+ Otherwise returns @ref IOH_GPIO_SUCCESS
+
+@param inode [@ref INOUT] Contains the reference of the inode structure
+@param file [@ref INOUT] Contains the reference of the file structure
+@retval int
+ - @ref IOH_GPIO_SUCCESS --> If operation is successful.
+ - -EBUSY --> If already opened/ request_irq
+ error status code.
+ - -EINVAL --> request_irq error status code.
+ - -ENOMEM --> request_irq error status code.
+ - -ENOSYS --> request_irq error status code.
+
+@see
+ - ioh_gpio_fops
+*/
+int ioh_gpio_open(struct inode *inode, struct file *file)
+{
+ int ret;
+
+ spin_lock(&ioh_gpio_lock);
+ IOH_DEBUG("ioh_gpio_open : open count value = %d", ioh_gpio_opencount);
+ if (ioh_gpio_opencount) {
+ IOH_LOG(KERN_ERR, "ioh_gpio_open : device already opened\n");
+ ret = -EBUSY;
+ } else {
+
+ ret =
+ (request_irq
+ (ioh_gpio_irq, &ioh_gpio_handler, IRQF_SHARED, MODULE_NAME,
+ (void *)ioh_gpio_base_address));
+ if (ret) {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_open : request_irq failed\n");
+ } else {
+ ioh_gpio_opencount++;
+ IOH_DEBUG
+ ("ioh_gpio_open : request_irq invoked\
+ successfully\n");
+ ret = IOH_GPIO_SUCCESS;
+ }
+ }
+ spin_unlock(&ioh_gpio_lock);
+
+ IOH_DEBUG("ioh_gpio_open returns=%d\n", ret);
+ return ret;
+}
+
+/*! @ingroup GPIO_InterfaceLayerAPI
+@fn int ioh_gpio_release(struct inode *inode,struct file *file)
+@remarks The main tasks performed by this function are:
+-Ensures that device is opened successfully by checking the open count value.
+ If it is not opened, then returns with IOH_GPIO_SUCCESS status code.
+-Disables interrupts for all pins by using @ref ioh_gpio_int_mode
+ API.
+-Un-registers interrupt handler and returns @ref IOH_GPIO_SUCCESS.
+
+@param inode [@ref INOUT] Contains the reference of the inode structure
+@param file [@ref INOUT] Contains the reference of the file structure
+@retval int
+ - @ref IOH_GPIO_SUCCESS -->
+ If the operation is successful.
+@see
+ - ioh_gpio_fops
+*/
+int ioh_gpio_release(struct inode *inode, struct file *file)
+{
+ struct ioh_gpio_reqt req;
+ spin_lock(&ioh_gpio_lock);
+
+ if (ioh_gpio_opencount > 0) {
+ memset(&req, 0, sizeof(req));
+ req.pins = IOH_GPIO_ALL_PINS;
+
+ /* disable interrupts for all gpio pins */
+ (void)ioh_gpio_int_mode(&req);
+
+ free_irq(ioh_gpio_irq, (void *)ioh_gpio_base_address);
+ IOH_DEBUG("ioh_gpio_release : free_irq invoked successfully");
+
+ ioh_gpio_opencount--;
+ }
+ spin_unlock(&ioh_gpio_lock);
+
+ IOH_DEBUG("ioh_gpio_release : ioh_gpio_opencount =%d\n",
+ ioh_gpio_opencount);
+
+ IOH_DEBUG("ioh_gpio_release returning=%d\n", IOH_GPIO_SUCCESS);
+ return IOH_GPIO_SUCCESS;
+}
+
+/*! @ingroup GPIO_InterfaceLayerAPI
+@fn int ioh_gpio_ioctl(struct inode * inode,struct file * file,
+ unsigned int cmd,unsigned long arg)
+@remarks The main tasks performed by this function are:
+ - Copies the arg from user space to kernel space.
+ If this fails, returns EFAULT status code.
+ - Checks the cmd specified. If not a valid command,
+ returns EINVAL status code.
+ - Verifies the validity of the command argument based on
+ the operation requested. If invalid, returns EINVAL.
+ - Performs the requested action based on the ioctl command,
+ by calling the appropriate HAL API functions.
+ - Returns @ref IOH_GPIO_SUCCESS if the command is completed
+ successfully.
+
+@param inode [@ref INOUT] Contains the reference of the inode structure
+@param file [@ref INOUT] Contains the reference of the file structure
+@param cmd [@ref IN] Contains the command value
+@param arg [@ref IN] Contains the command argument value
+@retval int
+- @ref IOH_GPIO_SUCCES --> If the operation is successful.
+- -EFAULT --> wait_event_interruptible API
+ is interrupted by a signal.
+- -ERESTARTSYS --> wait_event_interruptible API
+ is interrupted by a signal.
+- -EINVAL --> Invalid address/parameter.
+
+@see
+ - ioh_gpio_fops
+*/
+int ioh_gpio_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+
+ struct ioh_gpio_reqt gpio_reqt;
+ s32 ret_value;
+
+ IOH_DEBUG(KERN_INFO"%s:cmd = 0x%x\n", __func__, cmd);
+ IOH_DEBUG(KERN_INFO"%s: IOCTL_GPIO_INT_ENABLE= 0x%x\n", __func__,
+ IOCTL_GPIO_INT_ENABLE);
+ IOH_DEBUG(KERN_INFO"%s: IOCTL_GPIO_INT_DISABLE= 0x%x\n", __func__,
+ IOCTL_GPIO_INT_DISABLE);
+ IOH_DEBUG(KERN_INFO"%s: IOCTL_GPIO_DIRECTION= 0x%x\n", __func__,
+ IOCTL_GPIO_DIRECTION);
+ IOH_DEBUG(KERN_INFO"%s: IOCTL_GPIO_WRITE= 0x%x\n", __func__,
+ IOCTL_GPIO_WRITE);
+ IOH_DEBUG(KERN_INFO"%s: IOCTL_GPIO_READ= 0x%x\n", __func__,
+ IOCTL_GPIO_READ);
+ IOH_DEBUG(KERN_INFO"%s: IOCTL_GPIO_NOTIFY= 0x%x\n", __func__,
+ IOCTL_GPIO_NOTIFY);
+
+ do {
+ if (ioh_gpio_suspended == true) {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_ioctl : suspend initiated returning\
+ =%d\n",
+ IOH_GPIO_FAIL);
+ ret_value = IOH_GPIO_FAIL;
+ break;
+ }
+
+ ret_value =
+ copy_from_user(&gpio_reqt, (void *)arg,
+ sizeof(struct ioh_gpio_reqt));
+ if (ret_value) {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_ioctl : copy_from_user fail returning\
+ =%d\n",
+ -EFAULT);
+ ret_value = -EFAULT;
+ break;
+ }
+ IOH_DEBUG("ioh_gpio_ioctl : copy_from_user returns =%d\n",
+ ret_value);
+
+ if (((gpio_reqt.enable) > 1)
+ || ((gpio_reqt.pins) > GPIO_MAX_PINS_MASK)
+ || ((gpio_reqt.port) > GPIO_NUM_PORT_MAX)) {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_ioctl : Invalid parameter\
+ returning=%d\n",
+ -EINVAL);
+ ret_value = -EINVAL;
+ break;
+ }
+ switch (cmd) {
+ case IOCTL_GPIO_INT_ENABLE:
+ {
+
+ if (gpio_reqt.enable == 0) {
+ ret_value = -EINVAL;
+ IOH_DEBUG
+ ("ioh_gpio_ioctl : Invalid\
+ parameter in enable\n");
+ } else {
+ ret_value =
+ ioh_gpio_int_mode(&gpio_reqt);
+ IOH_DEBUG
+ ("ioh_gpio_ioctl : Invoked\
+ ioh_gpio_int_mode successfully\n");
+ }
+ break;
+ }
+
+ case IOCTL_GPIO_INT_DISABLE:
+ {
+ if (gpio_reqt.enable != 0) {
+ ret_value = -EINVAL;
+ IOH_DEBUG
+ ("ioh_gpio_ioctl : Invalid\
+ parameter in enable\n");
+ } else {
+ ret_value =
+ ioh_gpio_int_mode(&gpio_reqt);
+ IOH_DEBUG
+ ("ioh_gpio_ioctl : Invoked\
+ ioh_gpio_int_mode successfully\n");
+ }
+ break;
+ }
+
+ case IOCTL_GPIO_DIRECTION:
+ {
+ if ((gpio_reqt.mode > 1)) {
+
+ IOH_DEBUG
+ ("ioh_gpio_ioctl : Invalid\
+ direction\n");
+ ret_value = -EINVAL;
+ } else {
+ ioh_gpio_dir_mode(&gpio_reqt);
+ IOH_DEBUG
+ ("ioh_gpio_ioctl : Invoked\
+ ioh_gpio_dir_mode successfully\n");
+ ret_value = IOH_GPIO_SUCCESS;
+ }
+ break;
+ }
+
+ case IOCTL_GPIO_WRITE:
+ {
+ ret_value = ioh_gpio_write(&gpio_reqt);
+ IOH_DEBUG
+ ("ioh_gpio_ioctl : Invoked\
+ ioh_gpio_write_mode successfully\n");
+ break;
+ }
+
+ case IOCTL_GPIO_READ:
+ {
+ (void)ioh_gpio_read(&gpio_reqt);
+ IOH_DEBUG
+ ("ioh_gpio_ioctl : Invoked\
+ ioh_gpio_read_mode successfully\n");
+ ret_value =
+ copy_to_user((void *)arg, &gpio_reqt,
+ sizeof(struct ioh_gpio_reqt));
+
+ if (ret_value) {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_ioctl copy_to_user\
+ failed returning=%d\n",
+ -EFAULT);
+ ret_value = -EFAULT;
+ } else {
+ IOH_DEBUG
+ ("ioh_gpio_ioctl copy_to_user\
+ returns=%d\n",
+ ret_value);
+ ret_value = IOH_GPIO_SUCCESS;
+ }
+ break;
+ }
+
+ case IOCTL_GPIO_NOTIFY:
+ {
+ ioh_gpio_event_flag = 0;
+ if ((((ioh_gpio_readreg(IOH_IEN)) &
+ (gpio_reqt.pins)) != (gpio_reqt.pins))
+ ||
+ (((ioh_gpio_readreg(IOH_PM) &
+ (gpio_reqt.pins)) != false))) {
+ /* if interrupts are not enabled on the
+ pins for which notify is requested */
+ /* or the pins are not in input mode */
+ IOH_DEBUG
+ ("ioh_gpio_ioctl GPIO pins not in\
+ input mode or interrupts\
+ not enabled!");
+ ret_value = -EINVAL;
+ } else {
+ ret_value =
+ wait_event_interruptible
+ (ioh_gpio_event,
+ (ioh_gpio_event_flag & gpio_reqt.
+ pins) != 0);
+ if (ret_value) {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_ioctl wait_ev\
+ ent_interruptible\
+ failed returning=%d\n",
+ -ERESTARTSYS);
+ ret_value = -ERESTARTSYS;
+ } else {
+ IOH_DEBUG
+ ("ioh_gpio_ioctl wait_event\
+ _interruptible returns=%d\n",
+ ret_value);
+ (void)ioh_gpio_read(&gpio_reqt);
+ ret_value =
+ copy_to_user((void *)arg,
+ &gpio_reqt,
+ sizeof(struct
+ ioh_gpio_reqt));
+ if (ret_value) {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_ioctl\
+ copy_to_user\
+ failed returni\
+ ng=%d\n",
+ -EFAULT);
+ ret_value = -EFAULT;
+ } else {
+ IOH_DEBUG
+ ("ioh_gpio_ioctl\
+ copy_to_user\
+ returns=%d\n",
+ ret_value);
+ ret_value =
+ IOH_GPIO_SUCCESS;
+ }
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_ioctl invalid command\
+ returning=%d\n",
+ -EINVAL);
+ ret_value = -EINVAL;
+ break;
+ }
+ }
+ break;
+
+ } while (0);
+ IOH_LOG(KERN_ERR, "ioh_gpio_ioctl returns=%d\n", ret_value);
+ return ret_value;
+}
diff -urN linux-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_main.h topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_main.h
--- linux-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_main.h 1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_main.h 2010-04-01 10:58:31.000000000 +0900
@@ -0,0 +1,686 @@
+#ifndef __IOH_GPIO_MAIN_H__
+#define __IOH_GPIO_MAIN_H__
+/*!
+ * @file ioh_gpio_main.h
+ * @brief Provides all the interfaces pertaining to the GPIO module.
+ * @version 0.92
+ * @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 01/05/2010
+ * Added the interfaces provided by the gpio module.
+ *
+*/
+
+/*! @defgroup GPIO*/
+/*! @defgroup GPIO_Global
+ @ingroup GPIO*/
+
+/* @defgroup GlobalGeneral
+ @ingroup GPIO_Global*/
+/* @defgroup GlobalResultCodes
+ @ingroup GPIO_Global*/
+
+/*! @defgroup GPIO_InterfaceLayer
+ @ingroup GPIO*/
+/*! @defgroup GPIO_InterfaceLayerAPI
+ @ingroup GPIO_InterfaceLayer
+*/
+
+/* @defgroup InterfaceLayerNotifyRoutines
+ @ingroup GPIO_InterfaceLayer
+*/
+
+/*! @defgroup GPIO_PCILayer
+ @ingroup GPIO*/
+/*! @defgroup GPIO_PCILayerAPI
+ @ingroup GPIO_PCILayer
+*/
+/*! @defgroup GPIO_PCILayerFacilitators
+ @ingroup GPIO_PCILayer
+*/
+/*! @defgroup GPIO_HALLayer
+ @ingroup GPIO*/
+/*! @defgroup GPIO_HALLayerAPI
+ @ingroup GPIO_HALLayer
+*/
+
+/* @defgroup HALLayerFacilitators
+ @ingroup GPIO_HALLayer
+*/
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def GPIO_IOCTL_MAGIC
+ @brief The ioctl magic number.
+*/
+#define GPIO_IOCTL_MAGIC (0xf7)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOCTL_GPIO_INT_ENABLE
+ @brief IOCTL for GPIO interrupt enable.
+*/
+#define IOCTL_GPIO_INT_ENABLE (_IOW(GPIO_IOCTL_MAGIC, 1, struct ioh_gpio_reqt))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOCTL_GPIO_INT_DISABLE
+ @brief IOCTL for GPIO interrupt disable.
+*/
+#define IOCTL_GPIO_INT_DISABLE (_IOW(GPIO_IOCTL_MAGIC, 2, struct ioh_gpio_reqt))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOCTL_GPIO_DIRECTION
+ @brief IOCTL for GPIO direction setting.
+*/
+#define IOCTL_GPIO_DIRECTION (_IOW(GPIO_IOCTL_MAGIC, 3, struct ioh_gpio_reqt))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOCTL_GPIO_WRITE
+ @brief IOCTL for GPIO write.
+*/
+#define IOCTL_GPIO_WRITE (_IOW(GPIO_IOCTL_MAGIC, 4, struct ioh_gpio_reqt))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOCTL_GPIO_READ
+ @brief IOCTL for GPIO read.
+*/
+#define IOCTL_GPIO_READ (_IOR(GPIO_IOCTL_MAGIC, 5, struct ioh_gpio_reqt))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOCTL_GPIO_NOTIFY
+ @brief IOCTL for GPIO pin status change notification.
+*/
+#define IOCTL_GPIO_NOTIFY (_IOR(GPIO_IOCTL_MAGIC, 6, struct ioh_gpio_reqt))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN0
+ @brief GPIO PIN 0
+*/
+#define IOH_GPIO_PIN0 (0x1)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN1
+ @brief GPIO PIN 1
+*/
+#define IOH_GPIO_PIN1 (0x2)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN2
+ @brief GPIO PIN 2
+*/
+#define IOH_GPIO_PIN2 (0x4)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN3
+ @brief GPIO PIN 3
+*/
+#define IOH_GPIO_PIN3 (0x8)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN4
+ @brief GPIO PIN 4
+*/
+#define IOH_GPIO_PIN4 (0x10)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN5
+ @brief GPIO PIN 5
+*/
+#define IOH_GPIO_PIN5 (0x20)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN6
+ @brief GPIO PIN 6
+*/
+#define IOH_GPIO_PIN6 (0x40)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN7
+ @brief GPIO PIN 7
+*/
+#define IOH_GPIO_PIN7 (0x80)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN8
+ @brief GPIO PIN 8
+*/
+#define IOH_GPIO_PIN8 (0x100)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN9
+ @brief GPIO PIN 9
+*/
+#define IOH_GPIO_PIN9 (0x200)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN10
+ @brief GPIO PIN 10
+*/
+#define IOH_GPIO_PIN10 (0x400)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_PIN11
+ @brief GPIO PIN 11
+*/
+#define IOH_GPIO_PIN11 (0x800)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_ALL_PINS
+ @brief Mask for GPIO pins 0 to 11
+*/
+#define IOH_GPIO_ALL_PINS (IOH_GPIO_PIN0 | IOH_GPIO_PIN1 | IOH_GPIO_PIN2\
+| IOH_GPIO_PIN3 | IOH_GPIO_PIN4 | IOH_GPIO_PIN5 | IOH_GPIO_PIN6 | IOH_GPIO_PIN7\
+| IOH_GPIO_PIN8 | IOH_GPIO_PIN9 | IOH_GPIO_PIN10 | IOH_GPIO_PIN11)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN0
+ @brief Falling Edge interrupt on Pin0
+*/
+#define INT_FL_EDG_PIN0 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN1
+ @brief Falling Edge interrupt on Pin1
+*/
+#define INT_FL_EDG_PIN1 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN2
+ @brief Falling Edge interrupt on Pin2
+*/
+#define INT_FL_EDG_PIN2 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN3
+ @brief Falling Edge interrupt on Pin3
+*/
+#define INT_FL_EDG_PIN3 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN4
+ @brief Falling Edge interrupt on Pin4
+*/
+#define INT_FL_EDG_PIN4 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN5
+ @brief Falling Edge interrupt on Pin5
+*/
+#define INT_FL_EDG_PIN5 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN6
+ @brief Falling Edge interrupt on Pin6
+*/
+#define INT_FL_EDG_PIN6 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN7
+ @brief Falling Edge interrupt on Pin7
+*/
+#define INT_FL_EDG_PIN7 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN8
+ @brief Falling Edge interrupt on Pin8
+*/
+#define INT_FL_EDG_PIN8 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN9
+ @brief Falling Edge interrupt on Pin9
+*/
+#define INT_FL_EDG_PIN9 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN10
+ @brief Falling Edge interrupt on Pin10
+*/
+#define INT_FL_EDG_PIN10 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_EDG_PIN11
+ @brief Falling Edge interrupt on Pin11
+*/
+#define INT_FL_EDG_PIN11 (0x0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN0
+ @brief Rising Edge interrupt on Pin0
+*/
+#define INT_RS_EDG_PIN0 (0x1)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN1
+ @brief Rising Edge interrupt on Pin1
+*/
+#define INT_RS_EDG_PIN1 (0x10)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN2
+ @brief Rising Edge interrupt on Pin2
+*/
+#define INT_RS_EDG_PIN2 (0x100)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN3
+ @brief Rising Edge interrupt on Pin3
+*/
+#define INT_RS_EDG_PIN3 (0x1000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN4
+ @brief Rising Edge interrupt on Pin4
+*/
+#define INT_RS_EDG_PIN4 (0x10000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN5
+ @brief Rising Edge interrupt on Pin5
+*/
+#define INT_RS_EDG_PIN5 (0x100000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN6
+ @brief Rising Edge interrupt on Pin6
+*/
+#define INT_RS_EDG_PIN6 (0x1000000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN7
+ @brief Rising Edge interrupt on Pin7
+*/
+#define INT_RS_EDG_PIN7 (0x10000000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN8
+ @brief Rising Edge interrupt on Pin8
+*/
+#define INT_RS_EDG_PIN8 ((0x100000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN9
+ @brief Rising Edge interrupt on Pin9
+*/
+#define INT_RS_EDG_PIN9 ((0x1000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN10
+ @brief Rising Edge interrupt on Pin10
+*/
+#define INT_RS_EDG_PIN10 ((0x10000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_RS_EDG_PIN11
+ @brief Rising Edge interrupt on Pin11
+*/
+#define INT_RS_EDG_PIN11 ((0x100000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN0
+ @brief Low Level Interrupt on Pin0
+*/
+#define INT_LVL_LO_PIN0 (0x2)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN1
+ @brief Low Level Interrupt on Pin1
+*/
+#define INT_LVL_LO_PIN1 (0x20)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN2
+ @brief Low Level Interrupt on Pin2
+*/
+#define INT_LVL_LO_PIN2 (0x200)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN3
+ @brief Low Level Interrupt on Pin3
+*/
+#define INT_LVL_LO_PIN3 (0x2000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN4
+ @brief Low Level Interrupt on Pin4
+*/
+#define INT_LVL_LO_PIN4 (0x20000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN5
+ @brief Low Level Interrupt on Pin5
+*/
+#define INT_LVL_LO_PIN5 (0x200000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN6
+ @brief Low Level Interrupt on Pin6
+*/
+#define INT_LVL_LO_PIN6 (0x2000000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN7
+ @brief Low Level Interrupt on Pin7
+*/
+#define INT_LVL_LO_PIN7 (0x20000000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN8
+ @brief Low Level Interrupt on Pin8
+*/
+#define INT_LVL_LO_PIN8 ((0x200000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN9
+ @brief Low Level Interrupt on Pin9
+*/
+#define INT_LVL_LO_PIN9 ((0x2000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN10
+ @brief Low Level Interrupt on Pin10
+*/
+#define INT_LVL_LO_PIN10 ((0x20000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_LO_PIN11
+ @brief Low Level Interrupt on Pin11
+*/
+#define INT_LVL_LO_PIN11 ((0x200000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN0
+ @brief High Level Interrupt on Pin0
+*/
+#define INT_LVL_HI_PIN0 (0x3)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN1
+ @brief High Level Interrupt on Pin1
+*/
+#define INT_LVL_HI_PIN1 (0x30)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN2
+ @brief High Level Interrupt on Pin2
+*/
+#define INT_LVL_HI_PIN2 (0x300)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN3
+ @brief High Level Interrupt on Pin3
+*/
+#define INT_LVL_HI_PIN3 (0x3000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN4
+ @brief High Level Interrupt on Pin4
+*/
+#define INT_LVL_HI_PIN4 (0x30000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN5
+ @brief High Level Interrupt on Pin5
+*/
+#define INT_LVL_HI_PIN5 (0x300000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN6
+ @brief High Level Interrupt on Pin6
+*/
+#define INT_LVL_HI_PIN6 (0x3000000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN7
+ @brief High Level Interrupt on Pin7
+*/
+#define INT_LVL_HI_PIN7 (0x30000000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN8
+ @brief High Level Interrupt on Pin8
+*/
+#define INT_LVL_HI_PIN8 ((0x300000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN9
+ @brief High Level Interrupt on Pin9
+*/
+#define INT_LVL_HI_PIN9 ((0x3000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN10
+ @brief High Level Interrupt on Pin10
+*/
+#define INT_LVL_HI_PIN10 ((0x30000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_LVL_HI_PIN11
+ @brief High Level Interrupt on Pin11
+*/
+#define INT_LVL_HI_PIN11 ((0x300000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN0
+ @brief Falling and rising Edge on Pin0
+*/
+#define INT_FL_RS_EDG_PIN0 (0x4)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN1
+ @brief Falling and rising Edge on Pin1
+*/
+#define INT_FL_RS_EDG_PIN1 (0x40)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN2
+ @brief Falling and rising Edge on Pin2
+*/
+#define INT_FL_RS_EDG_PIN2 (0x400)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN3
+ @brief Falling and rising Edge on Pin3
+*/
+#define INT_FL_RS_EDG_PIN3 (0x4000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN4
+ @brief Falling and rising Edge on Pin4
+*/
+#define INT_FL_RS_EDG_PIN4 (0x40000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN5
+ @brief Falling and rising Edge on Pin5
+*/
+#define INT_FL_RS_EDG_PIN5 (0x400000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN6
+ @brief Falling and rising Edge on Pin6
+*/
+#define INT_FL_RS_EDG_PIN6 (0x4000000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN7
+ @brief Falling and rising Edge on Pin7
+*/
+#define INT_FL_RS_EDG_PIN7 (0x40000000)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN8
+ @brief Falling and rising Edge on Pin8
+*/
+#define INT_FL_RS_EDG_PIN8 ((0x400000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN9
+ @brief Falling and rising Edge on Pin9
+*/
+#define INT_FL_RS_EDG_PIN9 ((0x4000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN10
+ @brief Falling and rising Edge on Pin10
+*/
+#define INT_FL_RS_EDG_PIN10 ((0x40000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def INT_FL_RS_EDG_PIN11
+ @brief Falling and rising Edge on Pin11
+*/
+#define INT_FL_RS_EDG_PIN11 ((0x400000000000ULL))
+
+/*! @ingroup GPIO_InterfaceLayer
+
+ @def GPIO_MAX_PINS_MASK
+ @brief Mask used for all pins.
+*/
+#define GPIO_MAX_PINS_MASK (0xFFF)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def GPIO_NUM_PORT_MAX
+ @brief Maximum number of ports.
+*/
+#define GPIO_NUM_PORT_MAX (0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def GPIO_NUM_PINS
+ @brief Specifies number of GPIO PINS
+*/
+#define GPIO_NUM_PINS (12)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def GPIO_IN
+ @brief Specifies GPIO input mode.
+*/
+#define GPIO_IN (0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def GPIO_OUT
+ @brief Specifies GPIO output mode.
+*/
+#define GPIO_OUT (1)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def GPIO_HIGH
+ @brief Specifies GPIO HIGH level.
+*/
+#define GPIO_HIGH (1)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def GPIO_LOW
+ @brief Specifies GPIO LOW level.
+*/
+#define GPIO_LOW (0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_SUCCESS
+ @brief Specifies GPIO SUCCESS STATUS CODE
+*/
+#define IOH_GPIO_SUCCESS (0)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def IOH_GPIO_FAIL
+ @brief Specifies GPIO ERROR STATUS CODE
+*/
+#define IOH_GPIO_FAIL (-1)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def BIT_MASK_16
+ @brief Mask for 16 bits
+*/
+#define BIT_MASK_16 (0xFFFF)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def BIT_MASK_8
+ @brief Mask for 8 bits
+*/
+#define BIT_MASK_8 (0xFF)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def BIT_MASK_12
+ @brief Mask for 12 bits
+*/
+#define BIT_MASK_12 (0xFFF)
+
+/*! @ingroup GPIO_InterfaceLayer
+ @def BIT_MASK_32
+ @brief Maks value for 32 bits.
+*/
+#define BIT_MASK_32 (0xFFFFFFFF)
+
+/*structures*/
+/*! @ingroup GPIO_InterfaceLayer
+@struct ioh_gpio_reqt
+@brief This structure specifies information such the GPIO port, pins,
+ interrupt and direction
+ mode details associated with a user request. The GPIO port
+ status is also returned to
+ the user using this structure.
+@see
+ - ioh_gpio_int_mode
+ - ioh_gpio_dir_mode
+ - ioh_gpio_read
+ - ioh_gpio_write
+*/
+struct ioh_gpio_reqt {
+ unsigned long port; /**< Specifies the port. */
+ unsigned long pins; /**< Specifies the pins. */
+ unsigned long long mode;/**< Specifies the direction/interrupt mode.*/
+ unsigned long enable; /**< Interrupt enable/disable. */
+};
+
+extern s32 ioh_gpio_opencount;
+extern spinlock_t ioh_gpio_lock;
+extern const struct file_operations ioh_gpio_fops;
+
+/* exported function prototypes*/
+/*! @ingroup GPIO_InterfaceLayerAPI
+@fn int ioh_gpio_open( struct inode *inode,struct file *file )
+@brief This function is invoked when a process opens the device node
+*/
+int ioh_gpio_open(struct inode *inode, struct file *file);
+
+/*! @ingroup GPIO_InterfaceLayerAPI
+@fn int ioh_gpio_release(struct inode *inode,struct file *file)
+@brief This function is invoked when a process closes the device node
+*/
+int ioh_gpio_release(struct inode *inode, struct file *file);
+
+/*! @ingroup GPIO_InterfaceLayerAPI
+@fn int ioh_gpio_ioctl(struct inode * inode,struct file * file,unsigned int cmd,
+ unsigned long arg)
+@brief This function is registered at the driver initialization point
+ (module_init)
+ and invoked when user process invokes an ioctl call on the device.
+*/
+int ioh_gpio_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg);
+
+/* global variables*/
+extern u32 ioh_gpio_base_address; /* base address*/
+extern u32 ioh_gpio_irq; /* irq number*/
+extern s32 ioh_gpio_suspended; /* suspend status*/
+
+#endif
diff -urN linux-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_pci.c topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_pci.c
--- linux-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_pci.c 1970-01-01 09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/gpio/pch_gpio/pch_gpio_pci.c 2010-04-01 10:58:31.000000000 +0900
@@ -0,0 +1,537 @@
+/*!
+ * @file ioh_gpio_pci.c
+ * @brief Provides all the implementation of the interfaces pertaining to the
+ * pci and gpio registrations.
+ * @version 0.92
+ * @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 01/05/2010
+ * Added the interfaces provided by the gpio module.
+ *
+ */
+/*includes*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+
+#include "pch_common.h"
+#include "pch_debug.h"
+#include "pch_gpio_main.h"
+#include "pch_gpio_hal.h"
+
+/*macros*/
+/*! @ingroup GPIO_PCILayer
+ @def PCI_VENDOR_ID_IOH
+ @brief Outlines the PCI Vendor ID.
+*/
+#define PCI_VENDOR_ID_IOH (0x10DB)
+
+/*! @ingroup GPIO_PCILayer
+ @def PCI_DEVICE_ID_GE_GPIO
+ @brief Outlines the PCI Device ID for IOH GPIO.
+*/
+/* #define PCI_DEVICE_ID_GE_GPIO (0x8000)*/
+#define PCI_DEVICE_ID_GE_GPIO (0x8803) /* OKISEMI for LSI */
+
+/*! @ingroup GPIO_PCILayer
+ @def PCI_DEVICE_ID_MP_GPIO
+ @brief Outlines the PCI Device ID for MP GPIO.
+*/
+#define PCI_DEVICE_ID_MP_GPIO (0x8004)
+
+/*! @ingroup GPIO_PCILayer
+ @def PCI_DEVICE_ID_IVI_GPIO
+ @brief Outlines the PCI Device ID for IVI GPIO.
+*/
+#define PCI_DEVICE_ID_IVI_GPIO (0x8001)
+
+/*! @ingroup GPIO_PCILayer
+ @def IOH_MINOR_NOS
+ @brief Outlines the GPIO minor number limit.
+*/
+#define IOH_MINOR_NOS (1)
+
+/* Global variables*/
+u32 ioh_gpio_base_address;
+u32 ioh_gpio_irq;
+s32 ioh_gpio_suspended;
+
+/* Major number allocation via module parameter */
+static dev_t ioh_gpio_dev_no;
+static int ioh_gpio_major_no;
+static struct cdev ioh_gpio_dev;
+
+u32 ioh_gpio_bit_mask;
+
+/*! @ingroup GPIO_PCILayerAPI
+ @fn static s32 __devinit ioh_gpio_probe
+ (struct pci_dev* ioh_pci_dev,
+ const struct pci_device_id* pci_id)
+ @brief Provides the functionality of probing the module.
+*/
+static int __devinit ioh_gpio_probe(struct pci_dev *pdev, const
+ struct pci_device_id *id);
+
+/*! @ingroup GPIO_PCILayerAPI
+ @fn static void __devexit ioh_gpio_remove
+ (struct pci_dev * ioh_pci_dev)
+ @brief Provides the functionality of removing the module.
+*/
+static void __devexit ioh_gpio_remove(struct pci_dev *pdev);
+
+/*! @ingroup GPIO_PCILayerAPI
+ @fn static s32 ioh_gpio_suspend(struct pci_dev* pDev,
+ pm_message_t state)
+ @brief Provides the functionality of suspending the module.
+*/
+static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state);
+
+/*! @ingroup GPIO_PCILayerAPI
+ @fn static s32 ioh_gpio_resume(struct pci_dev* pDev)
+ @brief Provides the functionalities of resuming the module.
+*/
+static int ioh_gpio_resume(struct pci_dev *pdev);
+
+/*structures*/
+/*! @ingroup GPIO_PCILayerFacilitators
+@static struct pci_device_id
+@brief It is a structure used for preserving information related to the
+ device id.
+@note
+The concerned details should be provided as a reference in the pci driver
+structure.
+
+@see
+ - ioh_gpio_driver
+
+*/
+static struct pci_device_id ioh_gpio_pcidev_id[] = {
+
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_GE_GPIO)},
+ {PCI_DEVICE(PCI_VENDOR_ID_IOH, PCI_DEVICE_ID_MP_GPIO)},
+ {PCI_DEVICE(PCI_VENDOR_ID_IOH, PCI_DEVICE_ID_IVI_GPIO)},
+ {0,}
+};
+
+/*! @ingroup GPIO_PCILayerFacilitators
+@struct ioh_gpio_driver
+@brief This structure specifies the pci driver methods pertaining to
+ GPIO module.
+@see
+ - ioh_gpio_pci_init
+ - ioh_gpio_pci_exit
+*/
+static struct pci_driver ioh_gpio_driver = {
+ .name = "ioh_gpio_empty",
+ .id_table = ioh_gpio_pcidev_id,
+ .probe = ioh_gpio_probe,
+ .remove = __devexit_p(ioh_gpio_remove),
+#ifdef CONFIG_PM
+ .suspend = ioh_gpio_suspend, /* OKISEMI for PM bug fix */
+ .resume = ioh_gpio_resume /* OKISEMI for PM bug fix */
+#endif
+};
+
+/*! @ingroup GPIO_PCILayerAPI
+ @fn static int __init ioh_gpio_pci_init(void)
+ @brief Provides the functionality of initializing the module
+*/
+static int __init ioh_gpio_pci_init(void);
+/*! @ingroup GPIO_PCILayerAPI
+ @fn static void __exit ioh_gpio_pci_exit(void)
+ @brief Provides the functionality of exiting the module
+*/
+static void __exit ioh_gpio_pci_exit(void);
+
+MODULE_DESCRIPTION("IOH GPIO PCI Driver");
+MODULE_LICENSE("GPL");
+module_init(ioh_gpio_pci_init);
+module_exit(ioh_gpio_pci_exit);
+module_param(ioh_gpio_major_no, int, S_IRUSR | S_IWUSR);
+
+/*function implementations*/
+
+/*! @ingroup GPIO_PCILayerAPI
+@fn static int __init ioh_gpio_pci_init(void)
+@remarks Implements the initialization functionality of the module.
+ The main task performed by this function is:
+ - Register the module as PCI Driver.
+
+@param None
+@retval int
+ - @ref IOH_GPIO_SUCCESS --> Loading successful.
+ - -EEXIST --> pci_register_driver failed.
+ - -EINVAL --> pci_register_driver failed.
+ - -ENOMEM --> pci_register_driver failed.
+*/
+static int __init ioh_gpio_pci_init(void)
+{
+ s32 ret;
+ ret = pci_register_driver(&ioh_gpio_driver);
+ IOH_DEBUG
+ ("ioh_gpio_pci_init : Invoked pci_register_driver successfully\n");
+ IOH_DEBUG("ioh_gpio_pci_init returns -%d\n", ret);
+ return ret;
+}
+
+/*! @ingroup GPIO_PCILayerAPI
+ @fn static void __exit ioh_gpio_pci_exit(void)
+ @remarks Implements the exit functionality of the module.
+ The main task performed by this function is:
+ - Un-register the module as a PCI Driver.
+
+ @param None
+ @retval None
+*/
+static void __exit ioh_gpio_pci_exit(void)
+{
+ pci_unregister_driver(&ioh_gpio_driver);
+ IOH_DEBUG
+ ("ioh_gpio_pci_exit : Invoked pci_unregister_driver\
+ successfully\n");
+}
+
+/*! @ingroup GPIO_PCILayerAPI
+@fn static int __devinit ioh_gpio_probe(struct pci_dev* pdev,
+ const struct pci_device_id* id)
+@remarks Implements the probe functionality of the module.
+ This function is invoked
+ when a PCI device with the Vendor and Device ID supported by this module
+ is detected. The main tasks performed by this function are:
+ - Enables the device.
+ - Acquires the device resources and the remapped base address of
+ the device.
+ - Registers a character device driver for the user space application
+ to interact with the system.
+ - Registers the callback function.
+@note This function is invoked by the Kernel subsystem when a PCI device
+ with a supported vendor ID and Device ID is detected.
+
+@param pdev [@ref INOUT] Contains the reference of the pci_dev structure
+@param id [@ref IN] Contains the reference of the pci_device_id structure
+@retval int
+ - @ref IOH_GPIO_SUCCESS --> Operation successful.
+ - -EIO --> pci_enable_device error status code.
+ - -EINVAL --> pci_enable_device error status code.
+ - -EBUSY --> pci_request_regions/ alloc_chrdev_region
+ error status code.
+ - -ENOMEM --> pci_iomap/alloc_chrdev_region/cdev_add
+ error status code.
+
+@see
+ - ioh_gpio_driver
+*/
+static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+
+ char *DRIVER_NAME = "ioh_gpio";
+ int ret;
+ ioh_gpio_bit_mask =
+ (pdev->device ==
+ PCI_DEVICE_ID_IVI_GPIO) ? BIT_MASK_16 : BIT_MASK_12;
+ IOH_DEBUG("ioh_gpio_probe : The value of ioh_gpio_bit_mask is: %x\n",
+ ioh_gpio_bit_mask);
+
+ ioh_gpio_major_no = (ioh_gpio_major_no < 0
+ || ioh_gpio_major_no >
+ 254) ? 0 : ioh_gpio_major_no;
+
+ do {
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ IOH_LOG(KERN_ERR,
+ "\nioh_gpio_probe : pci_enable_device FAILED");
+ break;
+ }
+ IOH_DEBUG("ioh_gpio_probe : pci_enable_device returns %d\n",
+ ret);
+
+ ret = pci_request_regions(pdev, DRIVER_NAME);
+ if (ret) {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_probe : pci_request_regions FAILED");
+ pci_disable_device(pdev);
+ break;
+ }
+ IOH_DEBUG("ioh_gpio_probe : pci_request_regions returns %d\n",
+ ret);
+
+ ioh_gpio_base_address = (unsigned long)pci_iomap(pdev, 1, 0);
+
+ if (ioh_gpio_base_address == 0) {
+ IOH_LOG(KERN_ERR, "ioh_gpio_probe : pci_iomap FAILED");
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ ret = -ENOMEM;
+ break;
+ }
+
+ IOH_DEBUG
+ ("ioh_gpio_probe : pci_iomap SUCCESS and value in\
+ ioh_gpio_base_address"
+ "variable is %d\n", ioh_gpio_base_address);
+
+ if (ioh_gpio_major_no) {
+ ioh_gpio_dev_no = MKDEV(ioh_gpio_major_no, 0);
+ ret =
+ register_chrdev_region(ioh_gpio_dev_no,
+ IOH_MINOR_NOS, DRIVER_NAME);
+ if (ret) {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_probe : register_chrdev_\
+ region FAILED");
+ pci_iounmap(pdev,
+ (void *)ioh_gpio_base_address);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ break;
+ }
+ IOH_DEBUG
+ ("ioh_gpio_probe : register_chrdev_region\
+ returns %d\n",
+ ret);
+ } else {
+ ret =
+ alloc_chrdev_region(&ioh_gpio_dev_no, 0,
+ IOH_MINOR_NOS, DRIVER_NAME);
+ if (ret) {
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_probe : alloc_chrdev_region\
+ FAILED");
+ pci_iounmap(pdev,
+ (void *)ioh_gpio_base_address);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ break;
+ }
+ IOH_DEBUG
+ ("ioh_gpio_probe : alloc_chrdev_region\
+ returns %d\n",
+ ret);
+ }
+
+ cdev_init(&ioh_gpio_dev, &ioh_gpio_fops);
+ IOH_DEBUG("ioh_gpio_probe : cdev_init invoked successfully\n");
+
+ ioh_gpio_dev.owner = THIS_MODULE;
+ ioh_gpio_dev.ops = &ioh_gpio_fops;
+
+ ret = cdev_add(&ioh_gpio_dev, ioh_gpio_dev_no, IOH_MINOR_NOS);
+ if (ret) {
+ IOH_LOG(KERN_ERR, "ioh_gpio_probe : cdev_add FAILED");
+ unregister_chrdev_region(ioh_gpio_dev_no,
+ IOH_MINOR_NOS);
+ pci_iounmap(pdev, (void *)ioh_gpio_base_address);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ break;
+ }
+ IOH_DEBUG("ioh_gpio_probe : cdev_add returns- %d\n", ret);
+
+ ioh_gpio_cb_register(ioh_gpio_cb);
+ ioh_gpio_irq = pdev->irq;
+ IOH_DEBUG("ioh_gpio_probe returns %d\n", IOH_GPIO_SUCCESS);
+ device_set_wakeup_enable(&pdev->dev, 1);
+ return IOH_GPIO_SUCCESS;
+ } while (0);
+ IOH_DEBUG("ioh_gpio_probe returns %d\n", ret);
+ return ret;
+}
+
+/*! @ingroup GPIO_PCILayerAPI
+@fn static void __devexit ioh_gpio_remove(struct pci_dev * pdev)
+@remarks Implements the remove functionality of the module.
+The main tasks performed by this function are:
+-Disables the interrupts by invoking @ref ioh_gpio_int_mode API.
+-Removes the device from the system using cdev_del API
+-Un-registers the char device number by invoking unregister_chrdev_region API.
+-Releases the IO memory using pci_iounmap API
+-Releases the resources acquired using pci_release_regions API
+-Disables the pci device using pci_disable_device API
+
+@param pdev [@ref INOUT] Contains the reference of the pci_dev structure
+@retval None
+@see
+ - ioh_gpio_driver
+*/
+static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
+{
+
+ struct ioh_gpio_reqt req;
+ memset(&req, 0, sizeof(req));
+ req.pins = IOH_GPIO_ALL_PINS;
+ /* disable interrupts for all gpio pins */
+ (void)ioh_gpio_int_mode(&req);
+
+ cdev_del(&ioh_gpio_dev);
+ IOH_DEBUG("ioh_gpio_remove - cdev_del Invoked successfully\n");
+
+ unregister_chrdev_region(ioh_gpio_dev_no, IOH_MINOR_NOS);
+ IOH_DEBUG
+ ("ioh_gpio_remove - unregister_chrdev_region Invoked\
+ successfully\n");
+
+ pci_iounmap(pdev, (void *)ioh_gpio_base_address);
+
+ IOH_DEBUG("ioh_gpio_remove - pci_iounmap Invoked successfully\n");
+
+ pci_release_regions(pdev);
+ IOH_DEBUG
+ ("ioh_gpio_remove - pci_release_regions Invoked successfully\n");
+
+ pci_disable_device(pdev);
+ IOH_DEBUG
+ ("ioh_gpio_remove - pci_disable_device Invoked successfully\n");
+
+}
+
+#ifdef CONFIG_PM
+
+/*! @ingroup GPIO_PCILayerAPI
+@fn static s32 ioh_gpio_suspend(struct pci_dev* pdev,pm_message_t state)
+@remarks Implements the suspend functionality of the module. The main
+tasks performed by this function are:
+- Saves the current pin configuration by invoking
+ @ref ioh_gpio_save_reg_conf API.
+- Invokes pci_enable_wake with the enable parameter as 0,
+ so as to ensure that the device has its "wake" ability disabled
+- Saves the current state by invoking pci_save_state API.
+ If it fails then return with its error code.
+- Disables PCI device by invoking pci_disable_device API.
+- Sets the power state to low power mode by invoking
+ pci_set_power_state API and return @ref IOH_GPIO_SUCCESS status code.
+
+@param pdev [@ref INOUT] Contains the reference of the pci_dev structure
+@param state [@ref INOUT] Contains the reference of the pm_message_t
+ structure
+@retval int
+ - @ref IOH_GPIO_SUCCESS --> Operation successful.
+ - -ENOMEM --> pci_save_state error status code.
+@see
+ - ioh_gpio_driver
+
+*/
+static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ int ret;
+
+ ioh_gpio_suspended = true; /* For blocking further IOCTLs */
+
+ ioh_gpio_save_reg_conf();
+ IOH_DEBUG
+ ("ioh_gpio_suspend - ioh_gpio_save_reg_conf Invoked successfully\n");
+ ioh_gpio_restore_reg_conf();
+
+ ret = pci_save_state(pdev);
+ if (ret) {
+ IOH_LOG(KERN_ERR,
+ " ioh_gpio_suspend -pci_save_state returns-%d\n", ret);
+ return ret;
+ }
+
+ IOH_DEBUG("ioh_gpio_suspend - pci_save_state returns %d\n", ret);
+
+ pci_disable_device(pdev);
+ IOH_DEBUG
+ ("ioh_gpio_suspend - pci_disable_device Invoked successfully\n");
+
+ pci_set_power_state(pdev, PCI_D0);
+ IOH_DEBUG
+ ("ioh_gpio_suspend - pci_set_power_state Invoked successfully\n");
+
+ ret = pci_enable_wake(pdev, PCI_D0, 1);
+ if (!ret) {
+ IOH_DEBUG
+ ("ioh_gpio_suspend - pci_enable_wake Invoked successfully\n");
+ } else {
+ IOH_DEBUG("ioh_gpio_suspend - pci_enable_wake failed\n");
+ }
+ IOH_LOG(KERN_ERR, "ioh_gpio_suspend - return %d\n", IOH_GPIO_SUCCESS);
+
+ return IOH_GPIO_SUCCESS;
+}
+
+/*! @ingroup GPIO_PCILayerAPI
+@fn static s32 ioh_gpio_resume(struct pci_dev* pdev)
+@remarks Implements the resume functionality of the module. The main
+tasks performed by this function are:
+-Changes the power state of the device to D0 using pci_set_power_state API.
+-Invokes pci_restore_state API to restore the PCI register state
+-Invokes pci_enable_device API to enable the PCI device.
+If it fails, then return its error code.
+-To ensure that the device has its "wake" ability disabled,
+invokes pci_enable_wake with the enable parameter as 0
+-Invokes @ref ioh_gpio_restore_reg_conf API to restore the GPIO register
+configuration values and returns @ref IOH_GPIO_SUCCESS status code.
+
+@param pdev [@ref INOUT] Contains the reference of the pci_dev structure
+@retval int
+ - @ref IOH_GPIO_SUCCESS --> Operation successful.
+ - -EIO --> pci_enable_device error status code.
+ - -EINVAL --> pci_enable_device error status code.
+
+@see
+ - ioh_gpio_driver
+
+*/
+static int ioh_gpio_resume(struct pci_dev *pdev)
+{
+
+ int ret;
+
+ ret = pci_enable_wake(pdev, PCI_D0, 0);
+ IOH_LOG(KERN_ERR,
+ "ioh_gpio_resume - pci_set_power_state Invoked successfully\n");
+
+ pci_set_power_state(pdev, PCI_D0);
+ IOH_DEBUG
+ ("ioh_gpio_resume - pci_set_power_state Invoked successfully\n");
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ IOH_LOG(KERN_ERR, "ioh_gpio_resume-pci_enable_device failed ");
+ return ret;
+ }
+
+ IOH_DEBUG("ioh_gpio_resume - pci_enable_device returns -%d\n", ret);
+
+ pci_restore_state(pdev);
+ IOH_DEBUG("ioh_gpio_resume - pci_restore_state Invoked successfully\n");
+
+ ioh_gpio_writereg(0x3c, 0x00000001); /*reset*/
+ ioh_gpio_writereg(0x3c, 0x00000000);
+ ioh_gpio_restore_reg_conf();
+ ioh_gpio_suspended = false;
+
+ IOH_DEBUG("ioh_gpio_resume returns- %d\n", IOH_GPIO_SUCCESS);
+ return IOH_GPIO_SUCCESS;
+}
+
+#endif