mirror of
https://git.yoctoproject.org/poky
synced 2026-02-24 18:39:40 +01:00
2701 lines
78 KiB
Diff
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
|