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>
2018-05-24 14:32:09 +02:00
# include <linux/gpio/driver.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>
2015-01-26 22:46:04 -06:00
# include <linux/interrupt.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>
2013-01-18 15:31:37 +00:00
# include <linux/irqchip/chained_irq.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>
2015-12-12 23:55:21 +01:00
# include <linux/pinctrl/consumer.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
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
*
2015-01-26 22:46:06 -06:00
* BANK 6 - 0x0200 0x020C 0x0218 0x0224 0x0230 0x023C 0x0248
*
2011-10-17 20:37:52 +08:00
* NOTE :
* BANK 3 is only available on PXA27x and later processors .
2015-01-26 22:46:06 -06:00
* BANK 4 and 5 are only available on PXA935 , PXA1928
* BANK 6 is only available on PXA1928
2011-10-17 20:37:52 +08: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 21:07:15 +08:00
# define ED_MASK_OFFSET 0x9C /* GPIO edge detection for AP side */
2011-10-17 20:37:52 +08:00
2015-03-02 15:30:58 -06:00
# define BANK_OFF(n) (((n) / 3) << 8) + (((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
2015-11-28 22:37:42 +01:00
struct pxa_gpio_bank {
2009-01-07 18:01:51 +08:00
void __iomem * regbase ;
unsigned long irq_mask ;
unsigned long irq_edge_rise ;
unsigned long irq_edge_fall ;
# 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
} ;
2015-11-28 22:37:42 +01:00
struct pxa_gpio_chip {
struct device * dev ;
struct gpio_chip chip ;
struct pxa_gpio_bank * banks ;
2015-11-28 22:37:44 +01:00
struct irq_domain * irqdomain ;
2015-11-28 22:37:42 +01:00
int irq0 ;
int irq1 ;
int ( * set_wake ) ( unsigned int gpio , unsigned int on ) ;
} ;
2013-04-07 16:44:33 +08:00
enum pxa_gpio_type {
2011-10-10 16:03:51 +08:00
PXA25X_GPIO = 0 ,
PXA26X_GPIO ,
PXA27X_GPIO ,
PXA3XX_GPIO ,
PXA93X_GPIO ,
MMP_GPIO = 0x10 ,
2013-04-07 16:44:33 +08:00
MMP2_GPIO ,
2015-01-26 22:46:06 -06:00
PXA1928_GPIO ,
2013-04-07 16:44:33 +08:00
} ;
struct pxa_gpio_id {
enum pxa_gpio_type type ;
int gpio_nums ;
2011-10-10 16:03:51 +08:00
} ;
2009-01-07 18:01:51 +08:00
static DEFINE_SPINLOCK ( gpio_lock ) ;
2015-11-28 22:37:42 +01:00
static struct pxa_gpio_chip * pxa_gpio_chip ;
2013-04-07 16:44:33 +08:00
static enum pxa_gpio_type gpio_type ;
2009-01-07 18:01:51 +08:00
2013-04-07 16:44:33 +08: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-26 22:46:06 -06:00
static struct pxa_gpio_id pxa1928_id = {
. type = PXA1928_GPIO ,
. gpio_nums = 224 ,
} ;
2015-11-28 22:37:42 +01:00
# define for_each_gpio_bank(i, b, pc) \
for ( i = 0 , b = pc - > banks ; i < = pxa_last_gpio ; i + = 32 , b + + )
2009-01-07 18:01:51 +08:00
2015-11-28 22:37:42 +01:00
static inline struct pxa_gpio_chip * chip_to_pxachip ( struct gpio_chip * c )
2009-01-07 18:01:51 +08:00
{
2015-12-07 11:42:22 +01:00
struct pxa_gpio_chip * pxa_chip = gpiochip_get_data ( c ) ;
2015-11-28 22:37:42 +01:00
return pxa_chip ;
2009-01-07 18:01:51 +08:00
}
2015-12-07 11:42:22 +01:00
2015-11-28 22:37:42 +01:00
static inline void __iomem * gpio_bank_base ( struct gpio_chip * c , int gpio )
{
2015-12-07 11:42:22 +01:00
struct pxa_gpio_chip * p = gpiochip_get_data ( c ) ;
struct pxa_gpio_bank * bank = p - > banks + ( gpio / 32 ) ;
2009-01-07 18:01:51 +08:00
2015-11-28 22:37:42 +01:00
return bank - > regbase ;
}
static inline struct pxa_gpio_bank * gpio_to_pxabank ( struct gpio_chip * c ,
unsigned gpio )
2009-01-07 18:01:51 +08:00
{
2015-11-28 22:37:42 +01:00
return chip_to_pxachip ( c ) - > banks + gpio / 32 ;
2009-01-07 18:01:51 +08:00
}
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 : - )
*/
2015-11-28 22:37:42 +01:00
static inline int __gpio_is_occupied ( struct pxa_gpio_chip * pchip , unsigned gpio )
2011-10-17 20:37:52 +08:00
{
void __iomem * base ;
unsigned long gafr = 0 , gpdr = 0 ;
int ret , af = 0 , dir = 0 ;
2015-11-28 22:37:42 +01:00
base = gpio_bank_base ( & pchip - > chip , gpio ) ;
2011-10-17 20:37:52 +08:00
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 ;
}
2015-11-28 22:37:44 +01:00
int pxa_irq_to_gpio ( int irq )
2011-10-10 16:03:51 +08:00
{
2015-11-28 22:37:44 +01:00
struct pxa_gpio_chip * pchip = pxa_gpio_chip ;
int irq_gpio0 ;
irq_gpio0 = irq_find_mapping ( pchip - > irqdomain , 0 ) ;
if ( irq_gpio0 > 0 )
return irq - irq_gpio0 ;
return irq_gpio0 ;
2011-10-10 16:03:51 +08:00
}
2018-07-13 18:15:38 +02:00
static bool pxa_gpio_has_pinctrl ( void )
{
switch ( gpio_type ) {
case PXA3XX_GPIO :
return false ;
default :
return true ;
}
}
2015-11-28 22:37:44 +01:00
static int pxa_gpio_to_irq ( struct gpio_chip * chip , unsigned offset )
2011-10-10 16:03:51 +08:00
{
2015-11-28 22:37:44 +01:00
struct pxa_gpio_chip * pchip = chip_to_pxachip ( chip ) ;
return irq_find_mapping ( pchip - > irqdomain , offset ) ;
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 )
{
2015-11-28 22:37:42 +01:00
void __iomem * base = gpio_bank_base ( chip , offset ) ;
uint32_t value , mask = GPIO_bit ( offset ) ;
2009-01-07 18:01:51 +08:00
unsigned long flags ;
2015-12-12 23:55:21 +01:00
int ret ;
2018-07-13 18:15:38 +02:00
if ( pxa_gpio_has_pinctrl ( ) ) {
ret = pinctrl_gpio_direction_input ( chip - > base + offset ) ;
if ( ! ret )
return 0 ;
}
2009-01-07 18:01:51 +08:00
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
{
2015-11-28 22:37:42 +01:00
void __iomem * base = gpio_bank_base ( chip , offset ) ;
uint32_t tmp , mask = GPIO_bit ( offset ) ;
2009-01-07 18:01:51 +08:00
unsigned long flags ;
2015-12-12 23:55:21 +01:00
int ret ;
2009-01-07 18:01:51 +08:00
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
2018-07-13 18:15:38 +02:00
if ( pxa_gpio_has_pinctrl ( ) ) {
ret = pinctrl_gpio_direction_output ( chip - > base + offset ) ;
if ( ret )
return ret ;
}
2015-12-12 23:55:21 +01:00
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 )
{
2015-11-28 22:37:42 +01:00
void __iomem * base = gpio_bank_base ( chip , offset ) ;
u32 gplr = readl_relaxed ( base + GPLR_OFFSET ) ;
return ! ! ( gplr & GPIO_bit ( offset ) ) ;
2008-02-04 22:28:22 -08:00
}
static void pxa_gpio_set ( struct gpio_chip * chip , unsigned offset , int value )
{
2015-11-28 22:37:42 +01:00
void __iomem * base = gpio_bank_base ( chip , offset ) ;
writel_relaxed ( GPIO_bit ( offset ) ,
base + ( 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 ( flags )
* flags = gpiospec - > args [ 1 ] ;
2015-11-28 22:37:42 +01:00
return gpiospec - > args [ 0 ] ;
2012-07-25 17:35:39 +02:00
}
# endif
2015-11-28 22:37:42 +01:00
static int pxa_init_gpio_chip ( struct pxa_gpio_chip * pchip , int ngpio ,
2015-11-28 22:37:44 +01:00
struct device_node * np , void __iomem * regbase )
2009-01-06 17:37:37 +08:00
{
2015-11-28 22:37:42 +01:00
int i , gpio , nbanks = DIV_ROUND_UP ( ngpio , 32 ) ;
struct pxa_gpio_bank * bank ;
2009-01-06 17:37:37 +08:00
2015-11-28 22:37:42 +01:00
pchip - > banks = devm_kcalloc ( pchip - > dev , nbanks , sizeof ( * pchip - > banks ) ,
GFP_KERNEL ) ;
if ( ! pchip - > banks )
2009-01-07 18:01:51 +08:00
return - ENOMEM ;
2009-01-06 17:37:37 +08:00
2015-11-28 22:37:42 +01:00
pchip - > chip . label = " gpio-pxa " ;
pchip - > chip . direction_input = pxa_gpio_direction_input ;
pchip - > chip . direction_output = pxa_gpio_direction_output ;
pchip - > chip . get = pxa_gpio_get ;
pchip - > chip . set = pxa_gpio_set ;
pchip - > chip . to_irq = pxa_gpio_to_irq ;
pchip - > chip . ngpio = ngpio ;
2018-07-13 18:15:38 +02:00
if ( pxa_gpio_has_pinctrl ( ) ) {
pchip - > chip . request = gpiochip_generic_request ;
pchip - > chip . free = gpiochip_generic_free ;
}
2012-07-25 17:35:39 +02:00
# ifdef CONFIG_OF_GPIO
2015-11-28 22:37:44 +01:00
pchip - > chip . of_node = np ;
2015-11-28 22:37:42 +01:00
pchip - > chip . of_xlate = pxa_gpio_of_xlate ;
pchip - > chip . of_gpio_n_cells = 2 ;
2012-07-25 17:35:39 +02:00
# endif
2009-01-07 18:01:51 +08:00
2015-11-28 22:37:42 +01:00
for ( i = 0 , gpio = 0 ; i < nbanks ; i + + , gpio + = 32 ) {
bank = pchip - > banks + i ;
bank - > regbase = regbase + BANK_OFF ( i ) ;
2009-01-07 18:01:51 +08:00
}
2015-11-28 22:37:42 +01:00
2015-12-07 11:42:22 +01:00
return gpiochip_add_data ( & pchip - > chip , pchip ) ;
2009-01-07 18:01:51 +08:00
}
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
*/
2015-11-28 22:37:42 +01:00
static inline void update_edge_detect ( struct pxa_gpio_bank * c )
2009-04-21 14:39:07 +08:00
{
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
{
2015-11-28 22:37:44 +01:00
struct pxa_gpio_chip * pchip = irq_data_get_irq_chip_data ( d ) ;
unsigned int gpio = irqd_to_hwirq ( d ) ;
2015-11-28 22:37:42 +01:00
struct pxa_gpio_bank * c = gpio_to_pxabank ( & pchip - > chip , gpio ) ;
2009-01-07 18:01:51 +08:00
unsigned long gpdr , mask = GPIO_bit ( 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
2015-11-28 22:37:42 +01:00
if ( __gpio_is_occupied ( pchip , 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 ;
}
2015-11-28 22:37:44 +01:00
static irqreturn_t pxa_gpio_demux_handler ( int in_irq , void * d )
2008-03-04 11:42:26 +08:00
{
2015-11-28 22:37:42 +01:00
int loop , gpio , n , handled = 0 ;
2009-01-07 18:01:51 +08:00
unsigned long gedr ;
2015-11-28 22:37:44 +01:00
struct pxa_gpio_chip * pchip = d ;
2015-11-28 22:37:42 +01:00
struct pxa_gpio_bank * c ;
2012-07-31 14:13:09 +08:00
2008-03-04 11:42:26 +08:00
do {
loop = 0 ;
2015-11-28 22:37:42 +01:00
for_each_gpio_bank ( gpio , c , pchip ) {
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
2017-07-08 17:44:12 -05:00
generic_handle_irq (
irq_find_mapping ( pchip - > irqdomain ,
gpio + n ) ) ;
2009-01-07 18:01:51 +08:00
}
2008-03-04 11:42:26 +08:00
}
2015-11-28 22:37:44 +01:00
handled + = loop ;
2008-03-04 11:42:26 +08:00
} while ( loop ) ;
2012-07-31 14:13:09 +08:00
2015-11-28 22:37:44 +01:00
return handled ? IRQ_HANDLED : IRQ_NONE ;
}
static irqreturn_t pxa_gpio_direct_handler ( int in_irq , void * d )
{
struct pxa_gpio_chip * pchip = d ;
if ( in_irq = = pchip - > irq0 ) {
2017-07-08 17:44:12 -05:00
generic_handle_irq ( irq_find_mapping ( pchip - > irqdomain , 0 ) ) ;
2015-11-28 22:37:44 +01:00
} else if ( in_irq = = pchip - > irq1 ) {
2017-07-08 17:44:12 -05:00
generic_handle_irq ( irq_find_mapping ( pchip - > irqdomain , 1 ) ) ;
2015-11-28 22:37:44 +01:00
} else {
pr_err ( " %s() unknown irq %d \n " , __func__ , in_irq ) ;
return IRQ_NONE ;
}
return IRQ_HANDLED ;
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
{
2015-11-28 22:37:44 +01:00
struct pxa_gpio_chip * pchip = irq_data_get_irq_chip_data ( d ) ;
unsigned int gpio = irqd_to_hwirq ( d ) ;
2015-11-28 22:37:42 +01:00
void __iomem * base = gpio_bank_base ( & pchip - > chip , gpio ) ;
2009-01-07 18:01:51 +08:00
2015-11-28 22:37:42 +01:00
writel_relaxed ( GPIO_bit ( gpio ) , base + 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
{
2015-11-28 22:37:44 +01:00
struct pxa_gpio_chip * pchip = irq_data_get_irq_chip_data ( d ) ;
unsigned int gpio = irqd_to_hwirq ( d ) ;
2015-11-28 22:37:42 +01:00
struct pxa_gpio_bank * b = gpio_to_pxabank ( & pchip - > chip , gpio ) ;
void __iomem * base = gpio_bank_base ( & pchip - > chip , gpio ) ;
2009-01-07 18:01:51 +08:00
uint32_t grer , gfer ;
2015-11-28 22:37:42 +01:00
b - > irq_mask & = ~ GPIO_bit ( gpio ) ;
2009-01-07 18:01:51 +08:00
2015-11-28 22:37:42 +01:00
grer = readl_relaxed ( base + GRER_OFFSET ) & ~ GPIO_bit ( gpio ) ;
gfer = readl_relaxed ( base + GFER_OFFSET ) & ~ GPIO_bit ( gpio ) ;
writel_relaxed ( grer , base + GRER_OFFSET ) ;
writel_relaxed ( gfer , base + 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 )
{
2015-11-28 22:37:44 +01:00
struct pxa_gpio_chip * pchip = irq_data_get_irq_chip_data ( d ) ;
unsigned int gpio = irqd_to_hwirq ( d ) ;
2012-04-22 13:37:24 +02:00
2015-11-28 22:37:42 +01:00
if ( pchip - > set_wake )
return pchip - > set_wake ( gpio , on ) ;
2012-04-22 13:37:24 +02:00
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
{
2015-11-28 22:37:44 +01:00
struct pxa_gpio_chip * pchip = irq_data_get_irq_chip_data ( d ) ;
unsigned int gpio = irqd_to_hwirq ( d ) ;
2015-11-28 22:37:42 +01:00
struct pxa_gpio_bank * c = gpio_to_pxabank ( & pchip - > chip , 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
} ;
2013-04-07 16:44:33 +08:00
static int pxa_gpio_nums ( struct platform_device * pdev )
2011-10-14 16:44:07 +08:00
{
2013-04-07 16:44:33 +08: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 16:44:07 +08:00
int count = 0 ;
2013-04-07 16:44:33 +08: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-26 22:46:06 -06:00
case PXA1928_GPIO :
2013-04-07 16:44:33 +08:00
gpio_type = pxa_id - > type ;
count = pxa_id - > gpio_nums - 1 ;
break ;
default :
count = - EINVAL ;
break ;
2011-10-14 16:44:07 +08:00
}
return count ;
}
2012-04-13 15:15:45 +08: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 ) ;
2015-11-28 22:37:44 +01:00
irq_set_chip_data ( irq , d - > host_data ) ;
2015-07-27 15:55:16 -05:00
irq_set_noprobe ( irq ) ;
2012-04-13 15:15:45 +08:00
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
} ;
2015-12-18 21:40:40 +01:00
# ifdef CONFIG_OF
static const struct of_device_id pxa_gpio_dt_ids [ ] = {
{ . 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 , } ,
{ . compatible = " marvell,pxa1928-gpio " , . data = & pxa1928_id , } ,
{ }
} ;
2015-11-28 22:37:42 +01:00
static int pxa_gpio_probe_dt ( struct platform_device * pdev ,
struct pxa_gpio_chip * pchip )
2012-04-13 15:15:45 +08:00
{
2015-11-28 22:37:42 +01:00
int nr_gpios ;
2013-04-09 22:27:50 +08:00
const struct pxa_gpio_id * gpio_id ;
2012-04-13 15:15:45 +08:00
2018-04-30 09:38:15 +02:00
gpio_id = of_device_get_match_data ( & pdev - > dev ) ;
2013-04-09 22:27:50 +08:00
gpio_type = gpio_id - > type ;
2012-04-13 15:15:45 +08:00
2013-04-09 22:27:50 +08:00
nr_gpios = gpio_id - > gpio_nums ;
2012-04-13 15:15:45 +08:00
pxa_last_gpio = nr_gpios - 1 ;
2017-03-04 17:23:35 +01:00
irq_base = devm_irq_alloc_descs ( & pdev - > dev , - 1 , 0 , nr_gpios , 0 ) ;
2012-04-13 15:15:45 +08:00
if ( irq_base < 0 ) {
dev_err ( & pdev - > dev , " Failed to allocate IRQ numbers \n " ) ;
2015-11-28 22:37:42 +01:00
return irq_base ;
2012-04-13 15:15:45 +08:00
}
2015-11-28 22:37:44 +01:00
return irq_base ;
2012-04-13 15:15:45 +08:00
}
# else
2015-11-28 22:37:42 +01:00
# define pxa_gpio_probe_dt(pdev, pchip) (-1)
2012-04-13 15:15:45 +08:00
# endif
2012-11-19 13:22:34 -05:00
static int pxa_gpio_probe ( struct platform_device * pdev )
2008-03-04 11:42:26 +08:00
{
2015-11-28 22:37:42 +01:00
struct pxa_gpio_chip * pchip ;
struct pxa_gpio_bank * 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 ;
2015-11-28 22:37:42 +01:00
void __iomem * gpio_reg_base ;
2015-11-28 22:37:44 +01:00
int gpio , ret ;
2018-08-01 01:40:31 +00:00
int irq0 = 0 , irq1 = 0 , irq_mux ;
2008-03-04 11:42:26 +08:00
2015-11-28 22:37:42 +01:00
pchip = devm_kzalloc ( & pdev - > dev , sizeof ( * pchip ) , GFP_KERNEL ) ;
if ( ! pchip )
return - ENOMEM ;
pchip - > dev = & pdev - > dev ;
2013-04-09 18:12:04 +08:00
info = dev_get_platdata ( & pdev - > dev ) ;
if ( info ) {
irq_base = info - > irq_base ;
if ( irq_base < = 0 )
return - EINVAL ;
2013-04-07 16:44:33 +08:00
pxa_last_gpio = pxa_gpio_nums ( pdev ) ;
2015-11-28 22:37:42 +01:00
pchip - > set_wake = info - > gpio_set_wake ;
2012-07-22 16:55:44 +02:00
} else {
2015-11-28 22:37:44 +01:00
irq_base = pxa_gpio_probe_dt ( pdev , pchip ) ;
if ( irq_base < 0 )
2013-04-09 18:12:04 +08:00
return - EINVAL ;
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 ;
2015-11-28 22:37:44 +01:00
pchip - > irqdomain = irq_domain_add_legacy ( pdev - > dev . of_node ,
pxa_last_gpio + 1 , irq_base ,
0 , & pxa_irq_domain_ops , pchip ) ;
2016-01-05 12:56:37 +03:00
if ( ! pchip - > irqdomain )
return - ENOMEM ;
2015-11-28 22:37:44 +01:00
2011-10-17 20:37:52 +08:00
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 ;
2015-11-28 22:37:44 +01:00
pchip - > irq0 = irq0 ;
pchip - > irq1 = irq1 ;
2011-10-17 20:37:52 +08:00
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
gpio: pxa: Fix potential NULL dereference
platform_get_resource() may fail and return NULL, so we should
better check it's return value to avoid a NULL pointer dereference
a bit later in the code.
This is detected by Coccinelle semantic patch.
@@
expression pdev, res, n, t, e, e1, e2;
@@
res = platform_get_resource(pdev, t, n);
+ if (!res)
+ return -EINVAL;
... when != res == NULL
e = devm_ioremap(e1, res->start, e2);
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-07-11 13:19:38 +00:00
if ( ! res )
return - EINVAL ;
2015-11-28 22:37:43 +01:00
gpio_reg_base = devm_ioremap ( & pdev - > dev , res - > start ,
resource_size ( res ) ) ;
2011-10-17 20:37:52 +08:00
if ( ! gpio_reg_base )
return - EINVAL ;
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 ) ) ;
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 ) ;
return ret ;
}
2009-01-07 18:01:51 +08:00
/* Initialize GPIO chips */
2015-11-28 22:37:44 +01:00
ret = pxa_init_gpio_chip ( pchip , pxa_last_gpio + 1 , pdev - > dev . of_node ,
gpio_reg_base ) ;
2015-11-28 22:37:42 +01:00
if ( ret ) {
clk_put ( clk ) ;
return ret ;
}
2009-01-07 18:01:51 +08:00
2008-03-04 11:42:26 +08:00
/* clear all GPIO edge detects */
2015-11-28 22:37:42 +01:00
for_each_gpio_bank ( gpio , c , pchip ) {
2011-10-14 17:24:03 +08:00
writel_relaxed ( 0 , c - > regbase + GFER_OFFSET ) ;
writel_relaxed ( 0 , c - > regbase + GRER_OFFSET ) ;
2013-03-20 13:15:59 +01:00
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
}
2015-11-28 22:37:44 +01:00
if ( irq0 > 0 ) {
ret = devm_request_irq ( & pdev - > dev ,
irq0 , pxa_gpio_direct_handler , 0 ,
" gpio-0 " , pchip ) ;
if ( ret )
dev_err ( & pdev - > dev , " request of gpio0 irq failed: %d \n " ,
ret ) ;
2008-03-04 11:42:26 +08:00
}
2015-11-28 22:37:44 +01:00
if ( irq1 > 0 ) {
ret = devm_request_irq ( & pdev - > dev ,
irq1 , pxa_gpio_direct_handler , 0 ,
" gpio-1 " , pchip ) ;
if ( ret )
dev_err ( & pdev - > dev , " request of gpio1 irq failed: %d \n " ,
ret ) ;
}
ret = devm_request_irq ( & pdev - > dev ,
irq_mux , pxa_gpio_demux_handler , 0 ,
" gpio-mux " , pchip ) ;
if ( ret )
dev_err ( & pdev - > dev , " request of gpio-mux irq failed: %d \n " ,
ret ) ;
2008-03-04 11:42:26 +08:00
2015-11-28 22:37:42 +01:00
pxa_gpio_chip = pchip ;
2015-01-26 22:46:04 -06:00
2011-10-17 20:37:52 +08:00
return 0 ;
}
2013-04-07 16:44:33 +08: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-26 22:46:06 -06:00
{ " pxa1928-gpio " , ( unsigned long ) & pxa1928_id } ,
2013-04-07 16:44:33 +08:00
{ } ,
} ;
2011-10-17 20:37:52 +08:00
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
} ,
2013-04-07 16:44:33 +08:00
. id_table = gpio_id_table ,
2011-10-17 20:37:52 +08:00
} ;
2013-04-24 21:41:20 +02:00
2015-11-13 21:22:38 +01:00
static int __init pxa_gpio_legacy_init ( void )
2013-04-24 21:41:20 +02:00
{
2015-11-13 21:22:38 +01:00
if ( of_have_populated_dt ( ) )
return 0 ;
2013-04-24 21:41:20 +02:00
return platform_driver_register ( & pxa_gpio_driver ) ;
}
2015-11-13 21:22:38 +01:00
postcore_initcall ( pxa_gpio_legacy_init ) ;
static int __init pxa_gpio_dt_init ( void )
{
if ( of_have_populated_dt ( ) )
return platform_driver_register ( & pxa_gpio_driver ) ;
return 0 ;
}
device_initcall ( pxa_gpio_dt_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
{
2015-11-28 22:37:42 +01:00
struct pxa_gpio_chip * pchip = pxa_gpio_chip ;
struct pxa_gpio_bank * c ;
2009-01-07 18:01:51 +08:00
int gpio ;
2008-03-04 16:13:58 +08:00
2015-11-28 22:37:42 +01:00
for_each_gpio_bank ( gpio , c , pchip ) {
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
{
2015-11-28 22:37:42 +01:00
struct pxa_gpio_chip * pchip = pxa_gpio_chip ;
struct pxa_gpio_bank * c ;
2009-01-07 18:01:51 +08:00
int gpio ;
2008-03-04 16:13:58 +08:00
2015-11-28 22:37:42 +01:00
for_each_gpio_bank ( gpio , c , pchip ) {
2008-03-04 16:13:58 +08:00
/* restore level with set/clear */
2013-03-20 13:15:59 +01:00
writel_relaxed ( c - > saved_gplr , c - > regbase + GPSR_OFFSET ) ;
2011-10-14 17:24:03 +08:00
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 ) ;