arm: msm: gpio support
Subsystems (3)
PATCH 1/4 arm: msm: gpio support
From: Daniel Walker <[email protected]>
This adds basic gpio support in MSM using gpiolib, as well as gpio interrupt support.
--- 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
arch/arm/Kconfig +1 -0
@@ -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
arch/arm/mach-msm/Makefile +1 -0
@@ -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
arch/arm/mach-msm/gpio.c new file +428 -0
428 lines not on this page · raw message
arch/arm/mach-msm/gpio_hw.h new file +187 -0
187 lines not on this page · raw message
arch/arm/mach-msm/include/mach/gpio.h new file +43 -0
43 lines not on this page · raw message
Signature · 1 line
1.6.2.3
PATCH 2/4 arm: msm: GPIO support for HTC Dream
From: Pavel Machek <[email protected]>
Add GPIO support for HTC Dream.
--- arch/arm/mach-msm/Makefile | 2 +- arch/arm/mach-msm/board-trout-gpio.c | 112 ++++++++++++++++++++++++ arch/arm/mach-msm/board-trout.h | 157 ++++++++++++++++++++++++++++++++++ 3 files changed, 270 insertions(+), 1 deletions(-) create mode 100644 arch/arm/mach-msm/board-trout-gpio.c
arch/arm/mach-msm/Makefile +1 -1
@@ -9,5 +9,5 @@ obj-y += gpio.o obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o obj-$(CONFIG_MSM_SMD) += last_radio_log.o -obj-$(CONFIG_MACH_TROUT) += board-trout.o +obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o
arch/arm/mach-msm/board-trout-gpio.c new file +112 -0
112 lines not on this page · raw message
arch/arm/mach-msm/board-trout.h +157 -0
162 lines not on this page · raw message
Signature · 1 line
1.6.2.3
PATCH 3/4 arm: msm: trout: add trout specific gpio interrupts
From: Daniel Walker <[email protected]>
This adds the interrupt layer onto the initial trout gpio changes.
There changes were adapted from the Google driver which lists Arve Hjønnevåg <[email protected]> as the author.
--- arch/arm/mach-msm/board-trout-gpio.c | 114 ++++++++++++++++++++++++++++++++++ 1 files changed, 114 insertions(+), 0 deletions(-)
arch/arm/mach-msm/board-trout-gpio.c +114 -0
@@ -19,6 +19,15 @@#include "board-trout.h" +static uint8_t trout_int_mask[2 ] = { + [0 ] =0xff ,/* mask all interrupts */ + [1 ] =0xff , +}; +static uint8_t trout_sleep_int_mask[] = { + [0 ] =0xff , + [1 ] =0xff , +}; +struct msm_gpio_chip {struct gpio_chip chip;void __iomem *reg;/* Base of register bank */
@@ -95,16 +104,121 @@ static struct msm_gpio_chip msm_gpio_banks[] = { TROUT_GPIO_BANK("VIRTUAL", 0x12, TROUT_GPIO_VIRTUAL_BASE, 0), }; +static void trout_gpio_irq_ack (unsigned int irq) +{ +int bank =TROUT_INT_TO_BANK (irq); +uint8_t mask =TROUT_INT_TO_MASK (irq); +int reg =TROUT_BANK_TO_STAT_REG (bank); +/*printk(KERN_INFO "trout_gpio_irq_ack irq %d\n", irq);*/ +writeb (mask,TROUT_CPLD_BASE + reg); +} + +static void trout_gpio_irq_mask (unsigned int irq) +{ +unsigned long flags; +uint8_t reg_val; +int bank =TROUT_INT_TO_BANK (irq); +uint8_t mask =TROUT_INT_TO_MASK (irq); +int reg =TROUT_BANK_TO_MASK_REG (bank); + +local_irq_save (flags); + reg_val = trout_int_mask[bank] |= mask; +/*printk(KERN_INFO "trout_gpio_irq_mask irq %d => %d:%02x\n", +irq, bank, reg_val);*/ +writeb (reg_val,TROUT_CPLD_BASE + reg); +local_irq_restore (flags); +} + +static void trout_gpio_irq_unmask (unsigned int irq) +{ +unsigned long flags; +uint8_t reg_val; +int bank =TROUT_INT_TO_BANK (irq); +uint8_t mask =TROUT_INT_TO_MASK (irq); +int reg =TROUT_BANK_TO_MASK_REG (bank); + +local_irq_save (flags); + reg_val = trout_int_mask[bank] &= ~mask; +/*printk(KERN_INFO "trout_gpio_irq_unmask irq %d => %d:%02x\n", +irq, bank, reg_val);*/ +writeb (reg_val,TROUT_CPLD_BASE + reg); +local_irq_restore (flags); +} + +int trout_gpio_irq_set_wake (unsigned int irq,unsigned int on) +{ +unsigned long flags; +int bank =TROUT_INT_TO_BANK (irq); +uint8_t mask =TROUT_INT_TO_MASK (irq); + +local_irq_save (flags); +if (on) + trout_sleep_int_mask[bank] &= ~mask; +else + trout_sleep_int_mask[bank] |= mask; +local_irq_restore (flags); +return 0 ; +} + +static void trout_gpio_irq_handler (unsigned int irq,struct irq_desc *desc) +{ +int j, m; +unsigned v; +int bank; +int stat_reg; +int int_base =TROUT_INT_START ; +uint8_t int_mask; + +for (bank =0 ; bank <2 ; bank++) { + stat_reg =TROUT_BANK_TO_STAT_REG (bank); + v =readb (TROUT_CPLD_BASE + stat_reg); + int_mask = trout_int_mask[bank]; +if (v & int_mask) { +writeb (v & int_mask,TROUT_CPLD_BASE + stat_reg); +printk (KERN_ERR "trout_gpio_irq_handler: got masked " +"interrupt: %d:%02x\n" , bank, v & int_mask); + } + v &= ~int_mask; +while (v) { + m = v & -v; + j =fls (m) -1 ; +/*printk(KERN_INFO "msm_gpio_irq_handler %d:%02x %02x b" +"it %d irq %d\n", bank, v, m, j, int_base + j);*/ + v &= ~m; +generic_handle_irq (int_base + j); + } + int_base +=TROUT_INT_BANK0_COUNT ; + } + desc->chip->ack (irq); +} + +static struct irq_chip trout_gpio_irq_chip = { + .name ="troutgpio" , + .ack = trout_gpio_irq_ack, + .mask = trout_gpio_irq_mask, + .unmask = trout_gpio_irq_unmask, + .set_wake = trout_gpio_irq_set_wake, +}; +/* * Called from the processor-specific init to enable GPIO pin support. */ int __init trout_init_gpio (void ) {int i; +for (i =TROUT_INT_START ; i <=TROUT_INT_END ; i++) { +set_irq_chip (i, &trout_gpio_irq_chip); +set_irq_handler (i, handle_edge_irq); +set_irq_flags (i,IRQF_VALID ); + }for (i =0 ; i <ARRAY_SIZE (msm_gpio_banks); i++)gpiochip_add (&msm_gpio_banks[i].chip); +set_irq_type (MSM_GPIO_TO_INT (17 ),IRQF_TRIGGER_HIGH ); +set_irq_chained_handler (MSM_GPIO_TO_INT (17 ), trout_gpio_irq_handler); +set_irq_wake (MSM_GPIO_TO_INT (17 ),1 ); +return 0 ; }
Signature · 1 line
1.6.2.3
PATCH 4/4 arm: msm: trout add mmc support
This adds the platform data for MMC on trout.
--- arch/arm/mach-msm/Makefile | 2 +- arch/arm/mach-msm/board-trout-mmc.c | 189 +++++++++++++++++++++++++++++++++++ arch/arm/mach-msm/board-trout.c | 11 ++ 3 files changed, 201 insertions(+), 1 deletions(-) create mode 100644 arch/arm/mach-msm/board-trout-mmc.c
arch/arm/mach-msm/Makefile +1 -1
@@ -9,5 +9,5 @@ obj-y += gpio.o obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o obj-$(CONFIG_MSM_SMD) += last_radio_log.o -obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o +obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o
arch/arm/mach-msm/board-trout-mmc.c new file +189 -0
189 lines not on this page · raw message
arch/arm/mach-msm/board-trout.c +11 -0
@@ -30,6 +30,8 @@#include "devices.h" #include "board-trout.h" +extern int trout_init_mmc (unsigned int ); +static struct platform_device *devices[]__initdata = { &msm_device_uart3, &msm_device_smd,
@@ -56,7 +58,16 @@ static void __init trout_fixup(struct machine_desc *desc, struct tag *tags,static void __init trout_init (void ) { +int rc; +platform_add_devices (devices,ARRAY_SIZE (devices)); + +#ifdef CONFIG_MMC + rc =trout_init_mmc (system_rev); +if (rc) +printk (KERN_CRIT "%s: MMC init failure (%d)\n" , __func__, rc); +#endif + }static struct map_desc trout_io_desc[]__initdata = {
Signature · 1 line
1.6.2.3
PATCH 1/4 arm: msm: gpio support
In reply to Daniel WalkerQuoted 59 lines · Daniel Walker
From: Daniel Walker <[email protected]>
This adds basic gpio support in MSM using gpiolib, as well as gpio interrupt support.
Signed-off-by Daniel Walker <[email protected]>--- 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.harch/arm/Kconfig +1
-0@@ -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 memoryarch/arm/mach-msm/Makefile +1
-0@@ -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.oarch/arm/mach-msm/gpio.c new file +12
-0@@ -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
arch/arm/mach-msm/gpio.c line 22
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+* 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 <linux/io.h>
arch/arm/mach-msm/gpio.c line 23
Quoted 1 line
arch/arm/mach-msm/gpio.c new file +1
-0+#include <asm/irq.h>
This one is not needed.
arch/arm/mach-msm/gpio.c line 24
Quoted 1 line
arch/arm/mach-msm/gpio.c new file +1
-0+#include <linux/irq.h>
This includes the <asm/irq.h> for you.
Quoted 14 lines
arch/arm/mach-msm/gpio.c new file +14
-0+#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
arch/arm/mach-msm/gpio.c line 48
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+#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);
Can the code be re-ordered to eliminate the prototypes?
Quoted 60 lines
arch/arm/mach-msm/gpio.c new file +60
-0+ +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),
arch/arm/mach-msm/gpio.c line 118
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+#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);
The () around offset are not needed.
arch/arm/mach-msm/gpio.c line 122
Quoted 4 lines
arch/arm/mach-msm/gpio.c new file +4
-0+unsigned v; + +spin_lock_irqsave (&old_chip->lock, irq_flags); + b =1U << (offset);
Not needed. You already did it above.
arch/arm/mach-msm/gpio.c line 125
Quoted 3 lines
arch/arm/mach-msm/gpio.c new file +3
-0+ + v =readl (old_chip->regs.oe); +writel (v & (~b), old_chip->regs.oe);
Again, the () around ~b are not needed. There are a number of these in this file.
Quoted 102 lines
arch/arm/mach-msm/gpio.c new file +102
-0+ +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); +}
arch/arm/mach-msm/gpio.c line 237
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+ +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);
Urk... That's a bit confusing...
You might want to make this a macro or an inline function with some kind of comment.
Quoted 19 lines
arch/arm/mach-msm/gpio.c new file +19
-0+ +#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;
arch/arm/mach-msm/gpio.c line 266
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+ +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
Align the #if/#endif to the first column.
Quoted 190 lines
arch/arm/mach-msm/gpio.c new file +162
-0+/* 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);arch/arm/mach-msm/gpio_hw.h new file +22
-0@@ -0,0 +1,187 @@ +/* arch/arm/mach-msm/gpio_hw.h +* +* Copyright (C) 2007 Google, Inc. +* Author: Brian Swetland <[email protected]> +* +* 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
arch/arm/mach-msm/gpio_hw.h line 32
Quoted 10 lines
arch/arm/mach-msm/gpio_hw.h new file +10
-0+** +** 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. +*/ +
All the #define'd names in this file are pretty generic. You should probably add a prefix (MSM_ ?) to all of them.
Also, you should use tabs instead of spaces between the #define <name><tabs><something>
Quoted 171 lines
arch/arm/mach-msm/gpio_hw.h new file +155
-0+#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 arch/arm/mach-msm/include/mach/gpio.h new file +10
-0@@ -0,0 +1,43 @@ +/* linux/include/asm-arm/arch-msm/gpio.h +* +* Copyright (C) 2007 Google, Inc. +* Author: Mike Lockwood <[email protected]> +* +* 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,
arch/arm/mach-msm/include/mach/gpio.h line 20
Quoted 10 lines
arch/arm/mach-msm/include/mach/gpio.h new file +10
-0+* 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>
Why is this included?
Quoted 12 lines
arch/arm/mach-msm/include/mach/gpio.h new file +12
-0+#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); +} +
arch/arm/mach-msm/include/mach/gpio.h line 42
Quoted 10 lines
arch/arm/mach-msm/include/mach/gpio.h new file +10
-0+static inline int gpio_cansleep (unsigned gpio) +{ +return __gpio_cansleep (gpio); +} + +static inline int gpio_to_irq (unsigned gpio) +{ +return __gpio_to_irq (gpio); +} +
These could all just be:
#define gpio_get_value __gpio_get_value #define gpio_set_value __gpio_set_value #define gpio_cansleep __gpio_cansleep #define gpio_to_irq __gpio_to_irq
arch/arm/mach-msm/include/mach/gpio.h line 43
Quoted 1 line
arch/arm/mach-msm/include/mach/gpio.h new file +1
-0+#endif
Regards,
Hartley
PATCH 1/4 arm: msm: gpio support
Quoted 2 lines · H Hartley Sweeten
Quoted 1 line · Daniel Walker
From: Daniel Walker <[email protected]>
...
Quoted 13 lines
arch/arm/mach-msm/gpio.c
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+ +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);Urk... That's a bit confusing...
Quoted 3 lines
You might want to make this a macro or an inline function with some kind of comment.
On a related note, why did you inline msm_gpio_clear_detect_status? It is used from two other functions.
Quoted 14 lines
Quoted 14 lines
(quoted diff) +14
-0+ +#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); +} +
...
Signature · 1 line
Arve Hj?nnev?g
PATCH 1/4 arm: msm: gpio support
Quoted 18 lines · Arve Hj?nnev?g
Quoted 2 lines · H Hartley Sweeten
Quoted 1 line · Daniel Walker
From: Daniel Walker <[email protected]>
...
Quoted 13 lines
arch/arm/mach-msm/gpio.c line 237
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+ +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);Urk... That's a bit confusing...
Quoted 7 lines
Quoted 3 lines
You might want to make this a macro or an inline function with some kind of comment.
On a related note, why did you inline
msm_gpio_clear_detect_status? It is used from two other functions.
You mean other places in the Android tree?
Daniel
PATCH 1/4 arm: msm: gpio support
2010/3/31 Daniel Walker <[email protected]>:
Quoted 23 lines · Arve Hj?nnev?g
Quoted 22 lines
Quoted 2 lines · H Hartley Sweeten
Quoted 1 line · Daniel Walker
From: Daniel Walker <[email protected]>
...
Quoted 16 lines
arch/arm/mach-msm/gpio.c
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+ +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);Urk... That's a bit confusing...
You might want to make this a macro or an inline function with some kind of comment.
Quoted 5 lines
Quoted 3 lines
On a related note, why did you inline
msm_gpio_clear_detect_status? It is used from two other functions.You mean other places in the Android tree?
No, you copied it three times in this file.
Signature · 1 line
Arve Hj?nnev?g
PATCH 1/4 arm: msm: gpio support
Quoted 24 lines · Arve Hj?nnev?g
2010/3/31 Daniel Walker <[email protected]>:
Quoted 23 lines · Arve Hj?nnev?g
Quoted 22 lines
Quoted 2 lines · H Hartley Sweeten
Quoted 1 line · Daniel Walker
From: Daniel Walker <[email protected]>
...
Quoted 16 lines
arch/arm/mach-msm/gpio.c line 237
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+ +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);Urk... That's a bit confusing...
You might want to make this a macro or an inline function with some kind of comment.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
On a related note, why did you inline
msm_gpio_clear_detect_status? It is used from two other functions.You mean other places in the Android tree?
No, you copied it three times in this file.
Oh, well it was part of the API elimination , but it's helpful when doing clean up to have stuff all unrolled so optimization possibilities present themselves more easily .. You think I should convert it into an inline?
Daniel
PATCH 1/4 arm: msm: gpio support
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
Quoted 9 lines
arch/arm/mach-msm/gpio.c line 237
Quoted 3 lines
arch/arm/mach-msm/gpio.c new file +3
-0+spin_lock_irqsave (&msm_chip->lock, irq_flags); + + b =1U << (irq -FIRST_GPIO_IRQ - msm_chip->chip.base);Urk... That's a bit confusing...
You might want to make this a macro or an inline function with some kind of comment.
On a related note, why did you inline
msm_gpio_clear_detect_status? It is used from two other functions.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
You mean other places in the Android tree?
No, you copied it three times in this file.
Oh, well it was part of the API elimination , but it's helpful when doing clean up to have stuff all unrolled so optimization possibilities present themselves more easily .. You think I should convert it into an inline?
I guess so. Premature optimalization is sqrt(all evil).
Really, leave that to compiler.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
PATCH 1/4 arm: msm: gpio support
In reply to H Hartley SweetenQuoted 99 lines · H Hartley Sweeten
Quoted 59 lines · Daniel Walker
From: Daniel Walker <[email protected]>
This adds basic gpio support in MSM using gpiolib, as well as gpio interrupt support.
Signed-off-by Daniel Walker <[email protected]>--- 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.harch/arm/Kconfig +1
-0@@ -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 memoryarch/arm/mach-msm/Makefile +1
-0@@ -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.oarch/arm/mach-msm/gpio.c new file +12
-0@@ -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 arch/arm/mach-msm/gpio.c line 22
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+* 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 <
linux/io.h>arch/arm/mach-msm/gpio.c line 23
Quoted 1 line
arch/arm/mach-msm/gpio.c new file +1
-0+#include <asm/irq.h> This one is not needed.
arch/arm/mach-msm/gpio.c line 24
Quoted 1 line
arch/arm/mach-msm/gpio.c new file +1
-0+#include <linux/irq.h> This includes the <
asm/irq.h> for you.Quoted 18 lines
arch/arm/mach-msm/gpio.c new file +18
-0+#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 +
Quoted 8 lines
arch/arm/mach-msm/gpio.c line 48
Quoted 6 lines
arch/arm/mach-msm/gpio.c new file +6
-0+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);Can the code be re-ordered to eliminate the prototypes?
Yeah, I'm sure I can work that out.
Quoted 78 lines
Quoted 60 lines
arch/arm/mach-msm/gpio.c new file +60
-0+ +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),arch/arm/mach-msm/gpio.c line 118
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+#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);The () around offset are not needed.
arch/arm/mach-msm/gpio.c line 122
Quoted 4 lines
arch/arm/mach-msm/gpio.c new file +4
-0+unsigned v; + +spin_lock_irqsave (&old_chip->lock, irq_flags); + b =1U << (offset);
Quoted 7 lines
Not needed. You already did it above.
arch/arm/mach-msm/gpio.c line 125
Quoted 3 lines
arch/arm/mach-msm/gpio.c new file +3
-0+ + v =readl (old_chip->regs.oe); +writel (v & (~b), old_chip->regs.oe);Again, the () around ~b are not needed. There are a number of these in this file.
Ok ..
Quoted 115 lines
Quoted 102 lines
arch/arm/mach-msm/gpio.c new file +102
-0+ +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); +}arch/arm/mach-msm/gpio.c line 237
Quoted 10 lines
arch/arm/mach-msm/gpio.c new file +10
-0+ +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);Urk... That's a bit confusing...
Quoted 2 lines
You might want to make this a macro or an inline function with some kind of comment.
Ok ..
Quoted 23 lines
Quoted 23 lines
arch/arm/mach-msm/gpio.c new file +23
-0+ +#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);
Quoted 8 lines
arch/arm/mach-msm/gpio.c line 266
Quoted 6 lines
arch/arm/mach-msm/gpio.c new file +6
-0+ + v =readl (msm_chip->regs.int_edge); +/* level triggered interrupts are also latched */ +if (!(v & b)) { + +#if MSM_GPIO_BROKEN_INT_CLEAR Align the #if/#endif to the first column.
Yeah .
Quoted 204 lines
Quoted 190 lines
arch/arm/mach-msm/gpio.c new file +162
-0+/* 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);arch/arm/mach-msm/gpio_hw.h new file +22
-0@@ -0,0 +1,187 @@ +/* arch/arm/mach-msm/gpio_hw.h +* +* Copyright (C) 2007 Google, Inc. +* Author: Brian Swetland <[email protected]> +* +* 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 arch/arm/mach-msm/gpio_hw.h line 32
Quoted 10 lines
arch/arm/mach-msm/gpio_hw.h new file +10
-0+** +** 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. +*/ +All the #define'd names in this file are pretty generic. You should probably add a prefix (
MSM_?) to all of them.
Quoted 1 line
Also, you should use tabs instead of spaces between the #define <name><tabs><something>
No problem ..
Quoted 175 lines
Quoted 175 lines
arch/arm/mach-msm/gpio_hw.h new file +155
-0+#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 arch/arm/mach-msm/include/mach/gpio.h new file +14
-0@@ -0,0 +1,43 @@ +/* linux/include/asm-arm/arch-msm/gpio.h +* +* Copyright (C) 2007 Google, Inc. +* Author: Mike Lockwood <[email protected]> +* +* 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. +*
Quoted 8 lines
arch/arm/mach-msm/include/mach/gpio.h line 20
Quoted 6 lines
arch/arm/mach-msm/include/mach/gpio.h new file +6
-0+*/ + +#ifndef __ASM_ARCH_MSM_GPIO_H +#define __ASM_ARCH_MSM_GPIO_H + +#include <linux/interrupt.h> Why is this included?
Have to ask Mike Lockwood I guess, but I try removing it.
Quoted 25 lines
Quoted 12 lines
arch/arm/mach-msm/include/mach/gpio.h new file +12
-0+#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); +} +arch/arm/mach-msm/include/mach/gpio.h line 42
Quoted 10 lines
arch/arm/mach-msm/include/mach/gpio.h new file +10
-0+static inline int gpio_cansleep (unsigned gpio) +{ +return __gpio_cansleep (gpio); +} + +static inline int gpio_to_irq (unsigned gpio) +{ +return __gpio_to_irq (gpio); +} +These could all just be:
Quoted 4 lines
#define gpio_get_value __gpio_get_value #define gpio_set_value __gpio_set_value #define gpio_cansleep __gpio_cansleep #define gpio_to_irq __gpio_to_irq
Much cleaner .. I'll do that.
Thanks for all the good comments.
Daniel