[PATCH 1/4] arm: msm: gpio support

Daniel Walker dwalker at codeaurora.org
Tue Mar 30 19:11:54 EDT 2010


From: Daniel Walker <c_dwalke at quicinc.com>

This adds basic gpio support in MSM using gpiolib, as well as gpio
interrupt support.

Signed-off-by: Daniel Walker <c_dwalke at quicinc.com>
---
 arch/arm/Kconfig                      |    1 +
 arch/arm/mach-msm/Makefile            |    1 +
 arch/arm/mach-msm/gpio.c              |  428 +++++++++++++++++++++++++++++++++
 arch/arm/mach-msm/gpio_hw.h           |  187 ++++++++++++++
 arch/arm/mach-msm/include/mach/gpio.h |   43 ++++
 5 files changed, 660 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-msm/gpio.c
 create mode 100644 arch/arm/mach-msm/gpio_hw.h
 create mode 100644 arch/arm/mach-msm/include/mach/gpio.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index cadfe2e..5e29092 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -601,6 +601,7 @@ config ARCH_MSM
 	select CPU_V6
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
+	select ARCH_REQUIRE_GPIOLIB
 	help
 	  Support for Qualcomm MSM7K based systems.  This runs on the ARM11
 	  apps processor of the MSM7K and depends on a shared memory
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 147339c..47d47cb 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -4,6 +4,7 @@ obj-y += proc_comm.o
 obj-y += vreg.o
 obj-y += acpuclock-arm11.o
 obj-y += clock.o clock-7x01a.o
+obj-y += gpio.o
 
 obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
diff --git a/arch/arm/mach-msm/gpio.c b/arch/arm/mach-msm/gpio.c
new file mode 100644
index 0000000..5b95885
--- /dev/null
+++ b/arch/arm/mach-msm/gpio.c
@@ -0,0 +1,428 @@
+/* linux/arch/arm/mach-msm/gpio.c
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include "gpio_hw.h"
+
+#include "smd_private.h"
+
+static int msm_gpio_debug_mask;
+module_param_named(debug_mask, msm_gpio_debug_mask, int,
+		   S_IRUGO | S_IWUSR | S_IWGRP);
+
+#define MSM_GPIO_BROKEN_INT_CLEAR 1
+
+/* private gpio_configure flags */
+#define MSM_GPIOF_ENABLE_INTERRUPT      0x10000000
+#define MSM_GPIOF_DISABLE_INTERRUPT     0x20000000
+#define MSM_GPIOF_ENABLE_WAKE           0x40000000
+#define MSM_GPIOF_DISABLE_WAKE          0x80000000
+
+static int gpio_chip_to_irq(struct gpio_chip *chip, unsigned offset);
+static void gpio_chip_set(struct gpio_chip *chip, unsigned offset, int value);
+static int gpio_chip_get(struct gpio_chip *chip, unsigned offset);
+static int gpio_chip_direction_input(struct gpio_chip *chip, unsigned offset);
+static int gpio_chip_direction_output(struct gpio_chip *chip, unsigned offset,
+				      int value);
+
+struct msm_gpio_regs {
+	void __iomem *out;
+	void __iomem *in;
+	void __iomem *int_status;
+	void __iomem *int_clear;
+	void __iomem *int_en;
+	void __iomem *int_edge;
+	void __iomem *int_pos;
+	void __iomem *oe;
+};
+
+struct msm_gpio_chip {
+	struct gpio_chip        chip;
+	struct msm_gpio_regs    regs;
+	spinlock_t		lock;
+#if MSM_GPIO_BROKEN_INT_CLEAR
+	unsigned                int_status_copy;
+#endif
+	unsigned int            both_edge_detect;
+	unsigned int            int_enable[2]; /* 0: awake, 1: sleep */
+};
+
+#define MSM_GPIO_BANK(name, reg_num, start, end)			\
+	{								\
+		.regs = {						\
+			.out =         GPIO_OUT_ ## reg_num,		\
+			.in =          GPIO_IN_ ## reg_num ,		\
+			.int_status =  GPIO_INT_STATUS_ ## reg_num,	\
+			.int_clear =   GPIO_INT_CLEAR_ ## reg_num,	\
+			.int_en =      GPIO_INT_EN_ ## reg_num,		\
+			.int_edge =    GPIO_INT_EDGE_ ## reg_num,	\
+			.int_pos =     GPIO_INT_POS_ ## reg_num,	\
+			.oe =          GPIO_OE_ ## reg_num,		\
+		},							\
+		.chip = {						\
+			.label = name,					\
+			.ngpio = end - start + 1,			\
+			.direction_input = gpio_chip_direction_input,	\
+			.direction_output = gpio_chip_direction_output,	\
+			.get = gpio_chip_get,				\
+			.set = gpio_chip_set,				\
+			.to_irq = gpio_chip_to_irq,			\
+			.base = start,					\
+		}							\
+	}
+
+struct msm_gpio_chip msm_gpio_chips[] = {
+	MSM_GPIO_BANK("bank0", 0, 0, 15),
+	MSM_GPIO_BANK("bank1", 1, 16, 42),
+	MSM_GPIO_BANK("bank2", 2, 43, 67),
+	MSM_GPIO_BANK("bank3", 3, 68, 94),
+#if defined(CONFIG_ARCH_QSD8X50)
+	MSM_GPIO_BANK("bank4", 4, 95, 103),
+	MSM_GPIO_BANK("bank5", 5, 104, 121),
+	MSM_GPIO_BANK("bank6", 6, 122, 152),
+	MSM_GPIO_BANK("bank7", 7, 153, 164),
+#else
+	MSM_GPIO_BANK("bank4", 4, 95, 106),
+	MSM_GPIO_BANK("bank5", 5, 107, 121),
+#endif
+};
+
+#define to_msm_gpio_chip(c) container_of(c, struct msm_gpio_chip, chip)
+
+static int gpio_chip_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct msm_gpio_chip *old_chip = to_msm_gpio_chip(chip);
+	unsigned long irq_flags;
+	unsigned b = 1U << (offset);
+	unsigned v;
+
+	spin_lock_irqsave(&old_chip->lock, irq_flags);
+	b = 1U << (offset);
+
+	v = readl(old_chip->regs.oe);
+	writel(v & (~b), old_chip->regs.oe);
+
+	spin_unlock_irqrestore(&old_chip->lock, irq_flags);
+
+	return 0;
+}
+
+static int gpio_chip_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct msm_gpio_chip *old_chip = to_msm_gpio_chip(chip);
+	unsigned long irq_flags;
+	int ret = -ENOTSUPP;
+	unsigned b;
+
+	spin_lock_irqsave(&old_chip->lock, irq_flags);
+	b = 1U << (offset);
+
+	ret = (readl(old_chip->regs.in)) & b ? 1 : 0;
+
+	spin_unlock_irqrestore(&old_chip->lock, irq_flags);
+	return ret;
+}
+
+static inline int
+msm_gpio_write(struct msm_gpio_chip *chip, unsigned n, unsigned on)
+{
+	unsigned b = 1U << n;
+	unsigned v;
+
+	v = readl(chip->regs.out);
+	if (on)
+		writel(v | b, chip->regs.out);
+	else
+		writel(v & (~b), chip->regs.out);
+
+	return 0;
+}
+
+static int
+gpio_chip_direction_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct msm_gpio_chip *old_chip = to_msm_gpio_chip(chip);
+	unsigned long irq_flags;
+	unsigned v;
+
+	spin_lock_irqsave(&old_chip->lock, irq_flags);
+
+	msm_gpio_write(old_chip, offset, value);
+
+	v = readl(old_chip->regs.oe);
+	writel(v | offset, old_chip->regs.oe);
+
+	spin_unlock_irqrestore(&old_chip->lock, irq_flags);
+
+	return 0;
+}
+
+static void gpio_chip_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct msm_gpio_chip *old_chip = to_msm_gpio_chip(chip);
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&old_chip->lock, irq_flags);
+
+	msm_gpio_write(old_chip, offset, value);
+
+	spin_unlock_irqrestore(&old_chip->lock, irq_flags);
+}
+
+static int gpio_chip_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct msm_gpio_chip *old_chip = to_msm_gpio_chip(chip);
+	unsigned long irq_flags;
+	int ret;
+
+	spin_lock_irqsave(&old_chip->lock, irq_flags);
+	ret = MSM_GPIO_TO_INT(offset);
+	spin_unlock_irqrestore(&old_chip->lock, irq_flags);
+
+	return ret;
+}
+
+
+static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
+{
+	int loop_limit = 100;
+	unsigned pol, val, val2, intstat;
+	do {
+		val = readl(msm_chip->regs.in);
+		pol = readl(msm_chip->regs.int_pos);
+		pol = (pol & ~msm_chip->both_edge_detect) |
+		      (~val & msm_chip->both_edge_detect);
+
+		writel(pol, msm_chip->regs.int_pos);
+
+		intstat = readl(msm_chip->regs.int_status);
+		val2 = readl(msm_chip->regs.in);
+
+		if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
+			return;
+	} while (loop_limit-- > 0);
+	printk(KERN_ERR "msm_gpio_update_both_edge_detect, failed to reach stable state %x != %x\n", val, val2);
+}
+
+static void msm_gpio_irq_ack(unsigned int irq)
+{
+	unsigned long irq_flags;
+	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+	unsigned b;
+
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+
+	b = 1U << (irq - FIRST_GPIO_IRQ - msm_chip->chip.base);
+
+#if MSM_GPIO_BROKEN_INT_CLEAR
+	/* Save interrupts that already triggered before we loose them. */
+	/* Any interrupt that triggers between the read of int_status */
+	/* and the write to int_clear will still be lost though. */
+	msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
+	msm_chip->int_status_copy &= ~b;
+#endif
+	writel(b, msm_chip->regs.int_clear);
+
+	msm_gpio_update_both_edge_detect(msm_chip);
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_mask(unsigned int irq)
+{
+	unsigned long irq_flags;
+	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+	unsigned b, v;
+
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+
+	b = 1U << (irq - FIRST_GPIO_IRQ - msm_chip->chip.base);
+
+	v = readl(msm_chip->regs.int_edge);
+	/* level triggered interrupts are also latched */
+	if (!(v & b)) {
+
+	#if MSM_GPIO_BROKEN_INT_CLEAR
+		/* Save interrupts that already triggered before we loose
+		 * them. Any interrupt that triggers between the read of
+		 * int_status and the write to int_clear will still be
+		 * lost though.
+		 */
+		msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
+		msm_chip->int_status_copy &= ~b;
+	#endif
+		writel(b, msm_chip->regs.int_clear);
+		msm_gpio_update_both_edge_detect(msm_chip);
+	}
+
+	msm_chip->int_enable[0] &= ~b;
+	writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static void msm_gpio_irq_unmask(unsigned int irq)
+{
+	unsigned long irq_flags;
+	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+	unsigned b, v;
+
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+
+	b = 1U << (irq - FIRST_GPIO_IRQ - msm_chip->chip.base);
+
+	v = readl(msm_chip->regs.int_edge);
+	/* level triggered interrupts are also latched */
+	if (!(v & b)) {
+
+	#if MSM_GPIO_BROKEN_INT_CLEAR
+		/* Save interrupts that already triggered before we loose
+		 * them. Any interrupt that triggers between the read of
+		 * int_status and the write to int_clear will still be
+		 * lost though.
+		 */
+		msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
+		msm_chip->int_status_copy &= ~b;
+	#endif
+		writel(b, msm_chip->regs.int_clear);
+		msm_gpio_update_both_edge_detect(msm_chip);
+	}
+
+	msm_chip->int_enable[0] |= b;
+	writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
+
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+}
+
+static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+{
+	unsigned long irq_flags;
+	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+	unsigned b;
+
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+
+	b = 1U << (irq - FIRST_GPIO_IRQ - msm_chip->chip.base);
+
+	if (on)
+		msm_chip->int_enable[1] |= b;
+	else
+		msm_chip->int_enable[1] &= ~b;
+
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+
+	return 0;
+}
+
+
+static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
+{
+	unsigned long irq_flags;
+	struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
+	unsigned b, v;
+
+	spin_lock_irqsave(&msm_chip->lock, irq_flags);
+
+	b = 1U << (irq - FIRST_GPIO_IRQ - msm_chip->chip.base);
+
+	v = readl(msm_chip->regs.int_edge);
+	if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)) {
+		writel(v | b, msm_chip->regs.int_edge);
+		irq_desc[MSM_GPIO_TO_INT(irq - FIRST_GPIO_IRQ)].handle_irq = handle_edge_irq;
+	} else {
+		writel(v & (~b), msm_chip->regs.int_edge);
+		irq_desc[MSM_GPIO_TO_INT(irq - FIRST_GPIO_IRQ)].handle_irq = handle_level_irq;
+	}
+	if ((flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)) ==
+			 (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)) {
+		msm_chip->both_edge_detect |= b;
+		msm_gpio_update_both_edge_detect(msm_chip);
+	} else {
+		msm_chip->both_edge_detect &= ~b;
+		v = readl(msm_chip->regs.int_pos);
+		if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
+			writel(v | b, msm_chip->regs.int_pos);
+		else
+			writel(v & (~b), msm_chip->regs.int_pos);
+
+	}
+	spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
+	return 0;
+}
+
+static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	int i, j, m;
+	unsigned v;
+
+	for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
+		struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
+		v = readl(msm_chip->regs.int_status);
+		v &= msm_chip->int_enable[0];
+		while (v) {
+			m = v & -v;
+			j = fls(m) - 1;
+			v &= ~m;
+			generic_handle_irq(FIRST_GPIO_IRQ + msm_chip->chip.base + j);
+		}
+	}
+	desc->chip->ack(irq);
+}
+
+static struct irq_chip msm_gpio_irq_chip = {
+	.name      = "msmgpio",
+	.ack       = msm_gpio_irq_ack,
+	.mask      = msm_gpio_irq_mask,
+	.unmask    = msm_gpio_irq_unmask,
+	.set_wake  = msm_gpio_irq_set_wake,
+	.set_type  = msm_gpio_irq_set_type,
+};
+
+static int __init msm_init_gpio(void)
+{
+	int i, j = 0;
+	for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
+		if (i - FIRST_GPIO_IRQ > msm_gpio_chips[j].chip.ngpio - 1)
+			j++;
+		set_irq_chip_data(i, &msm_gpio_chips[j]);
+		set_irq_chip(i, &msm_gpio_irq_chip);
+		set_irq_handler(i, handle_edge_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
+		writel(0, msm_gpio_chips[i].regs.int_en);
+		spin_lock_init(&msm_gpio_chips[i].lock);
+		gpiochip_add(&msm_gpio_chips[i].chip);
+	}
+
+	set_irq_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
+	set_irq_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
+	set_irq_wake(INT_GPIO_GROUP1, 1);
+	set_irq_wake(INT_GPIO_GROUP2, 2);
+
+	return 0;
+}
+
+postcore_initcall(msm_init_gpio);
diff --git a/arch/arm/mach-msm/gpio_hw.h b/arch/arm/mach-msm/gpio_hw.h
new file mode 100644
index 0000000..f7e1b5b
--- /dev/null
+++ b/arch/arm/mach-msm/gpio_hw.h
@@ -0,0 +1,187 @@
+/* arch/arm/mach-msm/gpio_hw.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Brian Swetland <swetland at google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_GPIO_HW_H
+#define __ARCH_ARM_MACH_MSM_GPIO_HW_H
+
+#include <mach/msm_iomap.h>
+
+/* see 80-VA736-2 Rev C pp 695-751
+**
+** These are actually the *shadow* gpio registers, since the
+** real ones (which allow full access) are only available to the
+** ARM9 side of the world.
+**
+** Since the _BASE need to be page-aligned when we're mapping them
+** to virtual addresses, adjust for the additional offset in these
+** macros.
+*/
+
+#define GPIO1_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
+#define GPIO2_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
+
+#if defined(CONFIG_ARCH_MSM7X00A)
+
+/* output value */
+#define GPIO_OUT_0         GPIO1_REG(0x00)  /* gpio  15-0  */
+#define GPIO_OUT_1         GPIO2_REG(0x00)  /* gpio  42-16 */
+#define GPIO_OUT_2         GPIO1_REG(0x04)  /* gpio  67-43 */
+#define GPIO_OUT_3         GPIO1_REG(0x08)  /* gpio  94-68 */
+#define GPIO_OUT_4         GPIO1_REG(0x0C)  /* gpio 106-95 */
+#define GPIO_OUT_5         GPIO1_REG(0x50)  /* gpio 107-121 */
+
+/* same pin map as above, output enable */
+#define GPIO_OE_0          GPIO1_REG(0x10)
+#define GPIO_OE_1          GPIO2_REG(0x08)
+#define GPIO_OE_2          GPIO1_REG(0x14)
+#define GPIO_OE_3          GPIO1_REG(0x18)
+#define GPIO_OE_4          GPIO1_REG(0x1C)
+#define GPIO_OE_5          GPIO1_REG(0x54)
+
+/* same pin map as above, input read */
+#define GPIO_IN_0          GPIO1_REG(0x34)
+#define GPIO_IN_1          GPIO2_REG(0x20)
+#define GPIO_IN_2          GPIO1_REG(0x38)
+#define GPIO_IN_3          GPIO1_REG(0x3C)
+#define GPIO_IN_4          GPIO1_REG(0x40)
+#define GPIO_IN_5          GPIO1_REG(0x44)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define GPIO_INT_EDGE_0    GPIO1_REG(0x60)
+#define GPIO_INT_EDGE_1    GPIO2_REG(0x50)
+#define GPIO_INT_EDGE_2    GPIO1_REG(0x64)
+#define GPIO_INT_EDGE_3    GPIO1_REG(0x68)
+#define GPIO_INT_EDGE_4    GPIO1_REG(0x6C)
+#define GPIO_INT_EDGE_5    GPIO1_REG(0xC0)
+
+/* same pin map as above, 1=positive 0=negative */
+#define GPIO_INT_POS_0     GPIO1_REG(0x70)
+#define GPIO_INT_POS_1     GPIO2_REG(0x58)
+#define GPIO_INT_POS_2     GPIO1_REG(0x74)
+#define GPIO_INT_POS_3     GPIO1_REG(0x78)
+#define GPIO_INT_POS_4     GPIO1_REG(0x7C)
+#define GPIO_INT_POS_5     GPIO1_REG(0xBC)
+
+/* same pin map as above, interrupt enable */
+#define GPIO_INT_EN_0      GPIO1_REG(0x80)
+#define GPIO_INT_EN_1      GPIO2_REG(0x60)
+#define GPIO_INT_EN_2      GPIO1_REG(0x84)
+#define GPIO_INT_EN_3      GPIO1_REG(0x88)
+#define GPIO_INT_EN_4      GPIO1_REG(0x8C)
+#define GPIO_INT_EN_5      GPIO1_REG(0xB8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define GPIO_INT_CLEAR_0   GPIO1_REG(0x90)
+#define GPIO_INT_CLEAR_1   GPIO2_REG(0x68)
+#define GPIO_INT_CLEAR_2   GPIO1_REG(0x94)
+#define GPIO_INT_CLEAR_3   GPIO1_REG(0x98)
+#define GPIO_INT_CLEAR_4   GPIO1_REG(0x9C)
+#define GPIO_INT_CLEAR_5   GPIO1_REG(0xB4)
+
+/* same pin map as above, 1=interrupt pending */
+#define GPIO_INT_STATUS_0  GPIO1_REG(0xA0)
+#define GPIO_INT_STATUS_1  GPIO2_REG(0x70)
+#define GPIO_INT_STATUS_2  GPIO1_REG(0xA4)
+#define GPIO_INT_STATUS_3  GPIO1_REG(0xA8)
+#define GPIO_INT_STATUS_4  GPIO1_REG(0xAC)
+#define GPIO_INT_STATUS_5  GPIO1_REG(0xB0)
+
+#endif
+
+#if defined(CONFIG_ARCH_QSD8X50)
+/* output value */
+#define GPIO_OUT_0         GPIO1_REG(0x00)  /* gpio  15-0   */
+#define GPIO_OUT_1         GPIO2_REG(0x00)  /* gpio  42-16  */
+#define GPIO_OUT_2         GPIO1_REG(0x04)  /* gpio  67-43  */
+#define GPIO_OUT_3         GPIO1_REG(0x08)  /* gpio  94-68  */
+#define GPIO_OUT_4         GPIO1_REG(0x0C)  /* gpio 103-95  */
+#define GPIO_OUT_5         GPIO1_REG(0x10)  /* gpio 121-104 */
+#define GPIO_OUT_6         GPIO1_REG(0x14)  /* gpio 152-122 */
+#define GPIO_OUT_7         GPIO1_REG(0x18)  /* gpio 164-153 */
+
+/* same pin map as above, output enable */
+#define GPIO_OE_0          GPIO1_REG(0x20)
+#define GPIO_OE_1          GPIO2_REG(0x08)
+#define GPIO_OE_2          GPIO1_REG(0x24)
+#define GPIO_OE_3          GPIO1_REG(0x28)
+#define GPIO_OE_4          GPIO1_REG(0x2C)
+#define GPIO_OE_5          GPIO1_REG(0x30)
+#define GPIO_OE_6          GPIO1_REG(0x34)
+#define GPIO_OE_7          GPIO1_REG(0x38)
+
+/* same pin map as above, input read */
+#define GPIO_IN_0          GPIO1_REG(0x50)
+#define GPIO_IN_1          GPIO2_REG(0x20)
+#define GPIO_IN_2          GPIO1_REG(0x54)
+#define GPIO_IN_3          GPIO1_REG(0x58)
+#define GPIO_IN_4          GPIO1_REG(0x5C)
+#define GPIO_IN_5          GPIO1_REG(0x60)
+#define GPIO_IN_6          GPIO1_REG(0x64)
+#define GPIO_IN_7          GPIO1_REG(0x68)
+
+/* same pin map as above, 1=edge 0=level interrup */
+#define GPIO_INT_EDGE_0    GPIO1_REG(0x70)
+#define GPIO_INT_EDGE_1    GPIO2_REG(0x50)
+#define GPIO_INT_EDGE_2    GPIO1_REG(0x74)
+#define GPIO_INT_EDGE_3    GPIO1_REG(0x78)
+#define GPIO_INT_EDGE_4    GPIO1_REG(0x7C)
+#define GPIO_INT_EDGE_5    GPIO1_REG(0x80)
+#define GPIO_INT_EDGE_6    GPIO1_REG(0x84)
+#define GPIO_INT_EDGE_7    GPIO1_REG(0x88)
+
+/* same pin map as above, 1=positive 0=negative */
+#define GPIO_INT_POS_0     GPIO1_REG(0x90)
+#define GPIO_INT_POS_1     GPIO2_REG(0x58)
+#define GPIO_INT_POS_2     GPIO1_REG(0x94)
+#define GPIO_INT_POS_3     GPIO1_REG(0x98)
+#define GPIO_INT_POS_4     GPIO1_REG(0x9C)
+#define GPIO_INT_POS_5     GPIO1_REG(0xA0)
+#define GPIO_INT_POS_6     GPIO1_REG(0xA4)
+#define GPIO_INT_POS_7     GPIO1_REG(0xA8)
+
+/* same pin map as above, interrupt enable */
+#define GPIO_INT_EN_0      GPIO1_REG(0xB0)
+#define GPIO_INT_EN_1      GPIO2_REG(0x60)
+#define GPIO_INT_EN_2      GPIO1_REG(0xB4)
+#define GPIO_INT_EN_3      GPIO1_REG(0xB8)
+#define GPIO_INT_EN_4      GPIO1_REG(0xBC)
+#define GPIO_INT_EN_5      GPIO1_REG(0xC0)
+#define GPIO_INT_EN_6      GPIO1_REG(0xC4)
+#define GPIO_INT_EN_7      GPIO1_REG(0xC8)
+
+/* same pin map as above, write 1 to clear interrupt */
+#define GPIO_INT_CLEAR_0   GPIO1_REG(0xD0)
+#define GPIO_INT_CLEAR_1   GPIO2_REG(0x68)
+#define GPIO_INT_CLEAR_2   GPIO1_REG(0xD4)
+#define GPIO_INT_CLEAR_3   GPIO1_REG(0xD8)
+#define GPIO_INT_CLEAR_4   GPIO1_REG(0xDC)
+#define GPIO_INT_CLEAR_5   GPIO1_REG(0xE0)
+#define GPIO_INT_CLEAR_6   GPIO1_REG(0xE4)
+#define GPIO_INT_CLEAR_7   GPIO1_REG(0xE8)
+
+/* same pin map as above, 1=interrupt pending */
+#define GPIO_INT_STATUS_0  GPIO1_REG(0xF0)
+#define GPIO_INT_STATUS_1  GPIO2_REG(0x70)
+#define GPIO_INT_STATUS_2  GPIO1_REG(0xF4)
+#define GPIO_INT_STATUS_3  GPIO1_REG(0xF8)
+#define GPIO_INT_STATUS_4  GPIO1_REG(0xFC)
+#define GPIO_INT_STATUS_5  GPIO1_REG(0x100)
+#define GPIO_INT_STATUS_6  GPIO1_REG(0x104)
+#define GPIO_INT_STATUS_7  GPIO1_REG(0x108)
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
new file mode 100644
index 0000000..784e6f5
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/gpio.h
@@ -0,0 +1,43 @@
+/* linux/include/asm-arm/arch-msm/gpio.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Mike Lockwood <lockwood at android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_GPIO_H
+#define __ASM_ARCH_MSM_GPIO_H
+
+#include <linux/interrupt.h>
+#include <asm-generic/gpio.h>
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	__gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+	return __gpio_cansleep(gpio);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return __gpio_to_irq(gpio);
+}
+
+#endif
-- 
1.6.2.3




More information about the linux-arm-kernel mailing list