[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <4C80D3C8.9020204@dsn.okisemi.com>
Date: Fri, 03 Sep 2010 19:54:00 +0900
From: Masayuki Ohtak <masa-korg@....okisemi.com>
To: meego-dev@...go.com, Andrew Morton <akpm@...ux-foundation.org>,
Samuel Ortiz <sameo@...ux.intel.com>,
Mark Brown <broonie@...nsource.wolfsonmicro.com>,
Randy Dunlap <randy.dunlap@...cle.com>,
Alek Du <alek.du@...el.com>,
Richard Röjfors
<richard.rojfors@...ean-labs.com>,
Mike Frysinger <vapier@...too.org>,
linux-kernel@...r.kernel.org
CC: qi.wang@...el.com, andrew.chih.howe.khor@...el.com,
arjan@...ux.intel.com, gregkh@...e.de, yong.y.wang@...el.com,
Tomoya MORINAGA <morinaga526@....okisemi.com>
Subject: [MeeGo-Dev][PATCH] Topcliff: Update PCH_GPIO driver to 2.6.35
GPIO driver of Topcliff PCH
Topcliff PCH is the platform controller hub that is going to be used in
Intel's upcoming general embedded platform. All IO peripherals in
Topcliff PCH are actually devices sitting on AMBA bus.
Topcliff PCH has GPIO I/F. Using this I/F, it is able to access system
devices connected to GPIO.
Signed-off-by: Masayuki Ohtake <masa-korg@....okisemi.com>
---
drivers/gpio/Kconfig | 8 +
drivers/gpio/Makefile | 1 +
drivers/gpio/pch_gpio.c | 901 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/gpio/pch_gpio.h | 245 +++++++++++++
4 files changed, 1155 insertions(+), 0 deletions(-)
create mode 100644 drivers/gpio/pch_gpio.c
create mode 100644 drivers/gpio/pch_gpio.h
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 7face91..76701f6 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -113,6 +113,14 @@ config GPIO_SCH
comment "I2C GPIO expanders:"
+config PCH_GPIO
+ tristate "PCH GPIO"
+ depends on PCI
+ help
+ This driver is for PCH GPIO of Topcliff which is an IOH for x86
+ embedded processor.
+ This driver can access PCH GPIO device.
+
config GPIO_MAX7300
tristate "Maxim MAX7300 GPIO expander"
depends on I2C
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index e53dcff..eda01b6 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -35,3 +35,4 @@ obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o
obj-$(CONFIG_GPIO_SCH) += sch_gpio.o
obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o
obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o
+obj-$(CONFIG_PCH_GPIO) += pch_gpio.o
diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/pch_gpio.c
new file mode 100644
index 0000000..4cf8fc0
--- /dev/null
+++ b/drivers/gpio/pch_gpio.c
@@ -0,0 +1,901 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * 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.
+ */
+#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 <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+#include "pch_gpio.h"
+
+static void (*pch_gpio_cbr) (u32, struct pch_gpio_chip *);
+static DEFINE_MUTEX(pch_gpio_mutex);
+static s32 pch_gpio_major_no;
+
+/**
+ * pch_gpio_cb_register() - his function registers the callback function used
+ * by the gpio module
+ * @pch_gpio_ptr: Pointer to callback function.
+ */
+static void pch_gpio_cb_register(
+ void (*pch_gpio_ptr) (u32, struct pch_gpio_chip *),
+ struct pch_gpio_chip *chip)
+{
+ if (pch_gpio_ptr != NULL) {
+ init_waitqueue_head(&chip->pch_gpio_event);
+ pch_gpio_cbr = pch_gpio_ptr;
+ }
+}
+
+/**
+ * pch_gpio_int_mode - Implements the functionality of disabling or
+ * enabling interrupts.
+ * @gpio_reqt: Contains the reference of the pch_gpio_reqt structure
+ */
+static s32 pch_gpio_int_mode(struct pch_gpio_reqt *gpio_reqt,
+ struct pch_gpio_chip *chip)
+{
+ u32 pch_pins;
+ u32 i;
+ u32 ien_val;
+ u64 temp;
+ u64 mode_val;
+
+ /* initialize locals */
+ pch_pins = gpio_reqt->pins;
+ ien_val = ioread32(&chip->reg->ien);
+
+ /* Disable applicable bits in IEN register */
+ ien_val &= (~pch_pins);
+ iowrite32(ien_val, &chip->reg->ien);
+ dev_dbg(chip->dev, "%s wrote %x to ien\n", __func__, ien_val);
+
+ /* Reading the modes of all the 12 pins. */
+ mode_val = (((u64) ioread32(&chip->reg->im1)) << BITS_32) |
+ (ioread32(&chip->reg->im0));
+
+ /* enable interrupts */
+ if (gpio_reqt->enable == 1) {
+ dev_dbg(chip->dev, "%s Enabling interrupts\n", __func__);
+
+ for (i = 0; i < GPIO_NUM_PINS; i++) {
+ /*GPIO_NUM_PINS = max num. pins for the GPIO port. */
+ if (pch_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)) {
+ dev_err(chip->dev,
+ "%s Invalid mode selection for "
+ "pin %d\n", __func__, i);
+ return -EINVAL;
+ }
+ dev_dbg(chip->dev,
+ "%s : Interrupt enabled for pin %d\n",
+ __func__, i);
+ } else {
+ dev_dbg(chip->dev,
+ "%s : Interrupt not enabled for pin %d\n",
+ __func__, i);
+ }
+ }
+ /* Set the mode register IM0 */
+ iowrite32(((u32) (mode_val & BIT_MASK_32)), &chip->reg->im0);
+ dev_dbg(chip->dev, "%s wrote %x to im0\n", __func__,
+ ((u32) (mode_val & BIT_MASK_32)));
+
+ /* Set the mode register IM1 */
+ iowrite32(((u32) (mode_val >> BITS_32)), &chip->reg->im1);
+ dev_dbg(chip->dev, "%s wrote %x to im1\n", __func__,
+ ((u32) (mode_val >> BITS_32)));
+
+ /* Clear the status */
+ iowrite32(pch_pins, &chip->reg->iclr);
+ dev_dbg(chip->dev, "%s wrote %x to iclr\n", __func__,
+ pch_pins);
+ dev_dbg(chip->dev, "%s value in to istatus %x\n", __func__,
+ ioread32(&chip->reg->istatus));
+
+ /* Clear the mask register */
+ iowrite32(pch_pins, &chip->reg->imaskclr);
+ dev_dbg(chip->dev, "%s wrote %x to imaskclr\n", __func__,
+ pch_pins);
+
+ ien_val |= pch_pins;
+
+ /*Enable applicable bits in IEN register */
+ iowrite32(ien_val, &chip->reg->ien);
+ dev_dbg(chip->dev, "%s wrote %x to ien\n", __func__, ien_val);
+
+ }
+
+ /* disable interrupts */
+ else {
+ dev_dbg(chip->dev, "%s Disabling interrupts\n", __func__);
+ /* Clear the status */
+ iowrite32(pch_pins, &chip->reg->iclr);
+ dev_dbg(chip->dev, "%s wrote %x to iclr\n", __func__,
+ pch_pins);
+
+ /* Set the mask register */
+ iowrite32(pch_pins, &chip->reg->imask);
+ dev_dbg(chip->dev, "%s wrote %x to PCH_IMASK\n", __func__,
+ pch_pins);
+
+ /* IEN bits are already disabled initially */
+
+ }
+ dev_dbg(chip->dev, "%s returning=%d\n", __func__, 0);
+ return 0;
+}
+
+/**
+ * pch_gpio_dir_mode - Implements the functionalities for setting GPIO pin
+ * directions[input/output].
+ * @gpio_reqt: Contains the reference of the pch_gpio_reqt structure
+ */
+static void pch_gpio_dir_mode(struct pch_gpio_reqt *gpio_reqt,
+ struct pch_gpio_chip *chip)
+{
+ u32 pch_pm_regval;
+ u32 pch_pins;
+
+ pch_pm_regval = ioread32(&chip->reg->pm);
+ pch_pins = gpio_reqt->pins;
+
+ /* input mode */
+ if (gpio_reqt->mode == GPIO_IN) {
+ dev_dbg(chip->dev, "%s GPIO_IN\n", __func__);
+ pch_pm_regval &= (~pch_pins);
+ } else {
+ pch_pm_regval |= pch_pins;
+ dev_dbg(chip->dev, "%s GPIO_OUT\n", __func__);
+ }
+
+ iowrite32(pch_pm_regval, &chip->reg->pm);
+ dev_dbg(chip->dev, "%s wrote %x to pm\n", __func__, pch_pm_regval);
+}
+
+/**
+ * pch_gpio_read - Implements the register read functionality of the
+ * gpio module.
+ * @gpio_reqt: Contains the reference of the pch_gpio_reqt structure
+ */
+static inline s32 pch_gpio_read(struct pch_gpio_reqt *gpio_reqt,
+ struct pch_gpio_chip *chip)
+{
+ gpio_reqt->pins = chip->pch_gpio_bit_mask & ioread32(&chip->reg->pi);
+ return 0;
+}
+
+/**
+ * pch_gpio_write - Implements the register write functionality of
+ * the gpio module.
+ * @gpio_reqt: Contains the reference of the pch_gpio_reqt structure
+ */
+static inline s32 pch_gpio_write(struct pch_gpio_reqt *gpio_reqt,
+ struct pch_gpio_chip *chip)
+{
+ u32 reg_val;
+
+ reg_val = ioread32(&chip->reg->po);
+
+ if (gpio_reqt->mode == GPIO_LOW) {
+ reg_val &= ~(gpio_reqt->pins);
+ dev_dbg(chip->dev, "%s GPIO_LOW\n", __func__);
+ } else {
+ reg_val |= gpio_reqt->pins;
+ dev_dbg(chip->dev, "%s GPIO_HIGH\n", __func__);
+ }
+
+ iowrite32(reg_val, &chip->reg->po);
+ dev_dbg(chip->dev, "%s writing value=%x returning %d\n", __func__,
+ reg_val, 0);
+ return 0;
+}
+
+/**
+ * pch_gpio_handler - Implements the interrupt handler functionality of
+ * the gpio module.
+ * @irq: Contains the irq value
+ * @pData: Contains the reference to the base gpio address.
+ *
+ * Returns
+ * IRQ_HANDLED: If GPIO hardware is responsible for the interrupt.
+ * IRQ_NONE: Non-GPIO interrupt.
+ */
+static irqreturn_t pch_gpio_handler(s32 irq, void *pData)
+{
+ irqreturn_t ret = IRQ_NONE;
+ u32 pch_idisp_regval;
+ struct pch_gpio_chip *chip = (struct pch_gpio_chip *)pData;
+
+ pch_idisp_regval =
+ chip->pch_gpio_bit_mask & ioread32(&chip->reg->idisp);
+ if (pch_idisp_regval != 0) {
+ /*invoke the callback */
+ (*pch_gpio_cbr) (pch_idisp_regval, chip);
+ dev_dbg(chip->dev, "%s : "
+ "pch_gpio_cb invoked successfully %d\n", __func__, ret);
+
+ /*clear the interrupt */
+ dev_err(chip->dev, "Value at idisp8 = %x Value at pin8 = %x\n",
+ ioread32(&chip->reg->idisp),
+ ioread32(&chip->reg->pi) & 0x80);
+ iowrite32(pch_idisp_regval, &chip->reg->iclr);
+
+ ret = IRQ_HANDLED;
+ dev_dbg(chip->dev, "%s returns IRQ_HANDLED\n", __func__);
+ } else {
+ dev_dbg(chip->dev, "%s returns IRQ_NONE\n", __func__);
+ }
+ return ret;
+}
+
+/**
+ * pch_gpio_cb - The interrupt handler callback function.
+ * @value: Contains the value data
+ */
+static void pch_gpio_cb(u32 value, struct pch_gpio_chip *chip)
+{
+ /* update the event flag */
+ chip->pch_gpio_event_flag = value;
+
+ dev_dbg(chip->dev, "%s : "
+ "event flag value = %x\tIDISP register value = %x\n", __func__,
+ chip->pch_gpio_event_flag, ioread32(&chip->reg->idisp));
+ wake_up_interruptible(&chip->pch_gpio_event);
+}
+
+/*
+ Save register configuration and disable interrupts.
+ */
+static void pch_gpio_save_reg_conf(struct pch_gpio_chip *chip)
+{
+ dev_dbg(chip->dev, "%s ENTRY\n", __func__);
+ chip->pch_gpio_reg.ien_reg = ioread32(&chip->reg->ien);
+ chip->pch_gpio_reg.imask_reg = ioread32(&chip->reg->imask);
+ chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
+ chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
+ chip->pch_gpio_reg.im0_reg = ioread32(&chip->reg->im0);
+ chip->pch_gpio_reg.im1_reg = ioread32(&chip->reg->im1);
+
+ dev_dbg(chip->dev, "%s : ien=%x, imask=%x, po=%x,"
+ "pm=%x, im0=%x, im1=%x\n", __func__,
+ ioread32(&chip->reg->ien), ioread32(&chip->reg->imask),
+ ioread32(&chip->reg->po), ioread32(&chip->reg->pm),
+ ioread32(&chip->reg->im0), ioread32(&chip->reg->im1));
+
+ dev_dbg(chip->dev, "%s : pch_gpio_reg.ien_reg=%x, "
+ "pch_gpio_reg.imask_reg=%x, pch_gpio_reg.po_reg=%x, "
+ "pch_gpio_reg.pm_reg=%x, pch_gpio_reg.im0_reg=%x, "
+ "pch_gpio_reg.im1_reg=%x\n", __func__,
+ chip->pch_gpio_reg.ien_reg,
+ chip->pch_gpio_reg.imask_reg,
+ chip->pch_gpio_reg.po_reg, chip->pch_gpio_reg.pm_reg,
+ chip->pch_gpio_reg.im0_reg, chip->pch_gpio_reg.im1_reg);
+
+ /* Disable all gpio interrupts */
+ iowrite32(0, &chip->reg->ien);
+ dev_dbg(chip->dev, "%s disabled interrupts\n", __func__);
+}
+
+/*
+ *This function restores the register configuration of the GPIO device.
+ */
+static void pch_gpio_restore_reg_conf(struct pch_gpio_chip *chip)
+{
+ dev_dbg(chip->dev, "%s ENTRY\n", __func__);
+ /* to store contents of IEN register */
+ iowrite32(chip->pch_gpio_reg.ien_reg, &chip->reg->ien);
+ /* to store contents of IMASK register */
+ iowrite32(chip->pch_gpio_reg.imask_reg, &chip->reg->imask);
+ /* to store contents of IMASK register */
+ iowrite32(~chip->pch_gpio_reg.imask_reg, &chip->reg->imaskclr);
+ /* to store contents of PO register */
+ iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
+ /* to store contents of PM register */
+ iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
+ /* to store contents of IM0 register */
+ iowrite32(chip->pch_gpio_reg.im0_reg, &chip->reg->im0);
+ /* to store contents of IM1 register */
+ iowrite32(chip->pch_gpio_reg.im1_reg, &chip->reg->im1);
+
+ dev_dbg(chip->dev, "pch_gpio_save_reg_conf : pch_gpio_reg.ien_reg=%x, "
+ "pch_gpio_reg.imask_reg=%x, pch_gpio_reg.po_reg=%x, "
+ "pch_gpio_reg.pm_reg=%x, pch_gpio_reg.im0_reg=%x, "
+ "pch_gpio_reg.im1_reg=%x\n",
+ chip->pch_gpio_reg.ien_reg,
+ chip->pch_gpio_reg.imask_reg,
+ chip->pch_gpio_reg.po_reg, chip->pch_gpio_reg.pm_reg,
+ chip->pch_gpio_reg.im0_reg, chip->pch_gpio_reg.im1_reg);
+ dev_dbg(chip->dev, "pch_gpio_save_reg_conf : ien=%x, imask=%x, po=%x,"
+ "pm=%x, im0=%x, im1=%x\n",
+ ioread32(&chip->reg->ien), ioread32(&chip->reg->imask),
+ ioread32(&chip->reg->po), ioread32(&chip->reg->pm),
+ ioread32(&chip->reg->im0), ioread32(&chip->reg->im1));
+ dev_dbg(chip->dev, "%s enabled interrupts\n", __func__);
+}
+
+/**
+ * pch_gpio_open - This function is invoked when a process opens
+ * the device node
+ * @inode: Contains the reference of the inode structure
+ * @filep: Contains the reference of the file structure
+ *
+ * Returns
+ * 0: 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.
+ */
+static s32 pch_gpio_open(struct inode *inode, struct file *filep)
+{
+ s32 ret;
+ s32 err;
+ struct pch_gpio_chip *chip;
+
+ ret = mutex_lock_interruptible(&pch_gpio_mutex);
+ if (ret) {
+ err = -ERESTARTSYS;
+ goto return_err_nomutex;
+ }
+ dev_dbg(chip->dev, "%s : open count value = %d", __func__,
+ chip->pch_gpio_opencount);
+
+ chip = container_of(inode->i_cdev, struct pch_gpio_chip, pch_gpio_dev);
+ filep->private_data = chip;
+
+ if (chip->pch_gpio_opencount) {
+ dev_err(chip->dev, "%s : device already opened\n", __func__);
+ ret = -EBUSY;
+ } else {
+ ret = request_irq(chip->pch_gpio_irq, &pch_gpio_handler,
+ IRQF_SHARED, MODULE_NAME,
+ chip);
+ if (ret) {
+ dev_err(chip->dev,
+ "%s : request_irq failed\n", __func__);
+ } else {
+ chip->pch_gpio_opencount++;
+ dev_dbg(chip->dev,
+ "%s : request_irq invoked successfully\n", __func__);
+ ret = 0;
+ }
+ }
+
+ mutex_unlock(&pch_gpio_mutex);
+return_err_nomutex:
+ dev_dbg(chip->dev, "%s returns=%d\n", __func__, ret);
+ return ret;
+}
+
+/**
+ * pch_gpio_release - This function is invoked when a process closes
+ * the device node
+ * @inode: Contains the reference of the inode structure
+ * @filep: Contains the reference of the file structure
+ */
+static s32 pch_gpio_release(struct inode *inode, struct file *filep)
+{
+ struct pch_gpio_reqt req;
+ s32 ret;
+ s32 err;
+ struct pch_gpio_chip *chip =
+ (struct pch_gpio_chip *)filep->private_data;
+
+ ret = mutex_lock_interruptible(&pch_gpio_mutex);
+ if (ret) {
+ err = -ERESTARTSYS;
+ goto return_err_nomutex;
+ }
+
+ if (chip->pch_gpio_opencount > 0) {
+ memset(&req, 0, sizeof(req));
+ req.pins = PCH_GPIO_ALL_PINS;
+
+ /* disable interrupts for all gpio pins */
+ pch_gpio_int_mode(&req, chip);
+
+ free_irq(chip->pch_gpio_irq, chip);
+ dev_dbg(chip->dev,
+ "%s : free_irq invoked successfully", __func__);
+ chip->pch_gpio_opencount--;
+ }
+ dev_dbg(chip->dev, "%s : pch_gpio_opencount = %d returning = %d\n",
+ __func__, chip->pch_gpio_opencount, 0);
+ mutex_unlock(&pch_gpio_mutex);
+ return 0;
+return_err_nomutex:
+ return err;
+}
+
+/**
+ * pch_gpio_ioctl - This function is registered at the driver initialization
+ * point (module_init) and invoked when user process
+ * invokes an ioctl call on the device.
+ * @inode: Contains the reference of the inode structure
+ * @filep: Contains the reference of the file structure
+ * @cmd: Contains the command value
+ * @arg: Contains the command argument value
+ *
+ * Returns
+ * 0: 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.
+ *
+ */
+static long pch_gpio_ioctl(struct file *filep, unsigned int cmd,
+ unsigned long arg)
+{
+ struct pch_gpio_reqt gpio_reqt;
+ s32 ret_value;
+ s32 ret;
+ struct pch_gpio_chip *chip =
+ (struct pch_gpio_chip *)filep->private_data;
+
+ ret = mutex_lock_interruptible(&pch_gpio_mutex);
+ if (ret) {
+ ret_value = -ERESTARTSYS;
+ goto return_err_nomutex;
+ }
+
+ dev_dbg(chip->dev, "\n%s: cmd = 0x%x\n"
+ "%s: IOCTL_GPIO_INT_ENABLE= 0x%x\n"
+ "%s: IOCTL_GPIO_INT_DISABLE= 0x%x\n"
+ "%s: IOCTL_GPIO_DIRECTION= 0x%x\n"
+ "%s: IOCTL_GPIO_WRITE= 0x%x\n"
+ "%s: IOCTL_GPIO_READ= 0x%x\n"
+ "%s: IOCTL_GPIO_NOTIFY= 0x%x\n",
+ __func__, cmd,
+ __func__, IOCTL_GPIO_INT_ENABLE,
+ __func__, IOCTL_GPIO_INT_DISABLE,
+ __func__, IOCTL_GPIO_DIRECTION,
+ __func__, IOCTL_GPIO_WRITE,
+ __func__, IOCTL_GPIO_READ,
+ __func__, IOCTL_GPIO_NOTIFY);
+
+ if (chip->pch_gpio_suspended == true) {
+ dev_err(chip->dev, "%s : suspend initiated returning"
+ "=%d\n", __func__, EPERM);
+ ret_value = EPERM;
+ goto ioctl_error;
+ }
+
+ ret_value = copy_from_user(&gpio_reqt, (void *)arg,
+ sizeof(struct pch_gpio_reqt));
+ if (ret_value) {
+ dev_err(chip->dev, "%s : copy_from_user fail returning=%d\n",
+ __func__, -EFAULT);
+ ret_value = -EFAULT;
+ goto ioctl_error;
+ }
+ dev_dbg(chip->dev, "%s : copy_from_user returns =%d\n", __func__,
+ ret_value);
+
+ if (((gpio_reqt.enable) > 1)
+ || ((gpio_reqt.pins) > GPIO_MAX_PINS_MASK)
+ || ((gpio_reqt.port) > GPIO_NUM_PORT_MAX)) {
+ dev_err(chip->dev, "%s : Invalid parameter returning=%d\n",
+ __func__, -EINVAL);
+ ret_value = -EINVAL;
+ goto ioctl_error;
+ }
+ switch (cmd) {
+ case IOCTL_GPIO_INT_ENABLE:
+ if (gpio_reqt.enable == 0) {
+ ret_value = -EINVAL;
+ dev_dbg(chip->dev, "%s : Invalid parameter in enable\n",
+ __func__);
+ } else {
+ ret_value = pch_gpio_int_mode(&gpio_reqt, chip);
+ dev_dbg(chip->dev,
+ "%s : Invoked pch_gpio_int_mode successfully\n",
+ __func__);
+ }
+ break;
+ case IOCTL_GPIO_INT_DISABLE:
+ if (gpio_reqt.enable != 0) {
+ ret_value = -EINVAL;
+ dev_dbg(chip->dev, "%s : Invalid parameter in enable\n",
+ __func__);
+ } else {
+ ret_value = pch_gpio_int_mode(&gpio_reqt, chip);
+ dev_dbg(chip->dev,
+ "%s : Invoked pch_gpio_int_mode successfully\n",
+ __func__);
+ }
+ break;
+ case IOCTL_GPIO_DIRECTION:
+ if (gpio_reqt.mode > 1) {
+ dev_dbg(chip->dev, "%s :Invalid direction\n", __func__);
+ ret_value = -EINVAL;
+ } else {
+ pch_gpio_dir_mode(&gpio_reqt, chip);
+ dev_dbg(chip->dev,
+ "%s : Invoked pch_gpio_dir_mode successfully\n",
+ __func__);
+ ret_value = 0;
+ }
+ break;
+ case IOCTL_GPIO_WRITE:
+ ret_value = pch_gpio_write(&gpio_reqt, chip);
+ dev_dbg(chip->dev,
+ "%s : Invoked pch_gpio_write_mode successfully\n", __func__);
+ break;
+ case IOCTL_GPIO_READ:
+ pch_gpio_read(&gpio_reqt, chip);
+ dev_dbg(chip->dev,
+ "%s : Invoked pch_gpio_read_mode successfully\n", __func__);
+ ret_value = copy_to_user((void *)arg, &gpio_reqt,
+ sizeof(struct pch_gpio_reqt));
+
+ if (ret_value) {
+ dev_err(chip->dev,
+ "%s copy_to_user failed returning=%d\n",
+ __func__, -EFAULT);
+ ret_value = -EFAULT;
+ } else {
+ dev_dbg(chip->dev, "%s copy_to_user returns=%d\n",
+ __func__, ret_value);
+ ret_value = 0;
+ }
+ break;
+ case IOCTL_GPIO_NOTIFY:
+ chip->pch_gpio_event_flag = 0;
+ if ((((ioread32(&chip->reg->ien)) & (gpio_reqt.pins))
+ != (gpio_reqt.pins)) ||
+ (((ioread32(&chip->reg->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 */
+ dev_dbg(chip->dev, "%s GPIO pins not in "
+ "input mode or interrupts not enabled!", __func__);
+ ret_value = -EINVAL;
+ } else {
+ ret_value = wait_event_interruptible(
+ chip->pch_gpio_event,
+ (chip->pch_gpio_event_flag & gpio_reqt.pins) != 0);
+ if (ret_value) {
+ dev_err(chip->dev, "%s wait_event_interruptible"
+ "failed returning=%d\n",
+ __func__, -ERESTARTSYS);
+ ret_value = -ERESTARTSYS;
+ } else {
+ dev_dbg(chip->dev,
+ "%s wait_event_interruptible returns=%d\n",
+ __func__, ret_value);
+ pch_gpio_read(&gpio_reqt, chip);
+ ret_value = copy_to_user((void *)arg,
+ &gpio_reqt,
+ sizeof(struct pch_gpio_reqt));
+ if (ret_value) {
+ dev_err(chip->dev, "%s"
+ "copy_to_user failed returni"
+ "ng=%d\n", __func__, -EFAULT);
+ ret_value = -EFAULT;
+ } else {
+ dev_dbg(chip->dev, "%s"
+ "copy_to_user returns=%d\n",
+ __func__, ret_value);
+ ret_value = 0;
+ }
+ }
+ }
+ break;
+ default:
+ dev_err(chip->dev, "%s invalid command returning=%d\n",
+ __func__, -EINVAL);
+ ret_value = -EINVAL;
+ break;
+ }
+ioctl_error:
+ mutex_unlock(&pch_gpio_mutex);
+return_err_nomutex:
+ dev_dbg(chip->dev, "%s returns=%d\n", __func__, ret_value);
+ return ret_value;
+}
+
+/**
+ * struct pch_gpio_fops - Instance of the Kernel structure file_operations.
+ */
+static const struct file_operations pch_gpio_fops = {
+ .owner = THIS_MODULE,
+ .open = pch_gpio_open,
+ .release = pch_gpio_release,
+ .unlocked_ioctl = pch_gpio_ioctl,
+};
+
+static void __devexit pch_gpio_remove(struct pci_dev *pdev)
+{
+ struct pch_gpio_reqt req;
+ struct pch_gpio_chip *chip = pci_get_drvdata(pdev);
+ memset(&req, 0, sizeof(req));
+ req.pins = PCH_GPIO_ALL_PINS;
+ /* disable interrupts for all gpio pins */
+ pch_gpio_int_mode(&req, chip);
+
+ cdev_del(&chip->pch_gpio_dev);
+ dev_dbg(&pdev->dev, "%s - cdev_del Invoked successfully\n", __func__);
+
+ unregister_chrdev_region(chip->pch_gpio_dev_no, PCH_MINOR_NOS);
+ dev_dbg(&pdev->dev,
+ "%s - unregister_chrdev_region Invoked successfully\n", __func__);
+
+ pci_iounmap(pdev, chip->pch_gpio_base_address);
+
+ dev_dbg(&pdev->dev, "%s - pci_iounmap Invoked successfully\n",
+ __func__);
+
+ pci_release_regions(pdev);
+ dev_dbg(&pdev->dev,
+ "%s - pci_release_regions Invoked successfully\n", __func__);
+
+ pci_disable_device(pdev);
+ dev_dbg(&pdev->dev,
+ "%s - pci_disable_device Invoked successfully\n", __func__);
+ kfree(chip);
+}
+
+#ifdef CONFIG_PM
+static s32 pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ s32 ret;
+ struct pch_gpio_chip *chip = pci_get_drvdata(pdev);
+
+ chip->pch_gpio_suspended = true;
+
+ pch_gpio_save_reg_conf(chip);
+ dev_dbg(&pdev->dev,
+ "%s - pch_gpio_save_reg_conf Invoked successfully\n", __func__);
+ pch_gpio_restore_reg_conf(chip);
+
+ ret = pci_save_state(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "%s - pci_save_state returns-%d\n",
+ __func__, ret);
+ return ret;
+ }
+ dev_dbg(&pdev->dev, "%s - pci_save_state returns %d\n", __func__, ret);
+ pci_disable_device(pdev);
+ dev_dbg(&pdev->dev, "%s - "
+ "pci_disable_device Invoked successfully\n", __func__);
+ pci_set_power_state(pdev, PCI_D0);
+ dev_dbg(&pdev->dev, "%s - "
+ "pci_set_power_state Invoked successfully\n", __func__);
+ ret = pci_enable_wake(pdev, PCI_D0, 1);
+ if (!ret) {
+ dev_dbg(&pdev->dev, "%s - "
+ "pci_enable_wake Invoked successfully\n", __func__);
+ } else {
+ dev_dbg(&pdev->dev, "%s - pci_enable_wake failed\n", __func__);
+ }
+ dev_err(&pdev->dev, "%s - return %d\n", __func__, 0);
+ return 0;
+}
+
+static s32 pch_gpio_resume(struct pci_dev *pdev)
+{
+ s32 ret;
+ struct pch_gpio_chip *chip = pci_get_drvdata(pdev);
+
+ ret = pci_enable_wake(pdev, PCI_D0, 0);
+ dev_err(&pdev->dev, "%s - "
+ "pci_set_power_state Invoked successfully\n", __func__);
+
+ pci_set_power_state(pdev, PCI_D0);
+ dev_dbg(&pdev->dev, "%s - "
+ "pci_set_power_state Invoked successfully\n", __func__);
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "%s-pci_enable_device failed ", __func__);
+ return ret;
+ }
+ dev_dbg(&pdev->dev, "%s - "
+ "pci_enable_device returns -%d\n", __func__, ret);
+ pci_restore_state(pdev);
+ dev_dbg(&pdev->dev, "%s - "
+ "pci_restore_state Invoked successfully\n", __func__);
+
+ iowrite32(0x01, &chip->reg->reset);
+ iowrite32(0x00, &chip->reg->reset);
+ pch_gpio_restore_reg_conf(chip);
+ chip->pch_gpio_suspended = false;
+
+ dev_dbg(&pdev->dev, "%s returns- %d\n", __func__, 0);
+ return 0;
+}
+#else
+#define pch_gpio_suspend NULL
+#define pch_gpio_resume NULL
+#endif
+
+static struct pci_device_id pch_gpio_pcidev_id[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_GE_GPIO)},
+ {0,}
+};
+
+
+static s32 __devinit pch_gpio_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ s32 ret;
+ struct pch_gpio_chip *chip;
+
+ chip = kzalloc(sizeof(struct pch_gpio_chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ chip->dev = &pdev->dev;
+ chip->pch_gpio_bit_mask = BIT_MASK_12;
+ dev_dbg(&pdev->dev, "%s : The value of pch_gpio_bit_mask is: %x\n",
+ __func__, chip->pch_gpio_bit_mask);
+
+ if (pch_gpio_major_no < 0 || pch_gpio_major_no > 254)
+ pch_gpio_major_no = 0;
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__);
+ goto err_pci_enable;
+ }
+ dev_dbg(&pdev->dev, "%s : pci_enable_device returns %d\n",
+ __func__, ret);
+
+ ret = pci_request_regions(pdev, MODULE_NAME);
+ if (ret) {
+ dev_err(&pdev->dev, "%s : pci_request_regions FAILED",
+ __func__);
+ goto err_request_regions;
+ }
+ dev_dbg(&pdev->dev, "%s : "
+ "pci_request_regions returns %d\n", __func__, ret);
+
+ chip->pch_gpio_base_address = pci_iomap(pdev, 1, 0);
+
+ if (chip->pch_gpio_base_address == 0) {
+ dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
+ ret = -ENOMEM;
+ goto err_iomap;
+ }
+ chip->reg =
+ (struct pch_gpio_regs __iomem *)(chip->pch_gpio_base_address);
+
+ dev_dbg(&pdev->dev, "%s : pci_iomap SUCCESS and value in"
+ "pch_gpio_base_address variable is %p\n",
+ __func__, chip->pch_gpio_base_address);
+
+ if (pch_gpio_major_no) {
+ chip->pch_gpio_dev_no = MKDEV(pch_gpio_major_no, 0);
+ ret = register_chrdev_region(chip->pch_gpio_dev_no,
+ PCH_MINOR_NOS, MODULE_NAME);
+ if (ret) {
+ dev_err(&pdev->dev, "%s : "
+ "register_chrdev_region FAILED", __func__);
+ goto err_reg_chardev_reg;
+ }
+ dev_dbg(&pdev->dev, "%s : "
+ "register_chrdev_region returns %d\n", __func__, ret);
+ } else {
+ ret = alloc_chrdev_region(&chip->pch_gpio_dev_no, 0,
+ PCH_MINOR_NOS, MODULE_NAME);
+ if (ret) {
+ dev_err(&pdev->dev, "%s : alloc_chrdev_region FAILED",
+ __func__);
+ goto err_reg_chardev_reg;
+ }
+ dev_dbg(&pdev->dev, "%s : alloc_chrdev_region returns %d\n",
+ __func__, ret);
+ }
+
+ cdev_init(&chip->pch_gpio_dev, &pch_gpio_fops);
+ dev_dbg(&pdev->dev, "%s : cdev_init invoked successfully\n", __func__);
+
+ chip->pch_gpio_dev.owner = THIS_MODULE;
+ chip->pch_gpio_dev.ops = &pch_gpio_fops;
+
+ ret =
+ cdev_add(&chip->pch_gpio_dev, chip->pch_gpio_dev_no, PCH_MINOR_NOS);
+ if (ret) {
+ dev_err(&pdev->dev, "%s : cdev_add FAILED", __func__);
+ goto err_cdev_add;
+ }
+ dev_dbg(&pdev->dev, "%s : cdev_add returns- %d\n", __func__, ret);
+ pci_set_drvdata(pdev, chip);
+ pch_gpio_cb_register(pch_gpio_cb, chip);
+ chip->pch_gpio_irq = pdev->irq;
+ dev_dbg(&pdev->dev, "%s returns %d\n", __func__, 0);
+ device_set_wakeup_enable(&pdev->dev, 1);
+ return 0;
+err_cdev_add:
+ unregister_chrdev_region(chip->pch_gpio_dev_no, PCH_MINOR_NOS);
+
+err_reg_chardev_reg:
+ pci_iounmap(pdev, chip->pch_gpio_base_address);
+
+err_iomap:
+ pci_release_regions(pdev);
+
+err_request_regions:
+ pci_disable_device(pdev);
+
+err_pci_enable:
+ kfree(chip);
+ dev_dbg(&pdev->dev, "%s returns %d\n", __func__, ret);
+ return ret;
+}
+
+static struct pci_driver pch_gpio_driver = {
+ .name = "pch_gpio",
+ .id_table = pch_gpio_pcidev_id,
+ .probe = pch_gpio_probe,
+ .remove = __devexit_p(pch_gpio_remove),
+ .suspend = pch_gpio_suspend,
+ .resume = pch_gpio_resume
+};
+
+static s32 __init pch_gpio_pci_init(void)
+{
+ s32 ret;
+ ret = pci_register_driver(&pch_gpio_driver);
+
+ return ret;
+}
+
+static void __exit pch_gpio_pci_exit(void)
+{
+ pci_unregister_driver(&pch_gpio_driver);
+}
+MODULE_DESCRIPTION("PCH GPIO PCI Driver");
+MODULE_LICENSE("GPL");
+module_param(pch_gpio_major_no, int, S_IRUSR | S_IWUSR);
+module_init(pch_gpio_pci_init);
+module_exit(pch_gpio_pci_exit);
+
diff --git a/drivers/gpio/pch_gpio.h b/drivers/gpio/pch_gpio.h
new file mode 100644
index 0000000..f6eed95
--- /dev/null
+++ b/drivers/gpio/pch_gpio.h
@@ -0,0 +1,245 @@
+#ifndef __PCH_GPIO_MAIN_H__
+#define __PCH_GPIO_MAIN_H__
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * 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.
+ */
+
+/** The ioctl magic number. */
+#define GPIO_IOCTL_MAGIC 0xf2
+/** IOCTL for GPIO interrupt enable. */
+#define IOCTL_GPIO_INT_ENABLE (_IOW(GPIO_IOCTL_MAGIC, 1, struct pch_gpio_reqt))
+/** IOCTL for GPIO interrupt disable. */
+#define IOCTL_GPIO_INT_DISABLE (_IOW(GPIO_IOCTL_MAGIC, 2, struct pch_gpio_reqt))
+/** IOCTL for GPIO direction setting. */
+#define IOCTL_GPIO_DIRECTION (_IOW(GPIO_IOCTL_MAGIC, 3, struct pch_gpio_reqt))
+/** IOCTL for GPIO write. */
+#define IOCTL_GPIO_WRITE (_IOW(GPIO_IOCTL_MAGIC, 4, struct pch_gpio_reqt))
+/** IOCTL for GPIO read. */
+#define IOCTL_GPIO_READ (_IOR(GPIO_IOCTL_MAGIC, 5, struct pch_gpio_reqt))
+/** IOCTL for GPIO pin status change notification. */
+#define IOCTL_GPIO_NOTIFY (_IOR(GPIO_IOCTL_MAGIC, 6, struct pch_gpio_reqt))
+
+/** GPIO PIN */
+#define PCH_GPIO_PIN0 0x1
+#define PCH_GPIO_PIN1 0x2
+#define PCH_GPIO_PIN2 0x4
+#define PCH_GPIO_PIN3 0x8
+#define PCH_GPIO_PIN4 0x10
+#define PCH_GPIO_PIN5 0x20
+#define PCH_GPIO_PIN6 0x40
+#define PCH_GPIO_PIN7 0x80
+#define PCH_GPIO_PIN8 0x100
+#define PCH_GPIO_PIN9 0x200
+#define PCH_GPIO_PIN10 0x400
+#define PCH_GPIO_PIN11 0x800
+
+/** Mask for GPIO pins 0 to 11 */
+#define PCH_GPIO_ALL_PINS (PCH_GPIO_PIN0 | PCH_GPIO_PIN1 | PCH_GPIO_PIN2\
+ | PCH_GPIO_PIN3 | PCH_GPIO_PIN4 | PCH_GPIO_PIN5\
+ | PCH_GPIO_PIN6 | PCH_GPIO_PIN7 | PCH_GPIO_PIN8\
+ | PCH_GPIO_PIN9 | PCH_GPIO_PIN10\
+ | PCH_GPIO_PIN11)
+
+/** Falling Edge interrupt */
+#define INT_FL_EDG_PIN0 0x0
+#define INT_FL_EDG_PIN1 0x0
+#define INT_FL_EDG_PIN2 0x0
+#define INT_FL_EDG_PIN3 0x0
+#define INT_FL_EDG_PIN4 0x0
+#define INT_FL_EDG_PIN5 0x0
+#define INT_FL_EDG_PIN6 0x0
+#define INT_FL_EDG_PIN7 0x0
+#define INT_FL_EDG_PIN8 0x0
+#define INT_FL_EDG_PIN9 0x0
+#define INT_FL_EDG_PIN10 0x0
+#define INT_FL_EDG_PIN11 0x0
+
+/** Rising Edge interrupt */
+#define INT_RS_EDG_PIN0 0x1
+#define INT_RS_EDG_PIN1 0x10
+#define INT_RS_EDG_PIN2 0x100
+#define INT_RS_EDG_PIN3 0x1000
+#define INT_RS_EDG_PIN4 0x10000
+#define INT_RS_EDG_PIN5 0x100000
+#define INT_RS_EDG_PIN6 0x1000000
+#define INT_RS_EDG_PIN7 0x10000000
+#define INT_RS_EDG_PIN8 0x100000000ULL
+#define INT_RS_EDG_PIN9 0x1000000000ULL
+#define INT_RS_EDG_PIN10 0x10000000000ULL
+#define INT_RS_EDG_PIN11 0x100000000000ULL
+
+/** Low Level Interrupt */
+#define INT_LVL_LO_PIN0 0x2
+#define INT_LVL_LO_PIN1 0x20
+#define INT_LVL_LO_PIN2 0x200
+#define INT_LVL_LO_PIN3 0x2000
+#define INT_LVL_LO_PIN4 0x20000
+#define INT_LVL_LO_PIN5 0x200000
+#define INT_LVL_LO_PIN6 0x2000000
+#define INT_LVL_LO_PIN7 0x20000000
+#define INT_LVL_LO_PIN8 0x200000000ULL
+#define INT_LVL_LO_PIN9 0x2000000000ULL
+#define INT_LVL_LO_PIN10 0x20000000000ULL
+#define INT_LVL_LO_PIN11 0x200000000000ULL
+
+/** High Level Interrupt */
+#define INT_LVL_HI_PIN0 0x3
+#define INT_LVL_HI_PIN1 0x30
+#define INT_LVL_HI_PIN2 0x300
+#define INT_LVL_HI_PIN3 0x3000
+#define INT_LVL_HI_PIN4 0x30000
+#define INT_LVL_HI_PIN5 0x300000
+#define INT_LVL_HI_PIN6 0x3000000
+#define INT_LVL_HI_PIN7 0x30000000
+#define INT_LVL_HI_PIN8 0x300000000ULL
+#define INT_LVL_HI_PIN9 0x3000000000ULL
+#define INT_LVL_HI_PIN10 0x30000000000ULL
+#define INT_LVL_HI_PIN11 0x300000000000ULL
+
+/** Falling and rising Edge */
+#define INT_FL_RS_EDG_PIN0 0x4
+#define INT_FL_RS_EDG_PIN1 0x40
+#define INT_FL_RS_EDG_PIN2 0x400
+#define INT_FL_RS_EDG_PIN3 0x4000
+#define INT_FL_RS_EDG_PIN4 0x40000
+#define INT_FL_RS_EDG_PIN5 0x400000
+#define INT_FL_RS_EDG_PIN6 0x4000000
+#define INT_FL_RS_EDG_PIN7 0x40000000
+#define INT_FL_RS_EDG_PIN8 0x400000000ULL
+#define INT_FL_RS_EDG_PIN9 0x4000000000ULL
+#define INT_FL_RS_EDG_PIN10 0x40000000000ULL
+#define INT_FL_RS_EDG_PIN11 0x400000000000ULL
+
+#define GPIO_MAX_PINS_MASK 0xFFF /** Mask used for all pins.*/
+#define GPIO_NUM_PORT_MAX 0 /** Maximum number of ports.*/
+#define GPIO_NUM_PINS 12 /** Specifies number of GPIO PINS */
+#define GPIO_IN 0 /** Specifies GPIO input mode.*/
+#define GPIO_OUT 1 /** Specifies GPIO output mode. */
+#define GPIO_HIGH 1 /** Specifies GPIO HIGH level.*/
+#define GPIO_LOW 0 /** Specifies GPIO LOW level.*/
+#define BIT_MASK_16 0xFFFF /** Maks for 16 bits. */
+#define BIT_MASK_8 0xFF /** Maks for 8 bits. */
+#define BIT_MASK_12 0xFFF /** Maks for 12 bits. */
+#define BIT_MASK_32 0xFFFFFFFF /** Maks value for 32 bits. */
+#define GPIO_INT_MODE_MSK 0xF /** mask for interrupt mode configuration */
+#define GPIO_INT_MODE_POS 0x4 /** mask for interrupt mode bit position */
+#define GPIO_INT_MODE_VALID 0x4 /** interrupt mode valid value */
+#define BITS_32 32 /** Corresponds to the 32 bit position. */
+#define MODULE_NAME "pch_gpio"
+#define PCI_DEVICE_ID_GE_GPIO 0x8803
+#define PCH_MINOR_NOS 1 /** Outlines the GPIO minor number limit. */
+
+/**
+ * struct pch_gpio_regs - The register.
+ * @ien: IEN register [0x000]
+ * @istatus: ISTATUS register
+ * @idisp: IDISP register
+ * @iclr: ICLR register
+ * @imask: IMASK register
+ * @imaskclr: IMASKCLR register
+ * @po: P0 register
+ * @pi: PI register
+ * @pm: PM register
+ * @im0: IM0 register
+ * @im1: IM1 register [0x028]
+ * @reserved[4]:
+ * @reset: RESET register [0x03C]
+ */
+struct pch_gpio_regs {
+ u32 ien;
+ u32 istatus;
+ u32 idisp;
+ u32 iclr;
+ u32 imask;
+ u32 imaskclr;
+ u32 po;
+ u32 pi;
+ u32 pm;
+ u32 im0;
+ u32 im1;
+ u32 reserved[4];
+ u32 reset;
+};
+
+/**
+ * struct pch_gpio_reg_data - The register store data.
+ * @ien_reg: To store contents of IEN register.
+ * @imask_reg: To store contents of IMASK register.
+ * @po_reg: To store contents of PO register.
+ * @pm_reg: To store contents of PM register.
+ * @im0_reg: To store contents of IM0 register.
+ * @im1_reg: To store contents of IM1 register.
+ */
+struct pch_gpio_reg_data {
+ u32 ien_reg;
+ u32 imask_reg;
+ u32 po_reg;
+ u32 pm_reg;
+ u32 im0_reg;
+ u32 im1_reg;
+};
+
+
+/**
+ * struct pch_gpio_chip - GPIO private data structure.
+ * @pch_gpio_event: Wait queue.
+ * @pch_gpio_event_flag: event flag.
+ * @pch_gpio_opencount: GPIO device open counter.
+ * @pch_gpio_base_address: GPIO base address.
+ * @pch_gpio_irq: IRQ number.
+ * @pch_gpio_suspended: Suspend status.
+ * @pch_gpio_bit_mask: GPIO data bitmask.
+ * @pch_gpio_dev_no: Device number.
+ * @pch_gpio_dev: Character device data structure.
+ * @reg: PCH GPIO register list.
+ * @dev: Pointer to device structure.
+ * @pch_gpio_reg: Register data is saved here.
+ */
+struct pch_gpio_chip {
+ wait_queue_head_t pch_gpio_event;
+ u32 pch_gpio_event_flag;
+ s32 pch_gpio_opencount;
+ void __iomem *pch_gpio_base_address;
+ u32 pch_gpio_irq;
+ s32 pch_gpio_suspended;
+ u32 pch_gpio_bit_mask;
+ dev_t pch_gpio_dev_no;
+ struct cdev pch_gpio_dev;
+ struct pch_gpio_regs __iomem *reg;
+ struct device *dev;
+ struct pch_gpio_reg_data pch_gpio_reg;
+};
+
+/**
+ * struct pch_gpio_reqt - It is a structure used for perserving information
+ * related to the gpio request.
+ * @port: Specifies the port.
+ * @pins: Specifies the pins.
+ * @mode: Specifies the direction/interrupt mode.
+ * @enable: Interrupt enable/disable.
+ *
+ * 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.
+ */
+struct pch_gpio_reqt {
+ __u32 port;
+ __u32 pins;
+ __u64 mode;
+ __u32 enable;
+};
+
+#endif
--
1.6.0.6
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists