2008-02-05 09:28:22 +03:00
/*
2009-01-20 07:09:06 +03:00
* linux / arch / arm / plat - pxa / gpio . c
2008-02-05 09:28:22 +03: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 11:15:45 +04:00
# include <linux/module.h>
2011-10-17 17:26:55 +04:00
# include <linux/clk.h>
# include <linux/err.h>
2011-07-26 13:53:52 +04:00
# include <linux/gpio.h>
2011-10-17 16:37:52 +04:00
# include <linux/gpio-pxa.h>
2008-02-05 09:28:22 +03:00
# include <linux/init.h>
2015-01-27 07:46:04 +03:00
# include <linux/interrupt.h>
2008-03-04 06:42:26 +03:00
# include <linux/irq.h>
2012-04-13 11:15:45 +04:00
# include <linux/irqdomain.h>
2013-01-18 19:31:37 +04:00
# include <linux/irqchip/chained_irq.h>
2008-09-06 15:10:45 +04:00
# include <linux/io.h>
2012-04-13 11:15:45 +04:00
# include <linux/of.h>
# include <linux/of_device.h>
2011-10-17 16:37:52 +04:00
# include <linux/platform_device.h>
2011-04-23 00:03:11 +04:00
# include <linux/syscore_ops.h>
2009-06-20 00:56:09 +04:00
# include <linux/slab.h>
2008-02-05 09:28:22 +03:00
2011-10-17 16:37:52 +04: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
*
2015-01-27 07:46:06 +03:00
* BANK 6 - 0x0200 0x020C 0x0218 0x0224 0x0230 0x023C 0x0248
*
2011-10-17 16:37:52 +04:00
* NOTE :
* BANK 3 is only available on PXA27x and later processors .
2015-01-27 07:46:06 +03:00
* BANK 4 and 5 are only available on PXA935 , PXA1928
* BANK 6 is only available on PXA1928
2011-10-17 16:37:52 +04:00
*/
# 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 17:07:15 +04:00
# define ED_MASK_OFFSET 0x9C /* GPIO edge detection for AP side */
2011-10-17 16:37:52 +04:00
2015-03-03 00:30:58 +03:00
# define BANK_OFF(n) (((n) / 3) << 8) + (((n) % 3) << 2)
2008-02-05 09:28:22 +03:00
2009-01-07 06:30:49 +03:00
int pxa_last_gpio ;
2012-07-22 18:55:44 +04:00
static int irq_base ;
2009-01-07 06:30:49 +03:00
2012-04-13 11:15:45 +04:00
# ifdef CONFIG_OF
static struct irq_domain * domain ;
2012-07-25 19:35:39 +04:00
static struct device_node * pxa_gpio_of_node ;
2012-04-13 11:15:45 +04:00
# endif
2008-02-05 09:28:22 +03:00
struct pxa_gpio_chip {
struct gpio_chip chip ;
2009-01-07 13:01:51 +03:00
void __iomem * regbase ;
char label [ 10 ] ;
unsigned long irq_mask ;
unsigned long irq_edge_rise ;
unsigned long irq_edge_fall ;
2012-04-22 15:37:24 +04:00
int ( * set_wake ) ( unsigned int gpio , unsigned int on ) ;
2009-01-07 13:01:51 +03:00
# ifdef CONFIG_PM
unsigned long saved_gplr ;
unsigned long saved_gpdr ;
unsigned long saved_grer ;
unsigned long saved_gfer ;
# endif
2008-02-05 09:28:22 +03:00
} ;
2013-04-07 12:44:33 +04:00
enum pxa_gpio_type {
2011-10-10 12:03:51 +04:00
PXA25X_GPIO = 0 ,
PXA26X_GPIO ,
PXA27X_GPIO ,
PXA3XX_GPIO ,
PXA93X_GPIO ,
MMP_GPIO = 0x10 ,
2013-04-07 12:44:33 +04:00
MMP2_GPIO ,
2015-01-27 07:46:06 +03:00
PXA1928_GPIO ,
2013-04-07 12:44:33 +04:00
} ;
struct pxa_gpio_id {
enum pxa_gpio_type type ;
int gpio_nums ;
2011-10-10 12:03:51 +04:00
} ;
2009-01-07 13:01:51 +03:00
static DEFINE_SPINLOCK ( gpio_lock ) ;
static struct pxa_gpio_chip * pxa_gpio_chips ;
2013-04-07 12:44:33 +04:00
static enum pxa_gpio_type gpio_type ;
2011-10-17 16:37:52 +04:00
static void __iomem * gpio_reg_base ;
2009-01-07 13:01:51 +03:00
2013-04-07 12:44:33 +04:00
static struct pxa_gpio_id pxa25x_id = {
. type = PXA25X_GPIO ,
. gpio_nums = 85 ,
} ;
static struct pxa_gpio_id pxa26x_id = {
. type = PXA26X_GPIO ,
. gpio_nums = 90 ,
} ;
static struct pxa_gpio_id pxa27x_id = {
. type = PXA27X_GPIO ,
. gpio_nums = 121 ,
} ;
static struct pxa_gpio_id pxa3xx_id = {
. type = PXA3XX_GPIO ,
. gpio_nums = 128 ,
} ;
static struct pxa_gpio_id pxa93x_id = {
. type = PXA93X_GPIO ,
. gpio_nums = 192 ,
} ;
static struct pxa_gpio_id mmp_id = {
. type = MMP_GPIO ,
. gpio_nums = 128 ,
} ;
static struct pxa_gpio_id mmp2_id = {
. type = MMP2_GPIO ,
. gpio_nums = 192 ,
} ;
2015-01-27 07:46:06 +03:00
static struct pxa_gpio_id pxa1928_id = {
. type = PXA1928_GPIO ,
. gpio_nums = 224 ,
} ;
2009-01-07 13:01:51 +03: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 12:42:19 +04:00
static inline struct pxa_gpio_chip * gpio_to_pxachip ( unsigned gpio )
2009-01-07 13:01:51 +03:00
{
return & pxa_gpio_chips [ gpio_to_bank ( gpio ) ] ;
}
2011-10-10 12:03:51 +04: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 16:37:52 +04: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 12:03:51 +04:00
static int pxa_gpio_to_irq ( struct gpio_chip * chip , unsigned offset )
{
2012-07-22 18:55:44 +04:00
return chip - > base + offset + irq_base ;
2011-10-10 12:03:51 +04:00
}
int pxa_irq_to_gpio ( int irq )
{
2012-07-22 18:55:44 +04:00
return irq - irq_base ;
2011-10-10 12:03:51 +04:00
}
2008-02-05 09:28:22 +03:00
static int pxa_gpio_direction_input ( struct gpio_chip * chip , unsigned offset )
{
2009-01-07 13:01:51 +03: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 13:24:03 +04:00
value = readl_relaxed ( base + GPDR_OFFSET ) ;
2008-11-26 13:12:04 +03:00
if ( __gpio_is_inverted ( chip - > base + offset ) )
value | = mask ;
else
value & = ~ mask ;
2011-10-14 13:24:03 +04:00
writel_relaxed ( value , base + GPDR_OFFSET ) ;
2008-02-05 09:28:22 +03:00
2009-01-07 13:01:51 +03:00
spin_unlock_irqrestore ( & gpio_lock , flags ) ;
2008-02-05 09:28:22 +03:00
return 0 ;
}
static int pxa_gpio_direction_output ( struct gpio_chip * chip ,
2009-01-07 13:01:51 +03:00
unsigned offset , int value )
2008-02-05 09:28:22 +03:00
{
2009-01-07 13:01:51 +03:00
void __iomem * base = gpio_chip_base ( chip ) ;
uint32_t tmp , mask = 1 < < offset ;
unsigned long flags ;
2011-10-14 13:24:03 +04:00
writel_relaxed ( mask , base + ( value ? GPSR_OFFSET : GPCR_OFFSET ) ) ;
2009-01-07 13:01:51 +03:00
spin_lock_irqsave ( & gpio_lock , flags ) ;
2011-10-14 13:24:03 +04:00
tmp = readl_relaxed ( base + GPDR_OFFSET ) ;
2008-11-26 13:12:04 +03:00
if ( __gpio_is_inverted ( chip - > base + offset ) )
tmp & = ~ mask ;
else
tmp | = mask ;
2011-10-14 13:24:03 +04:00
writel_relaxed ( tmp , base + GPDR_OFFSET ) ;
2008-02-05 09:28:22 +03:00
2009-01-07 13:01:51 +03:00
spin_unlock_irqrestore ( & gpio_lock , flags ) ;
2008-02-05 09:28:22 +03:00
return 0 ;
}
static int pxa_gpio_get ( struct gpio_chip * chip , unsigned offset )
{
2014-01-09 13:25:57 +04:00
u32 gplr = readl_relaxed ( gpio_chip_base ( chip ) + GPLR_OFFSET ) ;
return ! ! ( gplr & ( 1 < < offset ) ) ;
2008-02-05 09:28:22 +03:00
}
static void pxa_gpio_set ( struct gpio_chip * chip , unsigned offset , int value )
{
2011-10-14 13:24:03 +04:00
writel_relaxed ( 1 < < offset , gpio_chip_base ( chip ) +
2009-01-07 13:01:51 +03:00
( value ? GPSR_OFFSET : GPCR_OFFSET ) ) ;
2008-02-05 09:28:22 +03:00
}
2012-07-25 19:35:39 +04: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-11-19 22:22:34 +04:00
static int pxa_init_gpio_chip ( int gpio_end ,
2012-04-22 15:37:24 +04:00
int ( * set_wake ) ( unsigned int , unsigned int ) )
2009-01-06 12:37:37 +03:00
{
2009-01-07 13:01:51 +03:00
int i , gpio , nbanks = gpio_to_bank ( gpio_end ) + 1 ;
struct pxa_gpio_chip * chips ;
2009-01-06 12:37:37 +03:00
2009-06-20 00:56:09 +04:00
chips = kzalloc ( nbanks * sizeof ( struct pxa_gpio_chip ) , GFP_KERNEL ) ;
2009-01-07 13:01:51 +03:00
if ( chips = = NULL ) {
pr_err ( " %s: failed to allocate GPIO chips \n " , __func__ ) ;
return - ENOMEM ;
2009-01-06 12:37:37 +03:00
}
2009-01-07 13:01:51 +03:00
for ( i = 0 , gpio = 0 ; i < nbanks ; i + + , gpio + = 32 ) {
struct gpio_chip * c = & chips [ i ] . chip ;
2008-03-04 06:42:26 +03:00
2009-01-07 13:01:51 +03:00
sprintf ( chips [ i ] . label , " gpio-%d " , i ) ;
2011-10-17 16:37:52 +04:00
chips [ i ] . regbase = gpio_reg_base + BANK_OFF ( i ) ;
2012-04-22 15:37:24 +04:00
chips [ i ] . set_wake = set_wake ;
2009-01-07 13:01:51 +03: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 12:03:51 +04:00
c - > to_irq = pxa_gpio_to_irq ;
2012-07-25 19:35:39 +04: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 13:01:51 +03: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 06:42:26 +03:00
2009-04-21 10:39:07 +04: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 13:24:03 +04:00
grer = readl_relaxed ( c - > regbase + GRER_OFFSET ) & ~ c - > irq_mask ;
gfer = readl_relaxed ( c - > regbase + GFER_OFFSET ) & ~ c - > irq_mask ;
2009-04-21 10:39:07 +04:00
grer | = c - > irq_edge_rise & c - > irq_mask ;
gfer | = c - > irq_edge_fall & c - > irq_mask ;
2011-10-14 13:24:03 +04:00
writel_relaxed ( grer , c - > regbase + GRER_OFFSET ) ;
writel_relaxed ( gfer , c - > regbase + GFER_OFFSET ) ;
2009-04-21 10:39:07 +04:00
}
2010-11-29 13:18:26 +03:00
static int pxa_gpio_irq_type ( struct irq_data * d , unsigned int type )
2008-03-04 06:42:26 +03:00
{
2009-01-07 13:01:51 +03:00
struct pxa_gpio_chip * c ;
2011-10-10 12:03:51 +04:00
int gpio = pxa_irq_to_gpio ( d - > irq ) ;
2009-01-07 13:01:51 +03:00
unsigned long gpdr , mask = GPIO_bit ( gpio ) ;
2008-03-04 06:42:26 +03:00
2011-06-13 12:42:19 +04:00
c = gpio_to_pxachip ( gpio ) ;
2008-03-04 06:42:26 +03: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 13:01:51 +03:00
if ( ( c - > irq_edge_rise | c - > irq_edge_fall ) & GPIO_bit ( gpio ) )
2008-03-04 06:42:26 +03:00
return 0 ;
2008-03-04 12:18:38 +03:00
if ( __gpio_is_occupied ( gpio ) )
2008-03-04 06:42:26 +03:00
return 0 ;
2008-03-04 12:18:38 +03:00
2008-03-04 06:42:26 +03:00
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING ;
}
2011-10-14 13:24:03 +04:00
gpdr = readl_relaxed ( c - > regbase + GPDR_OFFSET ) ;
2009-01-07 13:01:51 +03:00
2008-11-26 13:12:04 +03:00
if ( __gpio_is_inverted ( gpio ) )
2011-10-14 13:24:03 +04:00
writel_relaxed ( gpdr | mask , c - > regbase + GPDR_OFFSET ) ;
2008-11-26 13:12:04 +03:00
else
2011-10-14 13:24:03 +04:00
writel_relaxed ( gpdr & ~ mask , c - > regbase + GPDR_OFFSET ) ;
2008-03-04 06:42:26 +03:00
if ( type & IRQ_TYPE_EDGE_RISING )
2009-01-07 13:01:51 +03:00
c - > irq_edge_rise | = mask ;
2008-03-04 06:42:26 +03:00
else
2009-01-07 13:01:51 +03:00
c - > irq_edge_rise & = ~ mask ;
2008-03-04 06:42:26 +03:00
if ( type & IRQ_TYPE_EDGE_FALLING )
2009-01-07 13:01:51 +03:00
c - > irq_edge_fall | = mask ;
2008-03-04 06:42:26 +03:00
else
2009-01-07 13:01:51 +03:00
c - > irq_edge_fall & = ~ mask ;
2008-03-04 06:42:26 +03:00
2009-04-21 10:39:07 +04:00
update_edge_detect ( c ) ;
2008-03-04 06:42:26 +03:00
2010-11-29 13:18:26 +03:00
pr_debug ( " %s: IRQ%d (GPIO%d) - edge%s%s \n " , __func__ , d - > irq , gpio ,
2008-03-04 06:42:26 +03: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 13:01:51 +03:00
struct pxa_gpio_chip * c ;
int loop , gpio , gpio_base , n ;
unsigned long gedr ;
2012-07-31 10:13:09 +04:00
struct irq_chip * chip = irq_desc_get_chip ( desc ) ;
chained_irq_enter ( chip , desc ) ;
2008-03-04 06:42:26 +03:00
do {
loop = 0 ;
2009-01-07 13:01:51 +03:00
for_each_gpio_chip ( gpio , c ) {
gpio_base = c - > chip . base ;
2011-10-14 13:24:03 +04:00
gedr = readl_relaxed ( c - > regbase + GEDR_OFFSET ) ;
2009-01-07 13:01:51 +03:00
gedr = gedr & c - > irq_mask ;
2011-10-14 13:24:03 +04:00
writel_relaxed ( gedr , c - > regbase + GEDR_OFFSET ) ;
2008-03-04 06:42:26 +03:00
2012-09-14 06:36:59 +04:00
for_each_set_bit ( n , & gedr , BITS_PER_LONG ) {
2009-01-07 13:01:51 +03:00
loop = 1 ;
2008-03-04 06:42:26 +03:00
2009-01-07 13:01:51 +03:00
generic_handle_irq ( gpio_to_irq ( gpio_base + n ) ) ;
}
2008-03-04 06:42:26 +03:00
}
} while ( loop ) ;
2012-07-31 10:13:09 +04:00
chained_irq_exit ( chip , desc ) ;
2008-03-04 06:42:26 +03:00
}
2010-11-29 13:18:26 +03:00
static void pxa_ack_muxed_gpio ( struct irq_data * d )
2008-03-04 06:42:26 +03:00
{
2011-10-10 12:03:51 +04:00
int gpio = pxa_irq_to_gpio ( d - > irq ) ;
2011-06-13 12:42:19 +04:00
struct pxa_gpio_chip * c = gpio_to_pxachip ( gpio ) ;
2009-01-07 13:01:51 +03:00
2011-10-14 13:24:03 +04:00
writel_relaxed ( GPIO_bit ( gpio ) , c - > regbase + GEDR_OFFSET ) ;
2008-03-04 06:42:26 +03:00
}
2010-11-29 13:18:26 +03:00
static void pxa_mask_muxed_gpio ( struct irq_data * d )
2008-03-04 06:42:26 +03:00
{
2011-10-10 12:03:51 +04:00
int gpio = pxa_irq_to_gpio ( d - > irq ) ;
2011-06-13 12:42:19 +04:00
struct pxa_gpio_chip * c = gpio_to_pxachip ( gpio ) ;
2009-01-07 13:01:51 +03:00
uint32_t grer , gfer ;
c - > irq_mask & = ~ GPIO_bit ( gpio ) ;
2011-10-14 13:24:03 +04: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 06:42:26 +03:00
}
2012-04-22 15:37:24 +04: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 13:18:26 +03:00
static void pxa_unmask_muxed_gpio ( struct irq_data * d )
2008-03-04 06:42:26 +03:00
{
2011-10-10 12:03:51 +04:00
int gpio = pxa_irq_to_gpio ( d - > irq ) ;
2011-06-13 12:42:19 +04:00
struct pxa_gpio_chip * c = gpio_to_pxachip ( gpio ) ;
2009-01-07 13:01:51 +03:00
c - > irq_mask | = GPIO_bit ( gpio ) ;
2009-04-21 10:39:07 +04:00
update_edge_detect ( c ) ;
2008-03-04 06:42:26 +03:00
}
static struct irq_chip pxa_muxed_gpio_chip = {
. name = " GPIO " ,
2010-11-29 13:18:26 +03: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 15:37:24 +04:00
. irq_set_wake = pxa_gpio_set_wake ,
2008-03-04 06:42:26 +03:00
} ;
2013-04-07 12:44:33 +04:00
static int pxa_gpio_nums ( struct platform_device * pdev )
2011-10-14 12:44:07 +04:00
{
2013-04-07 12:44:33 +04:00
const struct platform_device_id * id = platform_get_device_id ( pdev ) ;
struct pxa_gpio_id * pxa_id = ( struct pxa_gpio_id * ) id - > driver_data ;
2011-10-14 12:44:07 +04:00
int count = 0 ;
2013-04-07 12:44:33 +04:00
switch ( pxa_id - > type ) {
case PXA25X_GPIO :
case PXA26X_GPIO :
case PXA27X_GPIO :
case PXA3XX_GPIO :
case PXA93X_GPIO :
case MMP_GPIO :
case MMP2_GPIO :
2015-01-27 07:46:06 +03:00
case PXA1928_GPIO :
2013-04-07 12:44:33 +04:00
gpio_type = pxa_id - > type ;
count = pxa_id - > gpio_nums - 1 ;
break ;
default :
count = - EINVAL ;
break ;
2011-10-14 12:44:07 +04:00
}
return count ;
}
2012-08-13 18:36:10 +04:00
# ifdef CONFIG_OF
2014-06-03 16:10:25 +04:00
static const struct of_device_id pxa_gpio_dt_ids [ ] = {
2013-04-09 18:27:50 +04:00
{ . compatible = " intel,pxa25x-gpio " , . data = & pxa25x_id , } ,
{ . compatible = " intel,pxa26x-gpio " , . data = & pxa26x_id , } ,
{ . compatible = " intel,pxa27x-gpio " , . data = & pxa27x_id , } ,
{ . compatible = " intel,pxa3xx-gpio " , . data = & pxa3xx_id , } ,
{ . compatible = " marvell,pxa93x-gpio " , . data = & pxa93x_id , } ,
{ . compatible = " marvell,mmp-gpio " , . data = & mmp_id , } ,
{ . compatible = " marvell,mmp2-gpio " , . data = & mmp2_id , } ,
2015-01-27 07:46:06 +03:00
{ . compatible = " marvell,pxa1928-gpio " , . data = & pxa1928_id , } ,
2012-04-13 11:15:45 +04:00
{ }
} ;
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 19:35:39 +04:00
. xlate = irq_domain_xlate_twocell ,
2012-04-13 11:15:45 +04:00
} ;
2012-11-19 22:22:34 +04:00
static int pxa_gpio_probe_dt ( struct platform_device * pdev )
2012-04-13 11:15:45 +04:00
{
2013-07-11 19:17:53 +04:00
int ret = 0 , nr_gpios ;
struct device_node * np = pdev - > dev . of_node ;
2012-04-13 11:15:45 +04:00
const struct of_device_id * of_id =
of_match_device ( pxa_gpio_dt_ids , & pdev - > dev ) ;
2013-04-09 18:27:50 +04:00
const struct pxa_gpio_id * gpio_id ;
2012-04-13 11:15:45 +04:00
2013-04-09 18:27:50 +04:00
if ( ! of_id | | ! of_id - > data ) {
2012-04-13 11:15:45 +04:00
dev_err ( & pdev - > dev , " Failed to find gpio controller \n " ) ;
return - EFAULT ;
}
2013-04-09 18:27:50 +04:00
gpio_id = of_id - > data ;
gpio_type = gpio_id - > type ;
2012-04-13 11:15:45 +04:00
2013-04-09 18:27:50 +04:00
nr_gpios = gpio_id - > gpio_nums ;
2012-04-13 11:15:45 +04:00
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 " ) ;
2013-07-11 19:17:53 +04:00
ret = irq_base ;
2012-04-13 11:15:45 +04:00
goto err ;
}
domain = irq_domain_add_legacy ( np , nr_gpios , irq_base , 0 ,
& pxa_irq_domain_ops , NULL ) ;
2012-07-25 19:35:39 +04:00
pxa_gpio_of_node = np ;
2012-04-13 11:15:45 +04:00
return 0 ;
err :
iounmap ( gpio_reg_base ) ;
return ret ;
}
# else
# define pxa_gpio_probe_dt(pdev) (-1)
# endif
2012-11-19 22:22:34 +04:00
static int pxa_gpio_probe ( struct platform_device * pdev )
2008-03-04 06:42:26 +03:00
{
2009-01-07 13:01:51 +03:00
struct pxa_gpio_chip * c ;
2011-10-17 16:37:52 +04:00
struct resource * res ;
2011-10-17 17:26:55 +04:00
struct clk * clk ;
2012-04-22 15:37:24 +04:00
struct pxa_gpio_platform_data * info ;
2012-04-13 11:15:45 +04:00
int gpio , irq , ret , use_of = 0 ;
2011-10-17 16:37:52 +04:00
int irq0 = 0 , irq1 = 0 , irq_mux , gpio_offset = 0 ;
2008-03-04 06:42:26 +03:00
2013-04-09 14:12:04 +04:00
info = dev_get_platdata ( & pdev - > dev ) ;
if ( info ) {
irq_base = info - > irq_base ;
if ( irq_base < = 0 )
return - EINVAL ;
2013-04-07 12:44:33 +04:00
pxa_last_gpio = pxa_gpio_nums ( pdev ) ;
2012-07-22 18:55:44 +04:00
} else {
2013-04-09 14:12:04 +04:00
irq_base = 0 ;
2012-04-13 11:15:45 +04:00
use_of = 1 ;
2013-04-09 14:12:04 +04:00
ret = pxa_gpio_probe_dt ( pdev ) ;
if ( ret < 0 )
return - EINVAL ;
2012-07-22 18:55:44 +04:00
}
2011-10-14 12:44:07 +04:00
if ( ! pxa_last_gpio )
2011-10-17 16:37:52 +04: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 06:42:26 +03:00
2011-10-17 17:26:55 +04: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 20:00:55 +04:00
ret = clk_prepare_enable ( clk ) ;
2011-10-17 17:26:55 +04:00
if ( ret ) {
clk_put ( clk ) ;
iounmap ( gpio_reg_base ) ;
return ret ;
}
2009-01-07 13:01:51 +03:00
/* Initialize GPIO chips */
2012-04-22 15:37:24 +04:00
pxa_init_gpio_chip ( pxa_last_gpio , info ? info - > gpio_set_wake : NULL ) ;
2009-01-07 13:01:51 +03:00
2008-03-04 06:42:26 +03:00
/* clear all GPIO edge detects */
2009-01-07 13:01:51 +03:00
for_each_gpio_chip ( gpio , c ) {
2011-10-14 13:24:03 +04:00
writel_relaxed ( 0 , c - > regbase + GFER_OFFSET ) ;
writel_relaxed ( 0 , c - > regbase + GRER_OFFSET ) ;
2013-03-20 16:15:59 +04:00
writel_relaxed ( ~ 0 , c - > regbase + GEDR_OFFSET ) ;
2011-10-17 17:07:15 +04: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 06:42:26 +03:00
}
2012-04-13 11:15:45 +04:00
if ( ! use_of ) {
2015-01-27 07:46:04 +03:00
if ( irq0 > 0 ) {
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 ) ;
}
if ( irq1 > 0 ) {
irq = gpio_to_irq ( 1 ) ;
irq_set_chip_and_handler ( irq , & pxa_muxed_gpio_chip ,
handle_edge_irq ) ;
set_irq_flags ( irq , IRQF_VALID | IRQF_PROBE ) ;
}
2012-04-13 11:15:45 +04:00
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 06:42:26 +03:00
}
2015-01-27 07:46:04 +03:00
if ( irq0 > 0 )
irq_set_chained_handler ( irq0 , pxa_gpio_demux_handler ) ;
if ( irq1 > 0 )
irq_set_chained_handler ( irq1 , pxa_gpio_demux_handler ) ;
2011-10-17 16:37:52 +04:00
irq_set_chained_handler ( irq_mux , pxa_gpio_demux_handler ) ;
return 0 ;
}
2013-04-07 12:44:33 +04:00
static const struct platform_device_id gpio_id_table [ ] = {
{ " pxa25x-gpio " , ( unsigned long ) & pxa25x_id } ,
{ " pxa26x-gpio " , ( unsigned long ) & pxa26x_id } ,
{ " pxa27x-gpio " , ( unsigned long ) & pxa27x_id } ,
{ " pxa3xx-gpio " , ( unsigned long ) & pxa3xx_id } ,
{ " pxa93x-gpio " , ( unsigned long ) & pxa93x_id } ,
{ " mmp-gpio " , ( unsigned long ) & mmp_id } ,
{ " mmp2-gpio " , ( unsigned long ) & mmp2_id } ,
2015-01-27 07:46:06 +03:00
{ " pxa1928-gpio " , ( unsigned long ) & pxa1928_id } ,
2013-04-07 12:44:33 +04:00
{ } ,
} ;
2011-10-17 16:37:52 +04:00
static struct platform_driver pxa_gpio_driver = {
. probe = pxa_gpio_probe ,
. driver = {
. name = " pxa-gpio " ,
2012-08-13 18:36:10 +04:00
. of_match_table = of_match_ptr ( pxa_gpio_dt_ids ) ,
2011-10-17 16:37:52 +04:00
} ,
2013-04-07 12:44:33 +04:00
. id_table = gpio_id_table ,
2011-10-17 16:37:52 +04:00
} ;
2013-04-24 23:41:20 +04:00
static int __init pxa_gpio_init ( void )
{
return platform_driver_register ( & pxa_gpio_driver ) ;
}
postcore_initcall ( pxa_gpio_init ) ;
2008-03-04 11:13:58 +03:00
# ifdef CONFIG_PM
2011-04-23 00:03:11 +04:00
static int pxa_gpio_suspend ( void )
2008-03-04 11:13:58 +03:00
{
2009-01-07 13:01:51 +03:00
struct pxa_gpio_chip * c ;
int gpio ;
2008-03-04 11:13:58 +03:00
2009-01-07 13:01:51 +03:00
for_each_gpio_chip ( gpio , c ) {
2011-10-14 13:24:03 +04: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 11:13:58 +03:00
/* Clear GPIO transition detect bits */
2011-10-14 13:24:03 +04:00
writel_relaxed ( 0xffffffff , c - > regbase + GEDR_OFFSET ) ;
2008-03-04 11:13:58 +03:00
}
return 0 ;
}
2011-04-23 00:03:11 +04:00
static void pxa_gpio_resume ( void )
2008-03-04 11:13:58 +03:00
{
2009-01-07 13:01:51 +03:00
struct pxa_gpio_chip * c ;
int gpio ;
2008-03-04 11:13:58 +03:00
2009-01-07 13:01:51 +03:00
for_each_gpio_chip ( gpio , c ) {
2008-03-04 11:13:58 +03:00
/* restore level with set/clear */
2013-03-20 16:15:59 +04:00
writel_relaxed ( c - > saved_gplr , c - > regbase + GPSR_OFFSET ) ;
2011-10-14 13:24:03 +04:00
writel_relaxed ( ~ c - > saved_gplr , c - > regbase + GPCR_OFFSET ) ;
2008-03-04 11:13:58 +03:00
2011-10-14 13:24:03 +04: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 11:13:58 +03:00
}
}
# else
# define pxa_gpio_suspend NULL
# define pxa_gpio_resume NULL
# endif
2011-04-23 00:03:11 +04:00
struct syscore_ops pxa_gpio_syscore_ops = {
2008-03-04 11:13:58 +03:00
. suspend = pxa_gpio_suspend ,
. resume = pxa_gpio_resume ,
} ;
2011-10-17 16:37:52 +04:00
static int __init pxa_gpio_sysinit ( void )
{
register_syscore_ops ( & pxa_gpio_syscore_ops ) ;
return 0 ;
}
postcore_initcall ( pxa_gpio_sysinit ) ;