diff options
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-gpio.patch')
-rw-r--r-- | meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-gpio.patch | 2700 |
1 files changed, 2700 insertions, 0 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-gpio.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-gpio.patch new file mode 100644 index 0000000000..c57f949078 --- /dev/null +++ b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-pch-gpio.patch @@ -0,0 +1,2700 @@ + + +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 |