2018-11-08 09:35:16 +03:00
// SPDX-License-Identifier: GPL-2.0
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
*/
# include <linux/err.h>
2018-05-31 09:08:13 +03:00
# include <linux/gpio/driver.h>
2013-03-13 15:32:13 +04:00
# 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>
2017-10-04 15:16:16 +03:00
# include <linux/of_device.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_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>
2018-02-04 22:15:02 +03:00
struct gpio_rcar_bank_info {
u32 iointsel ;
u32 inoutsel ;
u32 outdt ;
u32 posneg ;
u32 edglevel ;
u32 bothedge ;
u32 intmsk ;
} ;
2020-10-28 17:15:03 +03:00
struct gpio_rcar_info {
bool has_outdtsel ;
bool has_both_edge_trigger ;
gpio: rcar: Optimize GPIO pin state read on R-Car Gen3
Currently, the R-Car GPIO driver treats R-Car Gen2 and R-Car Gen3 GPIO
controllers the same. However, there exist small differences, like the
behavior of the General Input Register (INDT):
- On R-Car Gen1, R-Car Gen2, and RZ/G1, INDT only reflects the state
of an input pin if the GPIO is configured for input,
- On R-Car Gen3 and RZ/G2, INDT always reflects the state of the input
pins.
Hence to accommodate all variants, the driver does not use the INDT
register to read the status of a GPIO line when configured for output,
at the expense of doing 2 or 3 register reads instead of 1.
Given register accesses are slow, change the .get() and .get_multiple()
callbacks to always use INDT to read pin state on SoCs where this is
supported.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-01-08 13:20:25 +03:00
bool has_always_in ;
2021-01-08 13:20:26 +03:00
bool has_inen ;
2020-10-28 17:15:03 +03:00
} ;
2013-03-13 15:32:13 +04:00
struct gpio_rcar_priv {
void __iomem * base ;
spinlock_t lock ;
2018-11-22 23:19:41 +03:00
struct device * dev ;
2013-03-13 15:32:13 +04:00
struct gpio_chip gpio_chip ;
struct irq_chip irq_chip ;
2015-12-04 18:33:52 +03:00
unsigned int irq_parent ;
2018-02-12 16:55:13 +03:00
atomic_t wakeup_path ;
2020-10-28 17:15:03 +03:00
struct gpio_rcar_info info ;
2018-02-04 22:15:02 +03:00
struct gpio_rcar_bank_info bank_info ;
2013-03-13 15:32:13 +04:00
} ;
2020-10-28 17:15:02 +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 OUTDTSEL 0x40 /* Output Data Select Register */
# define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
2021-01-08 13:20:26 +03:00
# define INEN 0x50 /* General Input Enable 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 ) ;
2015-12-07 16:12:45 +03:00
struct gpio_rcar_priv * p = gpiochip_get_data ( gc ) ;
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 ) ;
2015-12-07 16:12:45 +03:00
struct gpio_rcar_priv * p = gpiochip_get_data ( gc ) ;
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 ) ;
2020-02-09 12:56:00 +03:00
/* Configure positive or negative logic in POSNEG */
2013-03-13 15:32:13 +04:00
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 */
2020-10-28 17:15:03 +03:00
if ( p - > info . has_both_edge_trigger )
2013-05-24 13:47:24 +04:00
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 ) ;
2015-12-07 16:12:45 +03:00
struct gpio_rcar_priv * p = gpiochip_get_data ( gc ) ;
2013-03-13 15:32:13 +04:00
unsigned int hwirq = irqd_to_hwirq ( d ) ;
2018-11-22 23:19:41 +03:00
dev_dbg ( p - > dev , " sense irq = %d, type = %d \n " , hwirq , type ) ;
2013-03-13 15:32:13 +04:00
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 :
2020-10-28 17:15:03 +03:00
if ( ! p - > info . has_both_edge_trigger )
2013-05-24 13:47:24 +04:00
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 ) ;
2015-12-07 16:12:45 +03:00
struct gpio_rcar_priv * p = gpiochip_get_data ( gc ) ;
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 ) {
2018-11-22 23:19:41 +03:00
dev_dbg ( p - > dev , " irq %u doesn't support irq_set_wake \n " ,
2015-05-21 14:21:37 +03:00
p - > irq_parent ) ;
p - > irq_parent = 0 ;
}
}
2015-03-18 21:41:09 +03:00
if ( on )
2018-02-12 16:55:13 +03:00
atomic_inc ( & p - > wakeup_path ) ;
2015-03-18 21:41:09 +03:00
else
2018-02-12 16:55:13 +03:00
atomic_dec ( & p - > wakeup_path ) ;
2015-03-18 21:41:09 +03:00
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 ) ) ;
2021-05-04 19:42:18 +03:00
generic_handle_domain_irq ( p - > gpio_chip . irq . domain ,
offset ) ;
2013-03-13 15:32:13 +04:00
irqs_handled + + ;
}
return irqs_handled ? IRQ_HANDLED : IRQ_NONE ;
}
static void gpio_rcar_config_general_input_output_mode ( struct gpio_chip * chip ,
unsigned int gpio ,
bool output )
{
2015-12-07 16:12:45 +03:00
struct gpio_rcar_priv * p = gpiochip_get_data ( chip ) ;
2013-03-13 15:32:13 +04:00
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 ) ;
2020-02-09 12:56:00 +03:00
/* Configure positive logic in POSNEG */
2013-03-13 15:32:13 +04:00
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 ) ;
2019-01-18 11:53:43 +03:00
/* Select General Output Register to output data in OUTDTSEL */
2020-10-28 17:15:03 +03:00
if ( p - > info . has_outdtsel & & output )
2019-01-18 11:53:43 +03:00
gpio_rcar_modify_bit ( p , OUTDTSEL , gpio , false ) ;
2013-03-13 15:32:13 +04:00
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 register cannot 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>
[Niklas: s/gpio_to_priv(chip)/gpiochip_get_data(chip)/]
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-12-08 20:32:28 +03:00
struct gpio_rcar_priv * p = gpiochip_get_data ( chip ) ;
int error ;
2018-11-22 23:19:41 +03:00
error = pm_runtime_get_sync ( p - > dev ) ;
2020-05-22 11:08:38 +03:00
if ( error < 0 ) {
pm_runtime_put ( p - > dev ) ;
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 register cannot 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>
[Niklas: s/gpio_to_priv(chip)/gpiochip_get_data(chip)/]
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-12-08 20:32:28 +03:00
return error ;
2020-05-22 11:08:38 +03:00
}
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 register cannot 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>
[Niklas: s/gpio_to_priv(chip)/gpiochip_get_data(chip)/]
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-12-08 20:32:28 +03:00
2017-09-22 12:02:10 +03:00
error = pinctrl_gpio_request ( chip - > base + 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 register cannot 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>
[Niklas: s/gpio_to_priv(chip)/gpiochip_get_data(chip)/]
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-12-08 20:32:28 +03:00
if ( error )
2018-11-22 23:19:41 +03:00
pm_runtime_put ( p - > dev ) ;
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 register cannot 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>
[Niklas: s/gpio_to_priv(chip)/gpiochip_get_data(chip)/]
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-12-08 20:32:28 +03:00
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 register cannot 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>
[Niklas: s/gpio_to_priv(chip)/gpiochip_get_data(chip)/]
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-12-08 20:32:28 +03:00
struct gpio_rcar_priv * p = gpiochip_get_data ( chip ) ;
2017-09-22 12:02:10 +03:00
pinctrl_gpio_free ( chip - > base + offset ) ;
2013-03-10 06:27:00 +04:00
2016-04-12 11:05:22 +03:00
/*
* Set the GPIO as an input to ensure that the next GPIO request won ' t
2013-03-10 06:27:00 +04:00
* 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 register cannot 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>
[Niklas: s/gpio_to_priv(chip)/gpiochip_get_data(chip)/]
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2016-12-08 20:32:28 +03:00
2018-11-22 23:19:41 +03:00
pm_runtime_put ( p - > dev ) ;
2013-03-10 06:27:00 +04:00
}
2018-07-12 12:15:01 +03:00
static int gpio_rcar_get_direction ( struct gpio_chip * chip , unsigned int offset )
{
struct gpio_rcar_priv * p = gpiochip_get_data ( chip ) ;
2019-11-06 11:54:12 +03:00
if ( gpio_rcar_read ( p , INOUTSEL ) & BIT ( offset ) )
return GPIO_LINE_DIRECTION_OUT ;
return GPIO_LINE_DIRECTION_IN ;
2018-07-12 12:15:01 +03: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 )
{
2020-10-28 17:15:01 +03:00
struct gpio_rcar_priv * p = gpiochip_get_data ( chip ) ;
2013-06-17 03:41:52 +04:00
u32 bit = BIT ( offset ) ;
gpio: rcar: Optimize GPIO pin state read on R-Car Gen3
Currently, the R-Car GPIO driver treats R-Car Gen2 and R-Car Gen3 GPIO
controllers the same. However, there exist small differences, like the
behavior of the General Input Register (INDT):
- On R-Car Gen1, R-Car Gen2, and RZ/G1, INDT only reflects the state
of an input pin if the GPIO is configured for input,
- On R-Car Gen3 and RZ/G2, INDT always reflects the state of the input
pins.
Hence to accommodate all variants, the driver does not use the INDT
register to read the status of a GPIO line when configured for output,
at the expense of doing 2 or 3 register reads instead of 1.
Given register accesses are slow, change the .get() and .get_multiple()
callbacks to always use INDT to read pin state on SoCs where this is
supported.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-01-08 13:20:25 +03:00
/*
* Before R - Car Gen3 , INDT does not show correct pin state when
* configured as output , so use OUTDT in case of output pins
*/
if ( ! p - > info . has_always_in & & ( gpio_rcar_read ( p , INOUTSEL ) & bit ) )
2020-10-28 17:15:01 +03:00
return ! ! ( gpio_rcar_read ( p , OUTDT ) & bit ) ;
2013-06-17 03:41:52 +04:00
else
2020-10-28 17:15:01 +03:00
return ! ! ( gpio_rcar_read ( p , INDT ) & bit ) ;
2013-03-13 15:32:13 +04:00
}
2020-10-28 17:15:04 +03:00
static int gpio_rcar_get_multiple ( struct gpio_chip * chip , unsigned long * mask ,
unsigned long * bits )
{
struct gpio_rcar_priv * p = gpiochip_get_data ( chip ) ;
u32 bankmask , outputs , m , val = 0 ;
unsigned long flags ;
bankmask = mask [ 0 ] & GENMASK ( chip - > ngpio - 1 , 0 ) ;
if ( chip - > valid_mask )
bankmask & = chip - > valid_mask [ 0 ] ;
if ( ! bankmask )
return 0 ;
gpio: rcar: Optimize GPIO pin state read on R-Car Gen3
Currently, the R-Car GPIO driver treats R-Car Gen2 and R-Car Gen3 GPIO
controllers the same. However, there exist small differences, like the
behavior of the General Input Register (INDT):
- On R-Car Gen1, R-Car Gen2, and RZ/G1, INDT only reflects the state
of an input pin if the GPIO is configured for input,
- On R-Car Gen3 and RZ/G2, INDT always reflects the state of the input
pins.
Hence to accommodate all variants, the driver does not use the INDT
register to read the status of a GPIO line when configured for output,
at the expense of doing 2 or 3 register reads instead of 1.
Given register accesses are slow, change the .get() and .get_multiple()
callbacks to always use INDT to read pin state on SoCs where this is
supported.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-01-08 13:20:25 +03:00
if ( p - > info . has_always_in ) {
bits [ 0 ] = gpio_rcar_read ( p , INDT ) & bankmask ;
return 0 ;
}
2020-10-28 17:15:04 +03:00
spin_lock_irqsave ( & p - > lock , flags ) ;
outputs = gpio_rcar_read ( p , INOUTSEL ) ;
m = outputs & bankmask ;
if ( m )
val | = gpio_rcar_read ( p , OUTDT ) & m ;
m = ~ outputs & bankmask ;
if ( m )
val | = gpio_rcar_read ( p , INDT ) & m ;
spin_unlock_irqrestore ( & p - > lock , flags ) ;
bits [ 0 ] = val ;
return 0 ;
}
2013-03-13 15:32:13 +04:00
static void gpio_rcar_set ( struct gpio_chip * chip , unsigned offset , int value )
{
2015-12-07 16:12:45 +03:00
struct gpio_rcar_priv * p = gpiochip_get_data ( chip ) ;
2013-03-13 15:32:13 +04:00
unsigned long flags ;
spin_lock_irqsave ( & p - > lock , flags ) ;
gpio_rcar_modify_bit ( p , OUTDT , offset , value ) ;
spin_unlock_irqrestore ( & p - > lock , flags ) ;
}
2016-03-14 18:21:44 +03:00
static void gpio_rcar_set_multiple ( struct gpio_chip * chip , unsigned long * mask ,
unsigned long * bits )
{
struct gpio_rcar_priv * p = gpiochip_get_data ( chip ) ;
unsigned long flags ;
u32 val , bankmask ;
bankmask = mask [ 0 ] & GENMASK ( chip - > ngpio - 1 , 0 ) ;
2018-08-07 10:57:02 +03:00
if ( chip - > valid_mask )
bankmask & = chip - > valid_mask [ 0 ] ;
2016-03-14 18:21:44 +03:00
if ( ! bankmask )
return ;
spin_lock_irqsave ( & p - > lock , flags ) ;
val = gpio_rcar_read ( p , OUTDT ) ;
val & = ~ bankmask ;
val | = ( bankmask & bits [ 0 ] ) ;
gpio_rcar_write ( p , OUTDT , val ) ;
spin_unlock_irqrestore ( & p - > lock , flags ) ;
}
2013-03-13 15:32:13 +04:00
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 ;
}
2014-11-07 14:54:08 +03:00
static const struct gpio_rcar_info gpio_rcar_info_gen1 = {
2019-01-18 11:53:43 +03:00
. has_outdtsel = false ,
2014-11-07 14:54:08 +03:00
. has_both_edge_trigger = false ,
gpio: rcar: Optimize GPIO pin state read on R-Car Gen3
Currently, the R-Car GPIO driver treats R-Car Gen2 and R-Car Gen3 GPIO
controllers the same. However, there exist small differences, like the
behavior of the General Input Register (INDT):
- On R-Car Gen1, R-Car Gen2, and RZ/G1, INDT only reflects the state
of an input pin if the GPIO is configured for input,
- On R-Car Gen3 and RZ/G2, INDT always reflects the state of the input
pins.
Hence to accommodate all variants, the driver does not use the INDT
register to read the status of a GPIO line when configured for output,
at the expense of doing 2 or 3 register reads instead of 1.
Given register accesses are slow, change the .get() and .get_multiple()
callbacks to always use INDT to read pin state on SoCs where this is
supported.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-01-08 13:20:25 +03:00
. has_always_in = false ,
2021-01-08 13:20:26 +03:00
. has_inen = false ,
2014-11-07 14:54:08 +03:00
} ;
static const struct gpio_rcar_info gpio_rcar_info_gen2 = {
2019-01-18 11:53:43 +03:00
. has_outdtsel = true ,
2014-11-07 14:54:08 +03:00
. has_both_edge_trigger = true ,
gpio: rcar: Optimize GPIO pin state read on R-Car Gen3
Currently, the R-Car GPIO driver treats R-Car Gen2 and R-Car Gen3 GPIO
controllers the same. However, there exist small differences, like the
behavior of the General Input Register (INDT):
- On R-Car Gen1, R-Car Gen2, and RZ/G1, INDT only reflects the state
of an input pin if the GPIO is configured for input,
- On R-Car Gen3 and RZ/G2, INDT always reflects the state of the input
pins.
Hence to accommodate all variants, the driver does not use the INDT
register to read the status of a GPIO line when configured for output,
at the expense of doing 2 or 3 register reads instead of 1.
Given register accesses are slow, change the .get() and .get_multiple()
callbacks to always use INDT to read pin state on SoCs where this is
supported.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-01-08 13:20:25 +03:00
. has_always_in = false ,
2021-01-08 13:20:26 +03:00
. has_inen = false ,
gpio: rcar: Optimize GPIO pin state read on R-Car Gen3
Currently, the R-Car GPIO driver treats R-Car Gen2 and R-Car Gen3 GPIO
controllers the same. However, there exist small differences, like the
behavior of the General Input Register (INDT):
- On R-Car Gen1, R-Car Gen2, and RZ/G1, INDT only reflects the state
of an input pin if the GPIO is configured for input,
- On R-Car Gen3 and RZ/G2, INDT always reflects the state of the input
pins.
Hence to accommodate all variants, the driver does not use the INDT
register to read the status of a GPIO line when configured for output,
at the expense of doing 2 or 3 register reads instead of 1.
Given register accesses are slow, change the .get() and .get_multiple()
callbacks to always use INDT to read pin state on SoCs where this is
supported.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-01-08 13:20:25 +03:00
} ;
static const struct gpio_rcar_info gpio_rcar_info_gen3 = {
. has_outdtsel = true ,
. has_both_edge_trigger = true ,
. has_always_in = true ,
2021-01-08 13:20:26 +03:00
. has_inen = false ,
} ;
static const struct gpio_rcar_info gpio_rcar_info_v3u = {
. has_outdtsel = true ,
. has_both_edge_trigger = true ,
. has_always_in = true ,
. has_inen = true ,
2014-11-07 14:54:08 +03:00
} ;
2013-11-29 17:48:00 +04:00
static const struct of_device_id gpio_rcar_of_table [ ] = {
{
2021-01-08 13:20:26 +03:00
. compatible = " renesas,gpio-r8a779a0 " ,
. data = & gpio_rcar_info_v3u ,
} , {
2017-07-11 15:38:30 +03:00
. compatible = " renesas,rcar-gen1-gpio " ,
. data = & gpio_rcar_info_gen1 ,
} , {
. compatible = " renesas,rcar-gen2-gpio " ,
. data = & gpio_rcar_info_gen2 ,
} , {
. compatible = " renesas,rcar-gen3-gpio " ,
gpio: rcar: Optimize GPIO pin state read on R-Car Gen3
Currently, the R-Car GPIO driver treats R-Car Gen2 and R-Car Gen3 GPIO
controllers the same. However, there exist small differences, like the
behavior of the General Input Register (INDT):
- On R-Car Gen1, R-Car Gen2, and RZ/G1, INDT only reflects the state
of an input pin if the GPIO is configured for input,
- On R-Car Gen3 and RZ/G2, INDT always reflects the state of the input
pins.
Hence to accommodate all variants, the driver does not use the INDT
register to read the status of a GPIO line when configured for output,
at the expense of doing 2 or 3 register reads instead of 1.
Given register accesses are slow, change the .get() and .get_multiple()
callbacks to always use INDT to read pin state on SoCs where this is
supported.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-01-08 13:20:25 +03:00
. data = & gpio_rcar_info_gen3 ,
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 ) ;
2015-12-04 18:33:52 +03:00
static int gpio_rcar_parse_dt ( struct gpio_rcar_priv * p , unsigned int * npins )
2013-05-21 15:40:06 +04:00
{
2018-11-22 23:19:41 +03:00
struct device_node * np = p - > dev - > of_node ;
2015-12-04 18:33:52 +03:00
const struct gpio_rcar_info * info ;
2013-05-21 15:40:06 +04:00
struct of_phandle_args args ;
int ret ;
2018-11-22 23:19:41 +03:00
info = of_device_get_match_data ( p - > dev ) ;
2020-10-28 17:15:03 +03:00
p - > info = * info ;
2013-11-29 17:48:00 +04:00
2015-12-04 18:33:52 +03:00
ret = of_parse_phandle_with_fixed_args ( np , " gpio-ranges " , 3 , 0 , & args ) ;
* npins = ret = = 0 ? args . args [ 2 ] : RCAR_MAX_GPIO_PER_BANK ;
2013-11-29 17:48:00 +04:00
2015-12-04 18:33:52 +03:00
if ( * npins = = 0 | | * npins > RCAR_MAX_GPIO_PER_BANK ) {
2018-11-22 23:19:41 +03:00
dev_warn ( p - > dev , " Invalid number of gpio lines %u, using %u \n " ,
* npins , RCAR_MAX_GPIO_PER_BANK ) ;
2015-12-04 18:33:52 +03:00
* npins = RCAR_MAX_GPIO_PER_BANK ;
2013-05-21 15:40:06 +04:00
}
2013-11-29 17:48:00 +04:00
return 0 ;
2013-05-21 15:40:06 +04:00
}
2021-01-08 13:20:26 +03:00
static void gpio_rcar_enable_inputs ( struct gpio_rcar_priv * p )
{
u32 mask = GENMASK ( p - > gpio_chip . ngpio - 1 , 0 ) ;
/* Select "Input Enable" in INEN */
if ( p - > gpio_chip . valid_mask )
mask & = p - > gpio_chip . valid_mask [ 0 ] ;
if ( mask )
gpio_rcar_write ( p , INEN , gpio_rcar_read ( p , INEN ) | mask ) ;
}
2013-03-13 15:32:13 +04:00
static int gpio_rcar_probe ( struct platform_device * pdev )
{
struct gpio_rcar_priv * p ;
2019-03-11 21:55:06 +03:00
struct resource * irq ;
2013-03-13 15:32:13 +04:00
struct gpio_chip * gpio_chip ;
struct irq_chip * irq_chip ;
2020-07-22 14:31:41 +03:00
struct gpio_irq_chip * girq ;
2014-03-28 00:47:36 +04:00
struct device * dev = & pdev - > dev ;
const char * name = dev_name ( dev ) ;
2015-12-04 18:33:52 +03:00
unsigned int npins ;
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
2018-11-22 23:19:41 +03:00
p - > dev = dev ;
2013-03-13 15:32:13 +04:00
spin_lock_init ( & p - > lock ) ;
2015-12-04 18:33:52 +03:00
/* Get device configuration from DT node */
ret = gpio_rcar_parse_dt ( p , & npins ) ;
2013-11-29 17:48:00 +04:00
if ( ret < 0 )
return ret ;
2013-05-21 15:40:06 +04:00
platform_set_drvdata ( pdev , p ) ;
2014-04-14 22:33:13 +04:00
pm_runtime_enable ( dev ) ;
2013-03-13 15:32:13 +04:00
irq = platform_get_resource ( pdev , IORESOURCE_IRQ , 0 ) ;
2017-10-13 00:08:14 +03:00
if ( ! irq ) {
dev_err ( dev , " missing IRQ \n " ) ;
2013-03-13 15:32:13 +04:00
ret = - EINVAL ;
goto err0 ;
}
2019-03-11 21:55:06 +03:00
p - > base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2017-10-13 00:08:14 +03:00
if ( IS_ERR ( p - > base ) ) {
ret = PTR_ERR ( p - > base ) ;
2013-03-13 15:32:13 +04:00
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 ;
2018-07-12 12:15:01 +03:00
gpio_chip - > get_direction = gpio_rcar_get_direction ;
2013-03-13 15:32:13 +04:00
gpio_chip - > direction_input = gpio_rcar_direction_input ;
gpio_chip - > get = gpio_rcar_get ;
2020-10-28 17:15:04 +03:00
gpio_chip - > get_multiple = gpio_rcar_get_multiple ;
2013-03-13 15:32:13 +04:00
gpio_chip - > direction_output = gpio_rcar_direction_output ;
gpio_chip - > set = gpio_rcar_set ;
2016-03-14 18:21:44 +03:00
gpio_chip - > set_multiple = gpio_rcar_set_multiple ;
2013-03-13 15:32:13 +04:00
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 ;
2015-12-04 18:33:52 +03:00
gpio_chip - > base = - 1 ;
gpio_chip - > ngpio = npins ;
2013-03-13 15:32:13 +04:00
irq_chip = & p - > irq_chip ;
2019-10-24 15:22:24 +03:00
irq_chip - > name = " gpio-rcar " ;
2016-12-08 20:32:27 +03:00
irq_chip - > parent_device = dev ;
2013-03-13 15:32:13 +04:00
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 ;
2019-06-17 19:49:14 +03:00
irq_chip - > flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND ;
2013-03-13 15:32:13 +04:00
2020-07-22 14:31:41 +03:00
girq = & gpio_chip - > irq ;
girq - > chip = irq_chip ;
/* This will let us handle the parent IRQ in the driver */
girq - > parent_handler = NULL ;
girq - > num_parents = 0 ;
girq - > parents = NULL ;
girq - > default_type = IRQ_TYPE_NONE ;
girq - > handler = handle_level_irq ;
2015-12-07 16:12:45 +03:00
ret = gpiochip_add_data ( gpio_chip , p ) ;
2015-01-12 13:07:59 +03:00
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: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 ;
}
2021-01-08 13:20:26 +03:00
if ( p - > info . has_inen ) {
2021-07-14 15:51:13 +03:00
pm_runtime_get_sync ( dev ) ;
2021-01-08 13:20:26 +03:00
gpio_rcar_enable_inputs ( p ) ;
2021-07-14 15:51:13 +03:00
pm_runtime_put ( dev ) ;
2021-01-08 13:20:26 +03:00
}
2015-12-04 18:33:52 +03:00
dev_info ( dev , " driving %d GPIOs \n " , npins ) ;
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 ;
}
2018-02-04 22:15:02 +03:00
# ifdef CONFIG_PM_SLEEP
static int gpio_rcar_suspend ( struct device * dev )
{
struct gpio_rcar_priv * p = dev_get_drvdata ( dev ) ;
p - > bank_info . iointsel = gpio_rcar_read ( p , IOINTSEL ) ;
p - > bank_info . inoutsel = gpio_rcar_read ( p , INOUTSEL ) ;
p - > bank_info . outdt = gpio_rcar_read ( p , OUTDT ) ;
p - > bank_info . intmsk = gpio_rcar_read ( p , INTMSK ) ;
p - > bank_info . posneg = gpio_rcar_read ( p , POSNEG ) ;
p - > bank_info . edglevel = gpio_rcar_read ( p , EDGLEVEL ) ;
2020-10-28 17:15:03 +03:00
if ( p - > info . has_both_edge_trigger )
2018-02-04 22:15:02 +03:00
p - > bank_info . bothedge = gpio_rcar_read ( p , BOTHEDGE ) ;
2018-02-12 16:55:13 +03:00
if ( atomic_read ( & p - > wakeup_path ) )
device_set_wakeup_path ( dev ) ;
2018-02-04 22:15:02 +03:00
return 0 ;
}
static int gpio_rcar_resume ( struct device * dev )
{
struct gpio_rcar_priv * p = dev_get_drvdata ( dev ) ;
unsigned int offset ;
u32 mask ;
for ( offset = 0 ; offset < p - > gpio_chip . ngpio ; offset + + ) {
2018-08-07 10:57:02 +03:00
if ( ! gpiochip_line_is_valid ( & p - > gpio_chip , offset ) )
continue ;
2018-02-04 22:15:02 +03:00
mask = BIT ( offset ) ;
/* I/O pin */
if ( ! ( p - > bank_info . iointsel & mask ) ) {
if ( p - > bank_info . inoutsel & mask )
gpio_rcar_direction_output (
& p - > gpio_chip , offset ,
! ! ( p - > bank_info . outdt & mask ) ) ;
else
gpio_rcar_direction_input ( & p - > gpio_chip ,
offset ) ;
} else {
/* Interrupt pin */
gpio_rcar_config_interrupt_input_mode (
p ,
offset ,
! ( p - > bank_info . posneg & mask ) ,
! ( p - > bank_info . edglevel & mask ) ,
! ! ( p - > bank_info . bothedge & mask ) ) ;
if ( p - > bank_info . intmsk & mask )
gpio_rcar_write ( p , MSKCLR , mask ) ;
}
}
2021-01-08 13:20:26 +03:00
if ( p - > info . has_inen )
gpio_rcar_enable_inputs ( p ) ;
2018-02-04 22:15:02 +03:00
return 0 ;
}
# endif /* CONFIG_PM_SLEEP*/
static SIMPLE_DEV_PM_OPS ( gpio_rcar_pm_ops , gpio_rcar_suspend , gpio_rcar_resume ) ;
2013-03-13 15:32:13 +04:00
static struct platform_driver gpio_rcar_device_driver = {
. probe = gpio_rcar_probe ,
. remove = gpio_rcar_remove ,
. driver = {
. name = " gpio_rcar " ,
2018-02-04 22:15:02 +03:00
. pm = & gpio_rcar_pm_ops ,
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 " ) ;