2008-02-04 22:28:22 -08:00
/*
2009-01-20 12:09:06 +08:00
* linux / arch / arm / plat - pxa / gpio . c
2008-02-04 22:28:22 -08:00
*
* Generic PXA GPIO handling
*
* Author : Nicolas Pitre
* Created : Jun 15 , 2001
* Copyright : MontaVista Software Inc .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
2012-04-13 15:15:45 +08:00
# include <linux/module.h>
2011-10-17 21:26:55 +08:00
# include <linux/clk.h>
# include <linux/err.h>
2011-07-26 10:53:52 +01:00
# include <linux/gpio.h>
2011-10-17 20:37:52 +08:00
# include <linux/gpio-pxa.h>
2008-02-04 22:28:22 -08:00
# include <linux/init.h>
2008-03-04 11:42:26 +08:00
# include <linux/irq.h>
2012-04-13 15:15:45 +08:00
# include <linux/irqdomain.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2012-04-13 15:15:45 +08:00
# include <linux/of.h>
# include <linux/of_device.h>
2011-10-17 20:37:52 +08:00
# include <linux/platform_device.h>
2011-04-22 22:03:11 +02:00
# include <linux/syscore_ops.h>
2009-06-19 22:56:09 +02:00
# include <linux/slab.h>
2008-02-04 22:28:22 -08:00
2012-07-31 14:13:09 +08:00
# include <asm/mach/irq.h>
2012-01-03 15:52:42 -06:00
# include <mach/irqs.h>
2011-10-17 20:37:52 +08:00
/*
* We handle the GPIOs by banks , each bank covers up to 32 GPIOs with
* one set of registers . The register offsets are organized below :
*
* GPLR GPDR GPSR GPCR GRER GFER GEDR
* BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048
* BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C
* BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050
*
* BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148
* BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C
* BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150
*
* NOTE :
* BANK 3 is only available on PXA27x and later processors .
* BANK 4 and 5 are only available on PXA935
*/
# define GPLR_OFFSET 0x00
# define GPDR_OFFSET 0x0C
# define GPSR_OFFSET 0x18
# define GPCR_OFFSET 0x24
# define GRER_OFFSET 0x30
# define GFER_OFFSET 0x3C
# define GEDR_OFFSET 0x48
# define GAFR_OFFSET 0x54
2011-10-17 21:07:15 +08:00
# define ED_MASK_OFFSET 0x9C /* GPIO edge detection for AP side */
2011-10-17 20:37:52 +08:00
# define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
2008-02-04 22:28:22 -08:00
2009-01-07 11:30:49 +08:00
int pxa_last_gpio ;
2012-07-22 16:55:44 +02:00
static int irq_base ;
2009-01-07 11:30:49 +08:00
2012-04-13 15:15:45 +08:00
# ifdef CONFIG_OF
static struct irq_domain * domain ;
2012-07-25 17:35:39 +02:00
static struct device_node * pxa_gpio_of_node ;
2012-04-13 15:15:45 +08:00
# endif
2008-02-04 22:28:22 -08:00
struct pxa_gpio_chip {
struct gpio_chip chip ;
2009-01-07 18:01:51 +08:00
void __iomem * regbase ;
char label [ 10 ] ;
unsigned long irq_mask ;
unsigned long irq_edge_rise ;
unsigned long irq_edge_fall ;
2012-04-22 13:37:24 +02:00
int ( * set_wake ) ( unsigned int gpio , unsigned int on ) ;
2009-01-07 18:01:51 +08:00
# ifdef CONFIG_PM
unsigned long saved_gplr ;
unsigned long saved_gpdr ;
unsigned long saved_grer ;
unsigned long saved_gfer ;
# endif
2008-02-04 22:28:22 -08:00
} ;
2011-10-10 16:03:51 +08:00
enum {
PXA25X_GPIO = 0 ,
PXA26X_GPIO ,
PXA27X_GPIO ,
PXA3XX_GPIO ,
PXA93X_GPIO ,
MMP_GPIO = 0x10 ,
} ;
2009-01-07 18:01:51 +08:00
static DEFINE_SPINLOCK ( gpio_lock ) ;
static struct pxa_gpio_chip * pxa_gpio_chips ;
2011-10-10 16:03:51 +08:00
static int gpio_type ;
2011-10-17 20:37:52 +08:00
static void __iomem * gpio_reg_base ;
2009-01-07 18:01:51 +08:00
# define for_each_gpio_chip(i, c) \
for ( i = 0 , c = & pxa_gpio_chips [ 0 ] ; i < = pxa_last_gpio ; i + = 32 , c + + )
static inline void __iomem * gpio_chip_base ( struct gpio_chip * c )
{
return container_of ( c , struct pxa_gpio_chip , chip ) - > regbase ;
}
2011-06-13 10:42:19 +02:00
static inline struct pxa_gpio_chip * gpio_to_pxachip ( unsigned gpio )
2009-01-07 18:01:51 +08:00
{
return & pxa_gpio_chips [ gpio_to_bank ( gpio ) ] ;
}
2011-10-10 16:03:51 +08:00
static inline int gpio_is_pxa_type ( int type )
{
return ( type & MMP_GPIO ) = = 0 ;
}
static inline int gpio_is_mmp_type ( int type )
{
return ( type & MMP_GPIO ) ! = 0 ;
}
2011-10-17 20:37:52 +08:00
/* GPIO86/87/88/89 on PXA26x have their direction bits in PXA_GPDR(2 inverted,
* as well as their Alternate Function value being ' 1 ' for GPIO in GAFRx .
*/
static inline int __gpio_is_inverted ( int gpio )
{
if ( ( gpio_type = = PXA26X_GPIO ) & & ( gpio > 85 ) )
return 1 ;
return 0 ;
}
/*
* On PXA25x and PXA27x , GAFRx and GPDRx together decide the alternate
* function of a GPIO , and GPDRx cannot be altered once configured . It
* is attributed as " occupied " here ( I know this terminology isn ' t
* accurate , you are welcome to propose a better one : - )
*/
static inline int __gpio_is_occupied ( unsigned gpio )
{
struct pxa_gpio_chip * pxachip ;
void __iomem * base ;
unsigned long gafr = 0 , gpdr = 0 ;
int ret , af = 0 , dir = 0 ;
pxachip = gpio_to_pxachip ( gpio ) ;
base = gpio_chip_base ( & pxachip - > chip ) ;
gpdr = readl_relaxed ( base + GPDR_OFFSET ) ;
switch ( gpio_type ) {
case PXA25X_GPIO :
case PXA26X_GPIO :
case PXA27X_GPIO :
gafr = readl_relaxed ( base + GAFR_OFFSET ) ;
af = ( gafr > > ( ( gpio & 0xf ) * 2 ) ) & 0x3 ;
dir = gpdr & GPIO_bit ( gpio ) ;
if ( __gpio_is_inverted ( gpio ) )
ret = ( af ! = 1 ) | | ( dir = = 0 ) ;
else
ret = ( af ! = 0 ) | | ( dir ! = 0 ) ;
break ;
default :
ret = gpdr & GPIO_bit ( gpio ) ;
break ;
}
return ret ;
}
2011-10-10 16:03:51 +08:00
static int pxa_gpio_to_irq ( struct gpio_chip * chip , unsigned offset )
{
2012-07-22 16:55:44 +02:00
return chip - > base + offset + irq_base ;
2011-10-10 16:03:51 +08:00
}
int pxa_irq_to_gpio ( int irq )
{
2012-07-22 16:55:44 +02:00
return irq - irq_base ;
2011-10-10 16:03:51 +08:00
}
2008-02-04 22:28:22 -08:00
static int pxa_gpio_direction_input ( struct gpio_chip * chip , unsigned offset )
{
2009-01-07 18:01:51 +08:00
void __iomem * base = gpio_chip_base ( chip ) ;
uint32_t value , mask = 1 < < offset ;
unsigned long flags ;
spin_lock_irqsave ( & gpio_lock , flags ) ;
2011-10-14 17:24:03 +08:00
value = readl_relaxed ( base + GPDR_OFFSET ) ;
2008-11-26 18:12:04 +08:00
if ( __gpio_is_inverted ( chip - > base + offset ) )
value | = mask ;
else
value & = ~ mask ;
2011-10-14 17:24:03 +08:00
writel_relaxed ( value , base + GPDR_OFFSET ) ;
2008-02-04 22:28:22 -08:00
2009-01-07 18:01:51 +08:00
spin_unlock_irqrestore ( & gpio_lock , flags ) ;
2008-02-04 22:28:22 -08:00
return 0 ;
}
static int pxa_gpio_direction_output ( struct gpio_chip * chip ,
2009-01-07 18:01:51 +08:00
unsigned offset , int value )
2008-02-04 22:28:22 -08:00
{
2009-01-07 18:01:51 +08:00
void __iomem * base = gpio_chip_base ( chip ) ;
uint32_t tmp , mask = 1 < < offset ;
unsigned long flags ;
2011-10-14 17:24:03 +08:00
writel_relaxed ( mask , base + ( value ? GPSR_OFFSET : GPCR_OFFSET ) ) ;
2009-01-07 18:01:51 +08:00
spin_lock_irqsave ( & gpio_lock , flags ) ;
2011-10-14 17:24:03 +08:00
tmp = readl_relaxed ( base + GPDR_OFFSET ) ;
2008-11-26 18:12:04 +08:00
if ( __gpio_is_inverted ( chip - > base + offset ) )
tmp & = ~ mask ;
else
tmp | = mask ;
2011-10-14 17:24:03 +08:00
writel_relaxed ( tmp , base + GPDR_OFFSET ) ;
2008-02-04 22:28:22 -08:00
2009-01-07 18:01:51 +08:00
spin_unlock_irqrestore ( & gpio_lock , flags ) ;
2008-02-04 22:28:22 -08:00
return 0 ;
}
static int pxa_gpio_get ( struct gpio_chip * chip , unsigned offset )
{
2011-10-14 17:24:03 +08:00
return readl_relaxed ( gpio_chip_base ( chip ) + GPLR_OFFSET ) & ( 1 < < offset ) ;
2008-02-04 22:28:22 -08:00
}
static void pxa_gpio_set ( struct gpio_chip * chip , unsigned offset , int value )
{
2011-10-14 17:24:03 +08:00
writel_relaxed ( 1 < < offset , gpio_chip_base ( chip ) +
2009-01-07 18:01:51 +08:00
( value ? GPSR_OFFSET : GPCR_OFFSET ) ) ;
2008-02-04 22:28:22 -08:00
}
2012-07-25 17:35:39 +02:00
# ifdef CONFIG_OF_GPIO
static int pxa_gpio_of_xlate ( struct gpio_chip * gc ,
const struct of_phandle_args * gpiospec ,
u32 * flags )
{
if ( gpiospec - > args [ 0 ] > pxa_last_gpio )
return - EINVAL ;
if ( gc ! = & pxa_gpio_chips [ gpiospec - > args [ 0 ] / 32 ] . chip )
return - EINVAL ;
if ( flags )
* flags = gpiospec - > args [ 1 ] ;
return gpiospec - > args [ 0 ] % 32 ;
}
# endif
2012-04-22 13:37:24 +02:00
static int __devinit pxa_init_gpio_chip ( int gpio_end ,
int ( * set_wake ) ( unsigned int , unsigned int ) )
2009-01-06 17:37:37 +08:00
{
2009-01-07 18:01:51 +08:00
int i , gpio , nbanks = gpio_to_bank ( gpio_end ) + 1 ;
struct pxa_gpio_chip * chips ;
2009-01-06 17:37:37 +08:00
2009-06-19 22:56:09 +02:00
chips = kzalloc ( nbanks * sizeof ( struct pxa_gpio_chip ) , GFP_KERNEL ) ;
2009-01-07 18:01:51 +08:00
if ( chips = = NULL ) {
pr_err ( " %s: failed to allocate GPIO chips \n " , __func__ ) ;
return - ENOMEM ;
2009-01-06 17:37:37 +08:00
}
2009-01-07 18:01:51 +08:00
for ( i = 0 , gpio = 0 ; i < nbanks ; i + + , gpio + = 32 ) {
struct gpio_chip * c = & chips [ i ] . chip ;
2008-03-04 11:42:26 +08:00
2009-01-07 18:01:51 +08:00
sprintf ( chips [ i ] . label , " gpio-%d " , i ) ;
2011-10-17 20:37:52 +08:00
chips [ i ] . regbase = gpio_reg_base + BANK_OFF ( i ) ;
2012-04-22 13:37:24 +02:00
chips [ i ] . set_wake = set_wake ;
2009-01-07 18:01:51 +08:00
c - > base = gpio ;
c - > label = chips [ i ] . label ;
c - > direction_input = pxa_gpio_direction_input ;
c - > direction_output = pxa_gpio_direction_output ;
c - > get = pxa_gpio_get ;
c - > set = pxa_gpio_set ;
2011-10-10 16:03:51 +08:00
c - > to_irq = pxa_gpio_to_irq ;
2012-07-25 17:35:39 +02:00
# ifdef CONFIG_OF_GPIO
c - > of_node = pxa_gpio_of_node ;
c - > of_xlate = pxa_gpio_of_xlate ;
c - > of_gpio_n_cells = 2 ;
# endif
2009-01-07 18:01:51 +08:00
/* number of GPIOs on last bank may be less than 32 */
c - > ngpio = ( gpio + 31 > gpio_end ) ? ( gpio_end - gpio + 1 ) : 32 ;
gpiochip_add ( c ) ;
}
pxa_gpio_chips = chips ;
return 0 ;
}
2008-03-04 11:42:26 +08:00
2009-04-21 14:39:07 +08:00
/* Update only those GRERx and GFERx edge detection register bits if those
* bits are set in c - > irq_mask
*/
static inline void update_edge_detect ( struct pxa_gpio_chip * c )
{
uint32_t grer , gfer ;
2011-10-14 17:24:03 +08:00
grer = readl_relaxed ( c - > regbase + GRER_OFFSET ) & ~ c - > irq_mask ;
gfer = readl_relaxed ( c - > regbase + GFER_OFFSET ) & ~ c - > irq_mask ;
2009-04-21 14:39:07 +08:00
grer | = c - > irq_edge_rise & c - > irq_mask ;
gfer | = c - > irq_edge_fall & c - > irq_mask ;
2011-10-14 17:24:03 +08:00
writel_relaxed ( grer , c - > regbase + GRER_OFFSET ) ;
writel_relaxed ( gfer , c - > regbase + GFER_OFFSET ) ;
2009-04-21 14:39:07 +08:00
}
2010-11-29 11:18:26 +01:00
static int pxa_gpio_irq_type ( struct irq_data * d , unsigned int type )
2008-03-04 11:42:26 +08:00
{
2009-01-07 18:01:51 +08:00
struct pxa_gpio_chip * c ;
2011-10-10 16:03:51 +08:00
int gpio = pxa_irq_to_gpio ( d - > irq ) ;
2009-01-07 18:01:51 +08:00
unsigned long gpdr , mask = GPIO_bit ( gpio ) ;
2008-03-04 11:42:26 +08:00
2011-06-13 10:42:19 +02:00
c = gpio_to_pxachip ( gpio ) ;
2008-03-04 11:42:26 +08:00
if ( type = = IRQ_TYPE_PROBE ) {
/* Don't mess with enabled GPIOs using preconfigured edges or
* GPIOs set to alternate function or to output during probe
*/
2009-01-07 18:01:51 +08:00
if ( ( c - > irq_edge_rise | c - > irq_edge_fall ) & GPIO_bit ( gpio ) )
2008-03-04 11:42:26 +08:00
return 0 ;
2008-03-04 17:18:38 +08:00
if ( __gpio_is_occupied ( gpio ) )
2008-03-04 11:42:26 +08:00
return 0 ;
2008-03-04 17:18:38 +08:00
2008-03-04 11:42:26 +08:00
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING ;
}
2011-10-14 17:24:03 +08:00
gpdr = readl_relaxed ( c - > regbase + GPDR_OFFSET ) ;
2009-01-07 18:01:51 +08:00
2008-11-26 18:12:04 +08:00
if ( __gpio_is_inverted ( gpio ) )
2011-10-14 17:24:03 +08:00
writel_relaxed ( gpdr | mask , c - > regbase + GPDR_OFFSET ) ;
2008-11-26 18:12:04 +08:00
else
2011-10-14 17:24:03 +08:00
writel_relaxed ( gpdr & ~ mask , c - > regbase + GPDR_OFFSET ) ;
2008-03-04 11:42:26 +08:00
if ( type & IRQ_TYPE_EDGE_RISING )
2009-01-07 18:01:51 +08:00
c - > irq_edge_rise | = mask ;
2008-03-04 11:42:26 +08:00
else
2009-01-07 18:01:51 +08:00
c - > irq_edge_rise & = ~ mask ;
2008-03-04 11:42:26 +08:00
if ( type & IRQ_TYPE_EDGE_FALLING )
2009-01-07 18:01:51 +08:00
c - > irq_edge_fall | = mask ;
2008-03-04 11:42:26 +08:00
else
2009-01-07 18:01:51 +08:00
c - > irq_edge_fall & = ~ mask ;
2008-03-04 11:42:26 +08:00
2009-04-21 14:39:07 +08:00
update_edge_detect ( c ) ;
2008-03-04 11:42:26 +08:00
2010-11-29 11:18:26 +01:00
pr_debug ( " %s: IRQ%d (GPIO%d) - edge%s%s \n " , __func__ , d - > irq , gpio ,
2008-03-04 11:42:26 +08:00
( ( type & IRQ_TYPE_EDGE_RISING ) ? " rising " : " " ) ,
( ( type & IRQ_TYPE_EDGE_FALLING ) ? " falling " : " " ) ) ;
return 0 ;
}
static void pxa_gpio_demux_handler ( unsigned int irq , struct irq_desc * desc )
{
2009-01-07 18:01:51 +08:00
struct pxa_gpio_chip * c ;
int loop , gpio , gpio_base , n ;
unsigned long gedr ;
2012-07-31 14:13:09 +08:00
struct irq_chip * chip = irq_desc_get_chip ( desc ) ;
chained_irq_enter ( chip , desc ) ;
2008-03-04 11:42:26 +08:00
do {
loop = 0 ;
2009-01-07 18:01:51 +08:00
for_each_gpio_chip ( gpio , c ) {
gpio_base = c - > chip . base ;
2011-10-14 17:24:03 +08:00
gedr = readl_relaxed ( c - > regbase + GEDR_OFFSET ) ;
2009-01-07 18:01:51 +08:00
gedr = gedr & c - > irq_mask ;
2011-10-14 17:24:03 +08:00
writel_relaxed ( gedr , c - > regbase + GEDR_OFFSET ) ;
2008-03-04 11:42:26 +08:00
2012-09-14 10:36:59 +08:00
for_each_set_bit ( n , & gedr , BITS_PER_LONG ) {
2009-01-07 18:01:51 +08:00
loop = 1 ;
2008-03-04 11:42:26 +08:00
2009-01-07 18:01:51 +08:00
generic_handle_irq ( gpio_to_irq ( gpio_base + n ) ) ;
}
2008-03-04 11:42:26 +08:00
}
} while ( loop ) ;
2012-07-31 14:13:09 +08:00
chained_irq_exit ( chip , desc ) ;
2008-03-04 11:42:26 +08:00
}
2010-11-29 11:18:26 +01:00
static void pxa_ack_muxed_gpio ( struct irq_data * d )
2008-03-04 11:42:26 +08:00
{
2011-10-10 16:03:51 +08:00
int gpio = pxa_irq_to_gpio ( d - > irq ) ;
2011-06-13 10:42:19 +02:00
struct pxa_gpio_chip * c = gpio_to_pxachip ( gpio ) ;
2009-01-07 18:01:51 +08:00
2011-10-14 17:24:03 +08:00
writel_relaxed ( GPIO_bit ( gpio ) , c - > regbase + GEDR_OFFSET ) ;
2008-03-04 11:42:26 +08:00
}
2010-11-29 11:18:26 +01:00
static void pxa_mask_muxed_gpio ( struct irq_data * d )
2008-03-04 11:42:26 +08:00
{
2011-10-10 16:03:51 +08:00
int gpio = pxa_irq_to_gpio ( d - > irq ) ;
2011-06-13 10:42:19 +02:00
struct pxa_gpio_chip * c = gpio_to_pxachip ( gpio ) ;
2009-01-07 18:01:51 +08:00
uint32_t grer , gfer ;
c - > irq_mask & = ~ GPIO_bit ( gpio ) ;
2011-10-14 17:24:03 +08:00
grer = readl_relaxed ( c - > regbase + GRER_OFFSET ) & ~ GPIO_bit ( gpio ) ;
gfer = readl_relaxed ( c - > regbase + GFER_OFFSET ) & ~ GPIO_bit ( gpio ) ;
writel_relaxed ( grer , c - > regbase + GRER_OFFSET ) ;
writel_relaxed ( gfer , c - > regbase + GFER_OFFSET ) ;
2008-03-04 11:42:26 +08:00
}
2012-04-22 13:37:24 +02:00
static int pxa_gpio_set_wake ( struct irq_data * d , unsigned int on )
{
int gpio = pxa_irq_to_gpio ( d - > irq ) ;
struct pxa_gpio_chip * c = gpio_to_pxachip ( gpio ) ;
if ( c - > set_wake )
return c - > set_wake ( gpio , on ) ;
else
return 0 ;
}
2010-11-29 11:18:26 +01:00
static void pxa_unmask_muxed_gpio ( struct irq_data * d )
2008-03-04 11:42:26 +08:00
{
2011-10-10 16:03:51 +08:00
int gpio = pxa_irq_to_gpio ( d - > irq ) ;
2011-06-13 10:42:19 +02:00
struct pxa_gpio_chip * c = gpio_to_pxachip ( gpio ) ;
2009-01-07 18:01:51 +08:00
c - > irq_mask | = GPIO_bit ( gpio ) ;
2009-04-21 14:39:07 +08:00
update_edge_detect ( c ) ;
2008-03-04 11:42:26 +08:00
}
static struct irq_chip pxa_muxed_gpio_chip = {
. name = " GPIO " ,
2010-11-29 11:18:26 +01:00
. irq_ack = pxa_ack_muxed_gpio ,
. irq_mask = pxa_mask_muxed_gpio ,
. irq_unmask = pxa_unmask_muxed_gpio ,
. irq_set_type = pxa_gpio_irq_type ,
2012-04-22 13:37:24 +02:00
. irq_set_wake = pxa_gpio_set_wake ,
2008-03-04 11:42:26 +08:00
} ;
2011-10-14 16:44:07 +08:00
static int pxa_gpio_nums ( void )
{
int count = 0 ;
# ifdef CONFIG_ARCH_PXA
if ( cpu_is_pxa25x ( ) ) {
# ifdef CONFIG_CPU_PXA26x
count = 89 ;
gpio_type = PXA26X_GPIO ;
# elif defined(CONFIG_PXA25x)
count = 84 ;
gpio_type = PXA26X_GPIO ;
# endif /* CONFIG_CPU_PXA26x */
} else if ( cpu_is_pxa27x ( ) ) {
count = 120 ;
gpio_type = PXA27X_GPIO ;
2012-11-15 17:06:06 +08:00
} else if ( cpu_is_pxa93x ( ) ) {
2011-10-14 16:44:07 +08:00
count = 191 ;
gpio_type = PXA93X_GPIO ;
} else if ( cpu_is_pxa3xx ( ) ) {
count = 127 ;
gpio_type = PXA3XX_GPIO ;
}
# endif /* CONFIG_ARCH_PXA */
# ifdef CONFIG_ARCH_MMP
if ( cpu_is_pxa168 ( ) | | cpu_is_pxa910 ( ) ) {
count = 127 ;
gpio_type = MMP_GPIO ;
} else if ( cpu_is_mmp2 ( ) ) {
count = 191 ;
2012-04-13 15:15:45 +08:00
gpio_type = MMP_GPIO ;
2011-10-14 16:44:07 +08:00
}
# endif /* CONFIG_ARCH_MMP */
return count ;
}
2012-08-13 14:36:10 +00:00
# ifdef CONFIG_OF
2012-04-13 15:15:45 +08:00
static struct of_device_id pxa_gpio_dt_ids [ ] = {
{ . compatible = " mrvl,pxa-gpio " } ,
{ . compatible = " mrvl,mmp-gpio " , . data = ( void * ) MMP_GPIO } ,
{ }
} ;
static int pxa_irq_domain_map ( struct irq_domain * d , unsigned int irq ,
irq_hw_number_t hw )
{
irq_set_chip_and_handler ( irq , & pxa_muxed_gpio_chip ,
handle_edge_irq ) ;
set_irq_flags ( irq , IRQF_VALID | IRQF_PROBE ) ;
return 0 ;
}
const struct irq_domain_ops pxa_irq_domain_ops = {
. map = pxa_irq_domain_map ,
2012-07-25 17:35:39 +02:00
. xlate = irq_domain_xlate_twocell ,
2012-04-13 15:15:45 +08:00
} ;
static int __devinit pxa_gpio_probe_dt ( struct platform_device * pdev )
{
2012-07-22 16:55:44 +02:00
int ret , nr_banks , nr_gpios ;
2012-04-13 15:15:45 +08:00
struct device_node * prev , * next , * np = pdev - > dev . of_node ;
const struct of_device_id * of_id =
of_match_device ( pxa_gpio_dt_ids , & pdev - > dev ) ;
if ( ! of_id ) {
dev_err ( & pdev - > dev , " Failed to find gpio controller \n " ) ;
return - EFAULT ;
}
gpio_type = ( int ) of_id - > data ;
next = of_get_next_child ( np , NULL ) ;
prev = next ;
if ( ! next ) {
dev_err ( & pdev - > dev , " Failed to find child gpio node \n " ) ;
ret = - EINVAL ;
goto err ;
}
for ( nr_banks = 1 ; ; nr_banks + + ) {
next = of_get_next_child ( np , prev ) ;
if ( ! next )
break ;
prev = next ;
}
of_node_put ( prev ) ;
nr_gpios = nr_banks < < 5 ;
pxa_last_gpio = nr_gpios - 1 ;
irq_base = irq_alloc_descs ( - 1 , 0 , nr_gpios , 0 ) ;
if ( irq_base < 0 ) {
dev_err ( & pdev - > dev , " Failed to allocate IRQ numbers \n " ) ;
goto err ;
}
domain = irq_domain_add_legacy ( np , nr_gpios , irq_base , 0 ,
& pxa_irq_domain_ops , NULL ) ;
2012-07-25 17:35:39 +02:00
pxa_gpio_of_node = np ;
2012-04-13 15:15:45 +08:00
return 0 ;
err :
iounmap ( gpio_reg_base ) ;
return ret ;
}
# else
# define pxa_gpio_probe_dt(pdev) (-1)
# endif
2011-10-17 20:37:52 +08:00
static int __devinit pxa_gpio_probe ( struct platform_device * pdev )
2008-03-04 11:42:26 +08:00
{
2009-01-07 18:01:51 +08:00
struct pxa_gpio_chip * c ;
2011-10-17 20:37:52 +08:00
struct resource * res ;
2011-10-17 21:26:55 +08:00
struct clk * clk ;
2012-04-22 13:37:24 +02:00
struct pxa_gpio_platform_data * info ;
2012-04-13 15:15:45 +08:00
int gpio , irq , ret , use_of = 0 ;
2011-10-17 20:37:52 +08:00
int irq0 = 0 , irq1 = 0 , irq_mux , gpio_offset = 0 ;
2008-03-04 11:42:26 +08:00
2012-04-13 15:15:45 +08:00
ret = pxa_gpio_probe_dt ( pdev ) ;
2012-07-22 16:55:44 +02:00
if ( ret < 0 ) {
2012-04-13 15:15:45 +08:00
pxa_last_gpio = pxa_gpio_nums ( ) ;
2012-07-22 16:55:44 +02:00
# ifdef CONFIG_ARCH_PXA
if ( gpio_is_pxa_type ( gpio_type ) )
irq_base = PXA_GPIO_TO_IRQ ( 0 ) ;
# endif
# ifdef CONFIG_ARCH_MMP
if ( gpio_is_mmp_type ( gpio_type ) )
irq_base = MMP_GPIO_TO_IRQ ( 0 ) ;
# endif
} else {
2012-04-13 15:15:45 +08:00
use_of = 1 ;
2012-07-22 16:55:44 +02:00
}
2011-10-14 16:44:07 +08:00
if ( ! pxa_last_gpio )
2011-10-17 20:37:52 +08:00
return - EINVAL ;
irq0 = platform_get_irq_byname ( pdev , " gpio0 " ) ;
irq1 = platform_get_irq_byname ( pdev , " gpio1 " ) ;
irq_mux = platform_get_irq_byname ( pdev , " gpio_mux " ) ;
if ( ( irq0 > 0 & & irq1 < = 0 ) | | ( irq0 < = 0 & & irq1 > 0 )
| | ( irq_mux < = 0 ) )
return - EINVAL ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( ! res )
return - EINVAL ;
gpio_reg_base = ioremap ( res - > start , resource_size ( res ) ) ;
if ( ! gpio_reg_base )
return - EINVAL ;
if ( irq0 > 0 )
gpio_offset = 2 ;
2008-03-04 11:42:26 +08:00
2011-10-17 21:26:55 +08:00
clk = clk_get ( & pdev - > dev , NULL ) ;
if ( IS_ERR ( clk ) ) {
dev_err ( & pdev - > dev , " Error %ld to get gpio clock \n " ,
PTR_ERR ( clk ) ) ;
iounmap ( gpio_reg_base ) ;
return PTR_ERR ( clk ) ;
}
2012-08-26 18:00:55 +02:00
ret = clk_prepare_enable ( clk ) ;
2011-10-17 21:26:55 +08:00
if ( ret ) {
clk_put ( clk ) ;
iounmap ( gpio_reg_base ) ;
return ret ;
}
2009-01-07 18:01:51 +08:00
/* Initialize GPIO chips */
2012-04-22 13:37:24 +02:00
info = dev_get_platdata ( & pdev - > dev ) ;
pxa_init_gpio_chip ( pxa_last_gpio , info ? info - > gpio_set_wake : NULL ) ;
2009-01-07 18:01:51 +08:00
2008-03-04 11:42:26 +08:00
/* clear all GPIO edge detects */
2009-01-07 18:01:51 +08:00
for_each_gpio_chip ( gpio , c ) {
2011-10-14 17:24:03 +08:00
writel_relaxed ( 0 , c - > regbase + GFER_OFFSET ) ;
writel_relaxed ( 0 , c - > regbase + GRER_OFFSET ) ;
writel_relaxed ( ~ 0 , c - > regbase + GEDR_OFFSET ) ;
2011-10-17 21:07:15 +08:00
/* unmask GPIO edge detect for AP side */
if ( gpio_is_mmp_type ( gpio_type ) )
writel_relaxed ( ~ 0 , c - > regbase + ED_MASK_OFFSET ) ;
2008-03-04 11:42:26 +08:00
}
2012-04-13 15:15:45 +08:00
if ( ! use_of ) {
2011-10-10 14:38:46 +08:00
# ifdef CONFIG_ARCH_PXA
2012-04-13 15:15:45 +08:00
irq = gpio_to_irq ( 0 ) ;
irq_set_chip_and_handler ( irq , & pxa_muxed_gpio_chip ,
handle_edge_irq ) ;
set_irq_flags ( irq , IRQF_VALID | IRQF_PROBE ) ;
irq_set_chained_handler ( IRQ_GPIO0 , pxa_gpio_demux_handler ) ;
2011-10-10 14:38:46 +08:00
2012-04-13 15:15:45 +08:00
irq = gpio_to_irq ( 1 ) ;
2011-03-24 13:35:09 +01:00
irq_set_chip_and_handler ( irq , & pxa_muxed_gpio_chip ,
handle_edge_irq ) ;
2008-03-04 11:42:26 +08:00
set_irq_flags ( irq , IRQF_VALID | IRQF_PROBE ) ;
2012-04-13 15:15:45 +08:00
irq_set_chained_handler ( IRQ_GPIO1 , pxa_gpio_demux_handler ) ;
# endif
for ( irq = gpio_to_irq ( gpio_offset ) ;
irq < = gpio_to_irq ( pxa_last_gpio ) ; irq + + ) {
irq_set_chip_and_handler ( irq , & pxa_muxed_gpio_chip ,
handle_edge_irq ) ;
set_irq_flags ( irq , IRQF_VALID | IRQF_PROBE ) ;
}
2008-03-04 11:42:26 +08:00
}
2011-10-17 20:37:52 +08:00
irq_set_chained_handler ( irq_mux , pxa_gpio_demux_handler ) ;
return 0 ;
}
static struct platform_driver pxa_gpio_driver = {
. probe = pxa_gpio_probe ,
. driver = {
. name = " pxa-gpio " ,
2012-08-13 14:36:10 +00:00
. of_match_table = of_match_ptr ( pxa_gpio_dt_ids ) ,
2011-10-17 20:37:52 +08:00
} ,
} ;
static int __init pxa_gpio_init ( void )
{
return platform_driver_register ( & pxa_gpio_driver ) ;
2008-03-04 11:42:26 +08:00
}
2011-10-17 20:37:52 +08:00
postcore_initcall ( pxa_gpio_init ) ;
2008-03-04 16:13:58 +08:00
# ifdef CONFIG_PM
2011-04-22 22:03:11 +02:00
static int pxa_gpio_suspend ( void )
2008-03-04 16:13:58 +08:00
{
2009-01-07 18:01:51 +08:00
struct pxa_gpio_chip * c ;
int gpio ;
2008-03-04 16:13:58 +08:00
2009-01-07 18:01:51 +08:00
for_each_gpio_chip ( gpio , c ) {
2011-10-14 17:24:03 +08:00
c - > saved_gplr = readl_relaxed ( c - > regbase + GPLR_OFFSET ) ;
c - > saved_gpdr = readl_relaxed ( c - > regbase + GPDR_OFFSET ) ;
c - > saved_grer = readl_relaxed ( c - > regbase + GRER_OFFSET ) ;
c - > saved_gfer = readl_relaxed ( c - > regbase + GFER_OFFSET ) ;
2008-03-04 16:13:58 +08:00
/* Clear GPIO transition detect bits */
2011-10-14 17:24:03 +08:00
writel_relaxed ( 0xffffffff , c - > regbase + GEDR_OFFSET ) ;
2008-03-04 16:13:58 +08:00
}
return 0 ;
}
2011-04-22 22:03:11 +02:00
static void pxa_gpio_resume ( void )
2008-03-04 16:13:58 +08:00
{
2009-01-07 18:01:51 +08:00
struct pxa_gpio_chip * c ;
int gpio ;
2008-03-04 16:13:58 +08:00
2009-01-07 18:01:51 +08:00
for_each_gpio_chip ( gpio , c ) {
2008-03-04 16:13:58 +08:00
/* restore level with set/clear */
2011-10-14 17:24:03 +08:00
writel_relaxed ( c - > saved_gplr , c - > regbase + GPSR_OFFSET ) ;
writel_relaxed ( ~ c - > saved_gplr , c - > regbase + GPCR_OFFSET ) ;
2008-03-04 16:13:58 +08:00
2011-10-14 17:24:03 +08:00
writel_relaxed ( c - > saved_grer , c - > regbase + GRER_OFFSET ) ;
writel_relaxed ( c - > saved_gfer , c - > regbase + GFER_OFFSET ) ;
writel_relaxed ( c - > saved_gpdr , c - > regbase + GPDR_OFFSET ) ;
2008-03-04 16:13:58 +08:00
}
}
# else
# define pxa_gpio_suspend NULL
# define pxa_gpio_resume NULL
# endif
2011-04-22 22:03:11 +02:00
struct syscore_ops pxa_gpio_syscore_ops = {
2008-03-04 16:13:58 +08:00
. suspend = pxa_gpio_suspend ,
. resume = pxa_gpio_resume ,
} ;
2011-10-17 20:37:52 +08:00
static int __init pxa_gpio_sysinit ( void )
{
register_syscore_ops ( & pxa_gpio_syscore_ops ) ;
return 0 ;
}
postcore_initcall ( pxa_gpio_sysinit ) ;