2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2008-04-10 16:31:47 +04:00
/*
* linux / arch / arm / mach - sa1100 / gpio . c
*
* Generic SA - 1100 GPIO handling
*/
2018-06-27 10:48:03 +03:00
# include <linux/gpio/driver.h>
2008-04-10 16:31:47 +04:00
# include <linux/init.h>
# include <linux/module.h>
2013-09-25 16:33:55 +04:00
# include <linux/io.h>
2015-01-15 04:32:26 +03:00
# include <linux/syscore_ops.h>
2016-08-31 10:49:44 +03:00
# include <soc/sa1100/pwer.h>
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2012-02-24 03:06:51 +04:00
# include <mach/irqs.h>
2008-04-10 16:31:47 +04:00
2016-08-31 10:49:44 +03:00
struct sa1100_gpio_chip {
struct gpio_chip chip ;
void __iomem * membase ;
int irqbase ;
u32 irqmask ;
u32 irqrising ;
u32 irqfalling ;
u32 irqwake ;
} ;
# define sa1100_gpio_chip(x) container_of(x, struct sa1100_gpio_chip, chip)
enum {
R_GPLR = 0x00 ,
R_GPDR = 0x04 ,
R_GPSR = 0x08 ,
R_GPCR = 0x0c ,
R_GRER = 0x10 ,
R_GFER = 0x14 ,
R_GEDR = 0x18 ,
R_GAFR = 0x1c ,
} ;
2008-04-10 16:31:47 +04:00
static int sa1100_gpio_get ( struct gpio_chip * chip , unsigned offset )
{
2016-08-31 10:49:44 +03:00
return readl_relaxed ( sa1100_gpio_chip ( chip ) - > membase + R_GPLR ) &
BIT ( offset ) ;
2008-04-10 16:31:47 +04:00
}
static void sa1100_gpio_set ( struct gpio_chip * chip , unsigned offset , int value )
{
2016-08-31 10:49:44 +03:00
int reg = value ? R_GPSR : R_GPCR ;
writel_relaxed ( BIT ( offset ) , sa1100_gpio_chip ( chip ) - > membase + reg ) ;
2008-04-10 16:31:47 +04:00
}
2016-08-31 10:49:44 +03:00
static int sa1100_get_direction ( struct gpio_chip * chip , unsigned offset )
{
void __iomem * gpdr = sa1100_gpio_chip ( chip ) - > membase + R_GPDR ;
2019-11-06 11:54:12 +03:00
if ( readl_relaxed ( gpdr ) & BIT ( offset ) )
return GPIO_LINE_DIRECTION_OUT ;
return GPIO_LINE_DIRECTION_IN ;
2016-08-31 10:49:44 +03:00
}
2008-04-10 16:31:47 +04:00
static int sa1100_direction_input ( struct gpio_chip * chip , unsigned offset )
{
2016-08-31 10:49:44 +03:00
void __iomem * gpdr = sa1100_gpio_chip ( chip ) - > membase + R_GPDR ;
2008-04-10 16:31:47 +04:00
unsigned long flags ;
local_irq_save ( flags ) ;
2016-08-31 10:49:44 +03:00
writel_relaxed ( readl_relaxed ( gpdr ) & ~ BIT ( offset ) , gpdr ) ;
2008-04-10 16:31:47 +04:00
local_irq_restore ( flags ) ;
2016-08-31 10:49:44 +03:00
2008-04-10 16:31:47 +04:00
return 0 ;
}
static int sa1100_direction_output ( struct gpio_chip * chip , unsigned offset , int value )
{
2016-08-31 10:49:44 +03:00
void __iomem * gpdr = sa1100_gpio_chip ( chip ) - > membase + R_GPDR ;
2008-04-10 16:31:47 +04:00
unsigned long flags ;
local_irq_save ( flags ) ;
sa1100_gpio_set ( chip , offset , value ) ;
2016-08-31 10:49:44 +03:00
writel_relaxed ( readl_relaxed ( gpdr ) | BIT ( offset ) , gpdr ) ;
2008-04-10 16:31:47 +04:00
local_irq_restore ( flags ) ;
2016-08-31 10:49:44 +03:00
2008-04-10 16:31:47 +04:00
return 0 ;
}
2011-12-18 22:24:57 +04:00
static int sa1100_to_irq ( struct gpio_chip * chip , unsigned offset )
{
2016-08-31 10:49:44 +03:00
return sa1100_gpio_chip ( chip ) - > irqbase + offset ;
2011-12-18 22:24:57 +04:00
}
2016-08-31 10:49:44 +03:00
static struct sa1100_gpio_chip sa1100_gpio_chip = {
. chip = {
. label = " gpio " ,
2016-08-31 10:49:44 +03:00
. get_direction = sa1100_get_direction ,
2016-08-31 10:49:44 +03:00
. direction_input = sa1100_direction_input ,
. direction_output = sa1100_direction_output ,
. set = sa1100_gpio_set ,
. get = sa1100_gpio_get ,
. to_irq = sa1100_to_irq ,
. base = 0 ,
. ngpio = GPIO_MAX + 1 ,
} ,
. membase = ( void * ) & GPLR ,
. irqbase = IRQ_GPIO0 ,
2008-04-10 16:31:47 +04:00
} ;
2015-01-15 04:32:26 +03:00
/*
* SA1100 GPIO edge detection for IRQs :
* IRQs are generated on Falling - Edge , Rising - Edge , or both .
* Use this instead of directly setting GRER / GFER .
*/
2016-08-31 10:49:44 +03:00
static void sa1100_update_edge_regs ( struct sa1100_gpio_chip * sgc )
{
void * base = sgc - > membase ;
u32 grer , gfer ;
grer = sgc - > irqrising & sgc - > irqmask ;
gfer = sgc - > irqfalling & sgc - > irqmask ;
writel_relaxed ( grer , base + R_GRER ) ;
writel_relaxed ( gfer , base + R_GFER ) ;
}
2015-01-15 04:32:26 +03:00
static int sa1100_gpio_type ( struct irq_data * d , unsigned int type )
{
2016-08-31 10:49:44 +03:00
struct sa1100_gpio_chip * sgc = irq_data_get_irq_chip_data ( d ) ;
unsigned int mask = BIT ( d - > hwirq ) ;
2015-01-15 04:32:26 +03:00
if ( type = = IRQ_TYPE_PROBE ) {
2016-08-31 10:49:44 +03:00
if ( ( sgc - > irqrising | sgc - > irqfalling ) & mask )
2015-01-15 04:32:26 +03:00
return 0 ;
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING ;
}
if ( type & IRQ_TYPE_EDGE_RISING )
2016-08-31 10:49:44 +03:00
sgc - > irqrising | = mask ;
2015-01-15 04:32:26 +03:00
else
2016-08-31 10:49:44 +03:00
sgc - > irqrising & = ~ mask ;
2015-01-15 04:32:26 +03:00
if ( type & IRQ_TYPE_EDGE_FALLING )
2016-08-31 10:49:44 +03:00
sgc - > irqfalling | = mask ;
2015-01-15 04:32:26 +03:00
else
2016-08-31 10:49:44 +03:00
sgc - > irqfalling & = ~ mask ;
2015-01-15 04:32:26 +03:00
2016-08-31 10:49:44 +03:00
sa1100_update_edge_regs ( sgc ) ;
2015-01-15 04:32:26 +03:00
return 0 ;
}
/*
* GPIO IRQs must be acknowledged .
*/
static void sa1100_gpio_ack ( struct irq_data * d )
{
2016-08-31 10:49:44 +03:00
struct sa1100_gpio_chip * sgc = irq_data_get_irq_chip_data ( d ) ;
writel_relaxed ( BIT ( d - > hwirq ) , sgc - > membase + R_GEDR ) ;
2015-01-15 04:32:26 +03:00
}
static void sa1100_gpio_mask ( struct irq_data * d )
{
2016-08-31 10:49:44 +03:00
struct sa1100_gpio_chip * sgc = irq_data_get_irq_chip_data ( d ) ;
2015-01-15 04:32:26 +03:00
unsigned int mask = BIT ( d - > hwirq ) ;
2016-08-31 10:49:44 +03:00
sgc - > irqmask & = ~ mask ;
2015-01-15 04:32:26 +03:00
2016-08-31 10:49:44 +03:00
sa1100_update_edge_regs ( sgc ) ;
2015-01-15 04:32:26 +03:00
}
static void sa1100_gpio_unmask ( struct irq_data * d )
{
2016-08-31 10:49:44 +03:00
struct sa1100_gpio_chip * sgc = irq_data_get_irq_chip_data ( d ) ;
2015-01-15 04:32:26 +03:00
unsigned int mask = BIT ( d - > hwirq ) ;
2016-08-31 10:49:44 +03:00
sgc - > irqmask | = mask ;
2015-01-15 04:32:26 +03:00
2016-08-31 10:49:44 +03:00
sa1100_update_edge_regs ( sgc ) ;
2015-01-15 04:32:26 +03:00
}
static int sa1100_gpio_wake ( struct irq_data * d , unsigned int on )
{
2016-08-31 10:49:44 +03:00
struct sa1100_gpio_chip * sgc = irq_data_get_irq_chip_data ( d ) ;
2016-08-31 10:49:44 +03:00
int ret = sa11x0_gpio_set_wake ( d - > hwirq , on ) ;
if ( ! ret ) {
if ( on )
2016-08-31 10:49:44 +03:00
sgc - > irqwake | = BIT ( d - > hwirq ) ;
2016-08-31 10:49:44 +03:00
else
2016-08-31 10:49:44 +03:00
sgc - > irqwake & = ~ BIT ( d - > hwirq ) ;
2016-08-31 10:49:44 +03:00
}
return ret ;
2015-01-15 04:32:26 +03:00
}
/*
* This is for GPIO IRQs
*/
static struct irq_chip sa1100_gpio_irq_chip = {
. name = " GPIO " ,
. irq_ack = sa1100_gpio_ack ,
. irq_mask = sa1100_gpio_mask ,
. irq_unmask = sa1100_gpio_unmask ,
. irq_set_type = sa1100_gpio_type ,
. irq_set_wake = sa1100_gpio_wake ,
} ;
static int sa1100_gpio_irqdomain_map ( struct irq_domain * d ,
unsigned int irq , irq_hw_number_t hwirq )
{
2016-08-31 10:49:44 +03:00
struct sa1100_gpio_chip * sgc = d - > host_data ;
irq_set_chip_data ( irq , sgc ) ;
irq_set_chip_and_handler ( irq , & sa1100_gpio_irq_chip , handle_edge_irq ) ;
2016-08-29 13:24:10 +03:00
irq_set_probe ( irq ) ;
2015-01-15 04:32:26 +03:00
return 0 ;
}
2015-04-27 15:54:07 +03:00
static const struct irq_domain_ops sa1100_gpio_irqdomain_ops = {
2015-01-15 04:32:26 +03:00
. map = sa1100_gpio_irqdomain_map ,
. xlate = irq_domain_xlate_onetwocell ,
} ;
static struct irq_domain * sa1100_gpio_irqdomain ;
/*
* IRQ 0 - 11 ( GPIO ) handler . We enter here with the
* irq_controller_lock held , and IRQs disabled . Decode the IRQ
* and call the handler .
*/
2015-09-14 11:42:37 +03:00
static void sa1100_gpio_handler ( struct irq_desc * desc )
2015-01-15 04:32:26 +03:00
{
2016-08-31 10:49:44 +03:00
struct sa1100_gpio_chip * sgc = irq_desc_get_handler_data ( desc ) ;
2015-07-13 01:11:27 +03:00
unsigned int irq , mask ;
2016-08-31 10:49:44 +03:00
void __iomem * gedr = sgc - > membase + R_GEDR ;
2015-01-15 04:32:26 +03:00
2016-08-31 10:49:44 +03:00
mask = readl_relaxed ( gedr ) ;
2015-01-15 04:32:26 +03:00
do {
/*
* clear down all currently active IRQ sources .
* We will be processing them all .
*/
2016-08-31 10:49:44 +03:00
writel_relaxed ( mask , gedr ) ;
2015-01-15 04:32:26 +03:00
2016-08-31 10:49:44 +03:00
irq = sgc - > irqbase ;
2015-01-15 04:32:26 +03:00
do {
if ( mask & 1 )
generic_handle_irq ( irq ) ;
mask > > = 1 ;
irq + + ;
} while ( mask ) ;
2016-08-31 10:49:44 +03:00
mask = readl_relaxed ( gedr ) ;
2015-01-15 04:32:26 +03:00
} while ( mask ) ;
}
static int sa1100_gpio_suspend ( void )
{
2016-08-31 10:49:44 +03:00
struct sa1100_gpio_chip * sgc = & sa1100_gpio_chip ;
2015-01-15 04:32:26 +03:00
/*
* Set the appropriate edges for wakeup .
*/
2016-08-31 10:49:44 +03:00
writel_relaxed ( sgc - > irqwake & sgc - > irqrising , sgc - > membase + R_GRER ) ;
writel_relaxed ( sgc - > irqwake & sgc - > irqfalling , sgc - > membase + R_GFER ) ;
2015-01-15 04:32:26 +03:00
/*
* Clear any pending GPIO interrupts .
*/
2016-08-31 10:49:44 +03:00
writel_relaxed ( readl_relaxed ( sgc - > membase + R_GEDR ) ,
sgc - > membase + R_GEDR ) ;
2015-01-15 04:32:26 +03:00
return 0 ;
}
static void sa1100_gpio_resume ( void )
{
2016-08-31 10:49:44 +03:00
sa1100_update_edge_regs ( & sa1100_gpio_chip ) ;
2015-01-15 04:32:26 +03:00
}
static struct syscore_ops sa1100_gpio_syscore_ops = {
. suspend = sa1100_gpio_suspend ,
. resume = sa1100_gpio_resume ,
} ;
static int __init sa1100_gpio_init_devicefs ( void )
{
register_syscore_ops ( & sa1100_gpio_syscore_ops ) ;
return 0 ;
}
device_initcall ( sa1100_gpio_init_devicefs ) ;
2016-08-31 10:49:44 +03:00
static const int sa1100_gpio_irqs [ ] __initconst = {
/* Install handlers for GPIO 0-10 edge detect interrupts */
IRQ_GPIO0_SC ,
IRQ_GPIO1_SC ,
IRQ_GPIO2_SC ,
IRQ_GPIO3_SC ,
IRQ_GPIO4_SC ,
IRQ_GPIO5_SC ,
IRQ_GPIO6_SC ,
IRQ_GPIO7_SC ,
IRQ_GPIO8_SC ,
IRQ_GPIO9_SC ,
IRQ_GPIO10_SC ,
/* Install handler for GPIO 11-27 edge detect interrupts */
IRQ_GPIO11_27 ,
} ;
2008-04-10 16:31:47 +04:00
void __init sa1100_init_gpio ( void )
{
2016-08-31 10:49:44 +03:00
struct sa1100_gpio_chip * sgc = & sa1100_gpio_chip ;
int i ;
2015-01-15 04:32:26 +03:00
/* clear all GPIO edge detects */
2016-08-31 10:49:44 +03:00
writel_relaxed ( 0 , sgc - > membase + R_GFER ) ;
writel_relaxed ( 0 , sgc - > membase + R_GRER ) ;
writel_relaxed ( - 1 , sgc - > membase + R_GEDR ) ;
2015-01-15 04:32:26 +03:00
2016-08-31 10:49:44 +03:00
gpiochip_add_data ( & sa1100_gpio_chip . chip , NULL ) ;
2015-01-15 04:32:26 +03:00
sa1100_gpio_irqdomain = irq_domain_add_simple ( NULL ,
28 , IRQ_GPIO0 ,
2016-08-31 10:49:44 +03:00
& sa1100_gpio_irqdomain_ops , sgc ) ;
2015-01-15 04:32:26 +03:00
2016-08-31 10:49:44 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( sa1100_gpio_irqs ) ; i + + )
irq_set_chained_handler_and_data ( sa1100_gpio_irqs [ i ] ,
sa1100_gpio_handler , sgc ) ;
2008-04-10 16:31:47 +04:00
}