2013-03-13 15:32:13 +04:00
/*
* Renesas R - Car GPIO Support
*
2014-11-07 14:54:08 +03:00
* Copyright ( C ) 2014 Renesas Electronics Corporation
2013-03-13 15:32:13 +04:00
* Copyright ( C ) 2013 Magnus Damm
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License
*
* 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 .
*/
2015-03-18 21:41:09 +03:00
# include <linux/clk.h>
2013-03-13 15:32:13 +04:00
# include <linux/err.h>
# include <linux/gpio.h>
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/ioport.h>
# include <linux/irq.h>
# include <linux/module.h>
2013-10-16 14:05:02 +04:00
# include <linux/of.h>
2013-03-10 06:27:00 +04:00
# include <linux/pinctrl/consumer.h>
2013-03-13 15:32:13 +04:00
# include <linux/platform_data/gpio-rcar.h>
# include <linux/platform_device.h>
2014-04-14 22:33:13 +04:00
# include <linux/pm_runtime.h>
2013-03-13 15:32:13 +04:00
# include <linux/spinlock.h>
# include <linux/slab.h>
struct gpio_rcar_priv {
void __iomem * base ;
spinlock_t lock ;
struct gpio_rcar_config config ;
struct platform_device * pdev ;
struct gpio_chip gpio_chip ;
struct irq_chip irq_chip ;
2015-03-18 21:41:09 +03:00
unsigned int irq_parent ;
struct clk * clk ;
2013-03-13 15:32:13 +04:00
} ;
2015-03-18 21:41:08 +03:00
# define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */
# define INOUTSEL 0x04 /* General Input/Output Switching Register */
# define OUTDT 0x08 /* General Output Register */
# define INDT 0x0c /* General Input Register */
# define INTDT 0x10 /* Interrupt Display Register */
# define INTCLR 0x14 /* Interrupt Clear Register */
# define INTMSK 0x18 /* Interrupt Mask Register */
# define MSKCLR 0x1c /* Interrupt Mask Clear Register */
# define POSNEG 0x20 /* Positive/Negative Logic Select Register */
# define EDGLEVEL 0x24 /* Edge/level Select Register */
# define FILONOFF 0x28 /* Chattering Prevention On/Off Register */
# define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
2013-03-13 15:32:13 +04:00
2013-05-21 15:40:06 +04:00
# define RCAR_MAX_GPIO_PER_BANK 32
2013-03-13 15:32:13 +04:00
static inline u32 gpio_rcar_read ( struct gpio_rcar_priv * p , int offs )
{
return ioread32 ( p - > base + offs ) ;
}
static inline void gpio_rcar_write ( struct gpio_rcar_priv * p , int offs ,
u32 value )
{
iowrite32 ( value , p - > base + offs ) ;
}
static void gpio_rcar_modify_bit ( struct gpio_rcar_priv * p , int offs ,
int bit , bool value )
{
u32 tmp = gpio_rcar_read ( p , offs ) ;
if ( value )
tmp | = BIT ( bit ) ;
else
tmp & = ~ BIT ( bit ) ;
gpio_rcar_write ( p , offs , tmp ) ;
}
static void gpio_rcar_irq_disable ( struct irq_data * d )
{
2015-01-12 13:07:59 +03:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
struct gpio_rcar_priv * p = container_of ( gc , struct gpio_rcar_priv ,
gpio_chip ) ;
2013-03-13 15:32:13 +04:00
gpio_rcar_write ( p , INTMSK , ~ BIT ( irqd_to_hwirq ( d ) ) ) ;
}
static void gpio_rcar_irq_enable ( struct irq_data * d )
{
2015-01-12 13:07:59 +03:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
struct gpio_rcar_priv * p = container_of ( gc , struct gpio_rcar_priv ,
gpio_chip ) ;
2013-03-13 15:32:13 +04:00
gpio_rcar_write ( p , MSKCLR , BIT ( irqd_to_hwirq ( d ) ) ) ;
}
static void gpio_rcar_config_interrupt_input_mode ( struct gpio_rcar_priv * p ,
unsigned int hwirq ,
bool active_high_rising_edge ,
2013-05-24 13:47:24 +04:00
bool level_trigger ,
bool both )
2013-03-13 15:32:13 +04:00
{
unsigned long flags ;
/* follow steps in the GPIO documentation for
* " Setting Edge-Sensitive Interrupt Input Mode " and
* " Setting Level-Sensitive Interrupt Input Mode "
*/
spin_lock_irqsave ( & p - > lock , flags ) ;
/* Configure postive or negative logic in POSNEG */
gpio_rcar_modify_bit ( p , POSNEG , hwirq , ! active_high_rising_edge ) ;
/* Configure edge or level trigger in EDGLEVEL */
gpio_rcar_modify_bit ( p , EDGLEVEL , hwirq , ! level_trigger ) ;
2013-05-24 13:47:24 +04:00
/* Select one edge or both edges in BOTHEDGE */
if ( p - > config . has_both_edge_trigger )
gpio_rcar_modify_bit ( p , BOTHEDGE , hwirq , both ) ;
2013-03-13 15:32:13 +04:00
/* Select "Interrupt Input Mode" in IOINTSEL */
gpio_rcar_modify_bit ( p , IOINTSEL , hwirq , true ) ;
/* Write INTCLR in case of edge trigger */
if ( ! level_trigger )
gpio_rcar_write ( p , INTCLR , BIT ( hwirq ) ) ;
spin_unlock_irqrestore ( & p - > lock , flags ) ;
}
static int gpio_rcar_irq_set_type ( struct irq_data * d , unsigned int type )
{
2015-01-12 13:07:59 +03:00
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
struct gpio_rcar_priv * p = container_of ( gc , struct gpio_rcar_priv ,
gpio_chip ) ;
2013-03-13 15:32:13 +04:00
unsigned int hwirq = irqd_to_hwirq ( d ) ;
dev_dbg ( & p - > pdev - > dev , " sense irq = %d, type = %d \n " , hwirq , type ) ;
switch ( type & IRQ_TYPE_SENSE_MASK ) {
case IRQ_TYPE_LEVEL_HIGH :
2013-05-24 13:47:24 +04:00
gpio_rcar_config_interrupt_input_mode ( p , hwirq , true , true ,
false ) ;
2013-03-13 15:32:13 +04:00
break ;
case IRQ_TYPE_LEVEL_LOW :
2013-05-24 13:47:24 +04:00
gpio_rcar_config_interrupt_input_mode ( p , hwirq , false , true ,
false ) ;
2013-03-13 15:32:13 +04:00
break ;
case IRQ_TYPE_EDGE_RISING :
2013-05-24 13:47:24 +04:00
gpio_rcar_config_interrupt_input_mode ( p , hwirq , true , false ,
false ) ;
2013-03-13 15:32:13 +04:00
break ;
case IRQ_TYPE_EDGE_FALLING :
2013-05-24 13:47:24 +04:00
gpio_rcar_config_interrupt_input_mode ( p , hwirq , false , false ,
false ) ;
break ;
case IRQ_TYPE_EDGE_BOTH :
if ( ! p - > config . has_both_edge_trigger )
return - EINVAL ;
gpio_rcar_config_interrupt_input_mode ( p , hwirq , true , false ,
true ) ;
2013-03-13 15:32:13 +04:00
break ;
default :
return - EINVAL ;
}
return 0 ;
}
2015-03-18 21:41:09 +03:00
static int gpio_rcar_irq_set_wake ( struct irq_data * d , unsigned int on )
{
struct gpio_chip * gc = irq_data_get_irq_chip_data ( d ) ;
struct gpio_rcar_priv * p = container_of ( gc , struct gpio_rcar_priv ,
gpio_chip ) ;
2015-05-21 14:21:37 +03:00
int error ;
if ( p - > irq_parent ) {
error = irq_set_irq_wake ( p - > irq_parent , on ) ;
if ( error ) {
dev_dbg ( & p - > pdev - > dev ,
" irq %u doesn't support irq_set_wake \n " ,
p - > irq_parent ) ;
p - > irq_parent = 0 ;
}
}
2015-03-18 21:41:09 +03:00
if ( ! p - > clk )
return 0 ;
if ( on )
clk_enable ( p - > clk ) ;
else
clk_disable ( p - > clk ) ;
return 0 ;
}
2013-03-13 15:32:13 +04:00
static irqreturn_t gpio_rcar_irq_handler ( int irq , void * dev_id )
{
struct gpio_rcar_priv * p = dev_id ;
u32 pending ;
unsigned int offset , irqs_handled = 0 ;
2013-11-29 22:04:09 +04:00
while ( ( pending = gpio_rcar_read ( p , INTDT ) &
gpio_rcar_read ( p , INTMSK ) ) ) {
2013-03-13 15:32:13 +04:00
offset = __ffs ( pending ) ;
gpio_rcar_write ( p , INTCLR , BIT ( offset ) ) ;
2015-01-12 13:07:59 +03:00
generic_handle_irq ( irq_find_mapping ( p - > gpio_chip . irqdomain ,
offset ) ) ;
2013-03-13 15:32:13 +04:00
irqs_handled + + ;
}
return irqs_handled ? IRQ_HANDLED : IRQ_NONE ;
}
static inline struct gpio_rcar_priv * gpio_to_priv ( struct gpio_chip * chip )
{
return container_of ( chip , struct gpio_rcar_priv , gpio_chip ) ;
}
static void gpio_rcar_config_general_input_output_mode ( struct gpio_chip * chip ,
unsigned int gpio ,
bool output )
{
struct gpio_rcar_priv * p = gpio_to_priv ( chip ) ;
unsigned long flags ;
/* follow steps in the GPIO documentation for
* " Setting General Output Mode " and
* " Setting General Input Mode "
*/
spin_lock_irqsave ( & p - > lock , flags ) ;
/* Configure postive logic in POSNEG */
gpio_rcar_modify_bit ( p , POSNEG , gpio , false ) ;
/* Select "General Input/Output Mode" in IOINTSEL */
gpio_rcar_modify_bit ( p , IOINTSEL , gpio , false ) ;
/* Select Input Mode or Output Mode in INOUTSEL */
gpio_rcar_modify_bit ( p , INOUTSEL , gpio , output ) ;
spin_unlock_irqrestore ( & p - > lock , flags ) ;
}
2013-03-10 06:27:00 +04:00
static int gpio_rcar_request ( struct gpio_chip * chip , unsigned offset )
{
gpio: rcar: Fine-grained Runtime PM support
Currently gpio modules are runtime-resumed at probe time. This means the
gpio module will be active all the time (except during system suspend,
if not configured as a wake-up source).
While an R-Car Gen2 gpio module retains pins configured for output at
the requested level while put in standby mode, gpio registercannot be
accessed while suspended. Unfortunately pm_runtime_get_sync() cannot be
called from all contexts where gpio register access is needed. Hence
move the Runtime PM handling from probe/remove time to gpio request/free
time, which is probably the best we can do.
On r8a7791/koelsch, gpio modules 0, 1, 3, and 4 are now suspended during
normal use (gpio2 is used for LEDs and regulators, gpio5 for keys, gpio6
for SD-Card CD & WP, gpio7 for keys and regulators).
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2015-06-25 17:45:57 +03:00
struct gpio_rcar_priv * p = gpio_to_priv ( chip ) ;
int error ;
error = pm_runtime_get_sync ( & p - > pdev - > dev ) ;
if ( error < 0 )
return error ;
error = pinctrl_request_gpio ( chip - > base + offset ) ;
if ( error )
pm_runtime_put ( & p - > pdev - > dev ) ;
return error ;
2013-03-10 06:27:00 +04:00
}
static void gpio_rcar_free ( struct gpio_chip * chip , unsigned offset )
{
gpio: rcar: Fine-grained Runtime PM support
Currently gpio modules are runtime-resumed at probe time. This means the
gpio module will be active all the time (except during system suspend,
if not configured as a wake-up source).
While an R-Car Gen2 gpio module retains pins configured for output at
the requested level while put in standby mode, gpio registercannot be
accessed while suspended. Unfortunately pm_runtime_get_sync() cannot be
called from all contexts where gpio register access is needed. Hence
move the Runtime PM handling from probe/remove time to gpio request/free
time, which is probably the best we can do.
On r8a7791/koelsch, gpio modules 0, 1, 3, and 4 are now suspended during
normal use (gpio2 is used for LEDs and regulators, gpio5 for keys, gpio6
for SD-Card CD & WP, gpio7 for keys and regulators).
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2015-06-25 17:45:57 +03:00
struct gpio_rcar_priv * p = gpio_to_priv ( chip ) ;
2013-03-10 06:27:00 +04:00
pinctrl_free_gpio ( chip - > base + offset ) ;
/* Set the GPIO as an input to ensure that the next GPIO request won't
* drive the GPIO pin as an output .
*/
gpio_rcar_config_general_input_output_mode ( chip , offset , false ) ;
gpio: rcar: Fine-grained Runtime PM support
Currently gpio modules are runtime-resumed at probe time. This means the
gpio module will be active all the time (except during system suspend,
if not configured as a wake-up source).
While an R-Car Gen2 gpio module retains pins configured for output at
the requested level while put in standby mode, gpio registercannot be
accessed while suspended. Unfortunately pm_runtime_get_sync() cannot be
called from all contexts where gpio register access is needed. Hence
move the Runtime PM handling from probe/remove time to gpio request/free
time, which is probably the best we can do.
On r8a7791/koelsch, gpio modules 0, 1, 3, and 4 are now suspended during
normal use (gpio2 is used for LEDs and regulators, gpio5 for keys, gpio6
for SD-Card CD & WP, gpio7 for keys and regulators).
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2015-06-25 17:45:57 +03:00
pm_runtime_put ( & p - > pdev - > dev ) ;
2013-03-10 06:27:00 +04:00
}
2013-03-13 15:32:13 +04:00
static int gpio_rcar_direction_input ( struct gpio_chip * chip , unsigned offset )
{
gpio_rcar_config_general_input_output_mode ( chip , offset , false ) ;
return 0 ;
}
static int gpio_rcar_get ( struct gpio_chip * chip , unsigned offset )
{
2013-06-17 03:41:52 +04:00
u32 bit = BIT ( offset ) ;
/* testing on r8a7790 shows that INDT does not show correct pin state
* when configured as output , so use OUTDT in case of output pins */
if ( gpio_rcar_read ( gpio_to_priv ( chip ) , INOUTSEL ) & bit )
2014-06-24 06:19:50 +04:00
return ! ! ( gpio_rcar_read ( gpio_to_priv ( chip ) , OUTDT ) & bit ) ;
2013-06-17 03:41:52 +04:00
else
2014-06-24 06:19:50 +04:00
return ! ! ( gpio_rcar_read ( gpio_to_priv ( chip ) , INDT ) & bit ) ;
2013-03-13 15:32:13 +04:00
}
static void gpio_rcar_set ( struct gpio_chip * chip , unsigned offset , int value )
{
struct gpio_rcar_priv * p = gpio_to_priv ( chip ) ;
unsigned long flags ;
spin_lock_irqsave ( & p - > lock , flags ) ;
gpio_rcar_modify_bit ( p , OUTDT , offset , value ) ;
spin_unlock_irqrestore ( & p - > lock , flags ) ;
}
static int gpio_rcar_direction_output ( struct gpio_chip * chip , unsigned offset ,
int value )
{
/* write GPIO value to output before selecting output mode of pin */
gpio_rcar_set ( chip , offset , value ) ;
gpio_rcar_config_general_input_output_mode ( chip , offset , true ) ;
return 0 ;
}
2013-11-29 17:48:00 +04:00
struct gpio_rcar_info {
bool has_both_edge_trigger ;
} ;
2014-11-07 14:54:08 +03:00
static const struct gpio_rcar_info gpio_rcar_info_gen1 = {
. has_both_edge_trigger = false ,
} ;
static const struct gpio_rcar_info gpio_rcar_info_gen2 = {
. has_both_edge_trigger = true ,
} ;
2013-11-29 17:48:00 +04:00
static const struct of_device_id gpio_rcar_of_table [ ] = {
{
. compatible = " renesas,gpio-r8a7790 " ,
2014-11-07 14:54:08 +03:00
. data = & gpio_rcar_info_gen2 ,
2013-11-29 17:48:00 +04:00
} , {
. compatible = " renesas,gpio-r8a7791 " ,
2014-11-07 14:54:08 +03:00
. data = & gpio_rcar_info_gen2 ,
} , {
. compatible = " renesas,gpio-r8a7793 " ,
. data = & gpio_rcar_info_gen2 ,
} , {
. compatible = " renesas,gpio-r8a7794 " ,
. data = & gpio_rcar_info_gen2 ,
2015-07-21 12:08:50 +03:00
} , {
. compatible = " renesas,gpio-r8a7795 " ,
/* Gen3 GPIO is identical to Gen2. */
. data = & gpio_rcar_info_gen2 ,
2013-11-29 17:48:00 +04:00
} , {
. compatible = " renesas,gpio-rcar " ,
2014-11-07 14:54:08 +03:00
. data = & gpio_rcar_info_gen1 ,
2013-11-29 17:48:00 +04:00
} , {
/* Terminator */
} ,
} ;
MODULE_DEVICE_TABLE ( of , gpio_rcar_of_table ) ;
static int gpio_rcar_parse_pdata ( struct gpio_rcar_priv * p )
2013-05-21 15:40:06 +04:00
{
2013-07-30 12:08:05 +04:00
struct gpio_rcar_config * pdata = dev_get_platdata ( & p - > pdev - > dev ) ;
2013-05-21 15:40:06 +04:00
struct device_node * np = p - > pdev - > dev . of_node ;
struct of_phandle_args args ;
int ret ;
2013-06-18 14:29:49 +04:00
if ( pdata ) {
2013-05-21 15:40:06 +04:00
p - > config = * pdata ;
2013-06-18 14:29:49 +04:00
} else if ( IS_ENABLED ( CONFIG_OF ) & & np ) {
2013-11-29 17:48:00 +04:00
const struct of_device_id * match ;
const struct gpio_rcar_info * info ;
match = of_match_node ( gpio_rcar_of_table , np ) ;
if ( ! match )
return - EINVAL ;
info = match - > data ;
2013-09-11 17:51:01 +04:00
ret = of_parse_phandle_with_fixed_args ( np , " gpio-ranges " , 3 , 0 ,
& args ) ;
p - > config . number_of_pins = ret = = 0 ? args . args [ 2 ]
2013-05-21 15:40:06 +04:00
: RCAR_MAX_GPIO_PER_BANK ;
p - > config . gpio_base = - 1 ;
2013-11-29 17:48:00 +04:00
p - > config . has_both_edge_trigger = info - > has_both_edge_trigger ;
2013-05-21 15:40:06 +04:00
}
if ( p - > config . number_of_pins = = 0 | |
p - > config . number_of_pins > RCAR_MAX_GPIO_PER_BANK ) {
dev_warn ( & p - > pdev - > dev ,
" Invalid number of gpio lines %u, using %u \n " ,
p - > config . number_of_pins , RCAR_MAX_GPIO_PER_BANK ) ;
p - > config . number_of_pins = RCAR_MAX_GPIO_PER_BANK ;
}
2013-11-29 17:48:00 +04:00
return 0 ;
2013-05-21 15:40:06 +04:00
}
2013-03-13 15:32:13 +04:00
static int gpio_rcar_probe ( struct platform_device * pdev )
{
struct gpio_rcar_priv * p ;
struct resource * io , * irq ;
struct gpio_chip * gpio_chip ;
struct irq_chip * irq_chip ;
2014-03-28 00:47:36 +04:00
struct device * dev = & pdev - > dev ;
const char * name = dev_name ( dev ) ;
2013-03-13 15:32:13 +04:00
int ret ;
2014-03-28 00:47:36 +04:00
p = devm_kzalloc ( dev , sizeof ( * p ) , GFP_KERNEL ) ;
2015-01-12 13:07:58 +03:00
if ( ! p )
return - ENOMEM ;
2013-03-13 15:32:13 +04:00
p - > pdev = pdev ;
spin_lock_init ( & p - > lock ) ;
2013-05-21 15:40:06 +04:00
/* Get device configuration from DT node or platform data. */
2013-11-29 17:48:00 +04:00
ret = gpio_rcar_parse_pdata ( p ) ;
if ( ret < 0 )
return ret ;
2013-05-21 15:40:06 +04:00
platform_set_drvdata ( pdev , p ) ;
2015-03-18 21:41:09 +03:00
p - > clk = devm_clk_get ( dev , NULL ) ;
if ( IS_ERR ( p - > clk ) ) {
dev_warn ( dev , " unable to get clock \n " ) ;
p - > clk = NULL ;
}
2014-04-14 22:33:13 +04:00
pm_runtime_enable ( dev ) ;
2013-03-13 15:32:13 +04:00
io = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
irq = platform_get_resource ( pdev , IORESOURCE_IRQ , 0 ) ;
if ( ! io | | ! irq ) {
2014-03-28 00:47:36 +04:00
dev_err ( dev , " missing IRQ or IOMEM \n " ) ;
2013-03-13 15:32:13 +04:00
ret = - EINVAL ;
goto err0 ;
}
2014-03-28 00:47:36 +04:00
p - > base = devm_ioremap_nocache ( dev , io - > start , resource_size ( io ) ) ;
2013-03-13 15:32:13 +04:00
if ( ! p - > base ) {
2014-03-28 00:47:36 +04:00
dev_err ( dev , " failed to remap I/O memory \n " ) ;
2013-03-13 15:32:13 +04:00
ret = - ENXIO ;
goto err0 ;
}
gpio_chip = & p - > gpio_chip ;
2013-03-10 06:27:00 +04:00
gpio_chip - > request = gpio_rcar_request ;
gpio_chip - > free = gpio_rcar_free ;
2013-03-13 15:32:13 +04:00
gpio_chip - > direction_input = gpio_rcar_direction_input ;
gpio_chip - > get = gpio_rcar_get ;
gpio_chip - > direction_output = gpio_rcar_direction_output ;
gpio_chip - > set = gpio_rcar_set ;
gpio_chip - > label = name ;
2015-11-04 11:56:26 +03:00
gpio_chip - > parent = dev ;
2013-03-13 15:32:13 +04:00
gpio_chip - > owner = THIS_MODULE ;
gpio_chip - > base = p - > config . gpio_base ;
gpio_chip - > ngpio = p - > config . number_of_pins ;
irq_chip = & p - > irq_chip ;
irq_chip - > name = name ;
irq_chip - > irq_mask = gpio_rcar_irq_disable ;
irq_chip - > irq_unmask = gpio_rcar_irq_enable ;
irq_chip - > irq_set_type = gpio_rcar_irq_set_type ;
2015-03-18 21:41:09 +03:00
irq_chip - > irq_set_wake = gpio_rcar_irq_set_wake ;
irq_chip - > flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND ;
2013-03-13 15:32:13 +04:00
2015-01-12 13:07:59 +03:00
ret = gpiochip_add ( gpio_chip ) ;
if ( ret ) {
dev_err ( dev , " failed to add GPIO controller \n " ) ;
2013-11-07 11:56:51 +04:00
goto err0 ;
2013-03-13 15:32:13 +04:00
}
2015-03-18 21:41:07 +03:00
ret = gpiochip_irqchip_add ( gpio_chip , irq_chip , p - > config . irq_base ,
2015-01-12 13:07:59 +03:00
handle_level_irq , IRQ_TYPE_NONE ) ;
if ( ret ) {
dev_err ( dev , " cannot add irqchip \n " ) ;
goto err1 ;
}
2015-03-18 21:41:09 +03:00
p - > irq_parent = irq - > start ;
2014-03-28 00:47:36 +04:00
if ( devm_request_irq ( dev , irq - > start , gpio_rcar_irq_handler ,
IRQF_SHARED , name , p ) ) {
dev_err ( dev , " failed to request IRQ \n " ) ;
2013-03-13 15:32:13 +04:00
ret = - ENOENT ;
goto err1 ;
}
2014-03-28 00:47:36 +04:00
dev_info ( dev , " driving %d GPIOs \n " , p - > config . number_of_pins ) ;
2013-03-13 15:32:13 +04:00
/* warn in case of mismatch if irq base is specified */
if ( p - > config . irq_base ) {
2015-03-18 21:41:07 +03:00
ret = irq_find_mapping ( gpio_chip - > irqdomain , 0 ) ;
2013-03-13 15:32:13 +04:00
if ( p - > config . irq_base ! = ret )
2014-03-28 00:47:36 +04:00
dev_warn ( dev , " irq base mismatch (%u/%u) \n " ,
2013-03-13 15:32:13 +04:00
p - > config . irq_base , ret ) ;
}
2013-05-21 15:40:06 +04:00
if ( p - > config . pctl_name ) {
ret = gpiochip_add_pin_range ( gpio_chip , p - > config . pctl_name , 0 ,
gpio_chip - > base , gpio_chip - > ngpio ) ;
if ( ret < 0 )
2014-03-28 00:47:36 +04:00
dev_warn ( dev , " failed to add pin range \n " ) ;
2013-05-21 15:40:06 +04:00
}
2013-03-10 06:27:00 +04:00
2013-03-13 15:32:13 +04:00
return 0 ;
err1 :
2015-03-18 21:41:07 +03:00
gpiochip_remove ( gpio_chip ) ;
2013-03-13 15:32:13 +04:00
err0 :
2014-04-14 22:33:13 +04:00
pm_runtime_disable ( dev ) ;
2013-03-13 15:32:13 +04:00
return ret ;
}
static int gpio_rcar_remove ( struct platform_device * pdev )
{
struct gpio_rcar_priv * p = platform_get_drvdata ( pdev ) ;
2014-07-13 00:30:12 +04:00
gpiochip_remove ( & p - > gpio_chip ) ;
2013-03-13 15:32:13 +04:00
2014-04-14 22:33:13 +04:00
pm_runtime_disable ( & pdev - > dev ) ;
2013-03-13 15:32:13 +04:00
return 0 ;
}
static struct platform_driver gpio_rcar_device_driver = {
. probe = gpio_rcar_probe ,
. remove = gpio_rcar_remove ,
. driver = {
. name = " gpio_rcar " ,
2013-05-21 15:40:06 +04:00
. of_match_table = of_match_ptr ( gpio_rcar_of_table ) ,
2013-03-13 15:32:13 +04:00
}
} ;
module_platform_driver ( gpio_rcar_device_driver ) ;
MODULE_AUTHOR ( " Magnus Damm " ) ;
MODULE_DESCRIPTION ( " Renesas R-Car GPIO Driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;