2018-11-29 01:28:46 +03:00
// SPDX-License-Identifier: GPL-2.0
2015-05-03 00:11:34 +03:00
/*
* GPIO driver for NXP LPC18xx / 43 xx .
*
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
* Copyright ( C ) 2018 Vladimir Zapolskiy < vz @ mleia . com >
2015-05-03 00:11:34 +03:00
* Copyright ( C ) 2015 Joachim Eastwood < manabian @ gmail . com >
*
*/
# include <linux/clk.h>
# include <linux/gpio/driver.h>
# include <linux/io.h>
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
# include <linux/irqdomain.h>
2015-05-03 00:11:34 +03:00
# include <linux/module.h>
# include <linux/of.h>
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
# include <linux/of_address.h>
# include <linux/of_irq.h>
2015-05-03 00:11:34 +03:00
# include <linux/pinctrl/consumer.h>
# include <linux/platform_device.h>
/* LPC18xx GPIO register offsets */
# define LPC18XX_REG_DIR(n) (0x2000 + n * sizeof(u32))
# define LPC18XX_MAX_PORTS 8
# define LPC18XX_PINS_PER_PORT 32
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
/* LPC18xx GPIO pin interrupt controller register offsets */
# define LPC18XX_GPIO_PIN_IC_ISEL 0x00
# define LPC18XX_GPIO_PIN_IC_IENR 0x04
# define LPC18XX_GPIO_PIN_IC_SIENR 0x08
# define LPC18XX_GPIO_PIN_IC_CIENR 0x0c
# define LPC18XX_GPIO_PIN_IC_IENF 0x10
# define LPC18XX_GPIO_PIN_IC_SIENF 0x14
# define LPC18XX_GPIO_PIN_IC_CIENF 0x18
# define LPC18XX_GPIO_PIN_IC_RISE 0x1c
# define LPC18XX_GPIO_PIN_IC_FALL 0x20
# define LPC18XX_GPIO_PIN_IC_IST 0x24
# define NR_LPC18XX_GPIO_PIN_IC_IRQS 8
struct lpc18xx_gpio_pin_ic {
void __iomem * base ;
struct irq_domain * domain ;
struct raw_spinlock lock ;
} ;
2015-05-03 00:11:34 +03:00
struct lpc18xx_gpio_chip {
struct gpio_chip gpio ;
void __iomem * base ;
struct clk * clk ;
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
struct lpc18xx_gpio_pin_ic * pin_ic ;
2015-05-03 00:11:34 +03:00
spinlock_t lock ;
} ;
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
static inline void lpc18xx_gpio_pin_ic_isel ( struct lpc18xx_gpio_pin_ic * ic ,
u32 pin , bool set )
{
u32 val = readl_relaxed ( ic - > base + LPC18XX_GPIO_PIN_IC_ISEL ) ;
if ( set )
val & = ~ BIT ( pin ) ;
else
val | = BIT ( pin ) ;
writel_relaxed ( val , ic - > base + LPC18XX_GPIO_PIN_IC_ISEL ) ;
}
static inline void lpc18xx_gpio_pin_ic_set ( struct lpc18xx_gpio_pin_ic * ic ,
u32 pin , u32 reg )
{
writel_relaxed ( BIT ( pin ) , ic - > base + reg ) ;
}
static void lpc18xx_gpio_pin_ic_mask ( struct irq_data * d )
{
struct lpc18xx_gpio_pin_ic * ic = d - > chip_data ;
u32 type = irqd_get_trigger_type ( d ) ;
raw_spin_lock ( & ic - > lock ) ;
if ( type & IRQ_TYPE_LEVEL_MASK | | type & IRQ_TYPE_EDGE_RISING )
lpc18xx_gpio_pin_ic_set ( ic , d - > hwirq ,
LPC18XX_GPIO_PIN_IC_CIENR ) ;
if ( type & IRQ_TYPE_EDGE_FALLING )
lpc18xx_gpio_pin_ic_set ( ic , d - > hwirq ,
LPC18XX_GPIO_PIN_IC_CIENF ) ;
raw_spin_unlock ( & ic - > lock ) ;
irq_chip_mask_parent ( d ) ;
}
static void lpc18xx_gpio_pin_ic_unmask ( struct irq_data * d )
{
struct lpc18xx_gpio_pin_ic * ic = d - > chip_data ;
u32 type = irqd_get_trigger_type ( d ) ;
raw_spin_lock ( & ic - > lock ) ;
if ( type & IRQ_TYPE_LEVEL_MASK | | type & IRQ_TYPE_EDGE_RISING )
lpc18xx_gpio_pin_ic_set ( ic , d - > hwirq ,
LPC18XX_GPIO_PIN_IC_SIENR ) ;
if ( type & IRQ_TYPE_EDGE_FALLING )
lpc18xx_gpio_pin_ic_set ( ic , d - > hwirq ,
LPC18XX_GPIO_PIN_IC_SIENF ) ;
raw_spin_unlock ( & ic - > lock ) ;
irq_chip_unmask_parent ( d ) ;
}
static void lpc18xx_gpio_pin_ic_eoi ( struct irq_data * d )
{
struct lpc18xx_gpio_pin_ic * ic = d - > chip_data ;
u32 type = irqd_get_trigger_type ( d ) ;
raw_spin_lock ( & ic - > lock ) ;
if ( type & IRQ_TYPE_EDGE_BOTH )
lpc18xx_gpio_pin_ic_set ( ic , d - > hwirq ,
LPC18XX_GPIO_PIN_IC_IST ) ;
raw_spin_unlock ( & ic - > lock ) ;
irq_chip_eoi_parent ( d ) ;
}
static int lpc18xx_gpio_pin_ic_set_type ( struct irq_data * d , unsigned int type )
{
struct lpc18xx_gpio_pin_ic * ic = d - > chip_data ;
raw_spin_lock ( & ic - > lock ) ;
if ( type & IRQ_TYPE_LEVEL_HIGH ) {
lpc18xx_gpio_pin_ic_isel ( ic , d - > hwirq , true ) ;
lpc18xx_gpio_pin_ic_set ( ic , d - > hwirq ,
LPC18XX_GPIO_PIN_IC_SIENF ) ;
} else if ( type & IRQ_TYPE_LEVEL_LOW ) {
lpc18xx_gpio_pin_ic_isel ( ic , d - > hwirq , true ) ;
lpc18xx_gpio_pin_ic_set ( ic , d - > hwirq ,
LPC18XX_GPIO_PIN_IC_CIENF ) ;
} else {
lpc18xx_gpio_pin_ic_isel ( ic , d - > hwirq , false ) ;
}
raw_spin_unlock ( & ic - > lock ) ;
return 0 ;
}
static struct irq_chip lpc18xx_gpio_pin_ic = {
. name = " LPC18xx GPIO pin " ,
. irq_mask = lpc18xx_gpio_pin_ic_mask ,
. irq_unmask = lpc18xx_gpio_pin_ic_unmask ,
. irq_eoi = lpc18xx_gpio_pin_ic_eoi ,
. irq_set_type = lpc18xx_gpio_pin_ic_set_type ,
. flags = IRQCHIP_SET_TYPE_MASKED ,
} ;
static int lpc18xx_gpio_pin_ic_domain_alloc ( struct irq_domain * domain ,
unsigned int virq ,
unsigned int nr_irqs , void * data )
{
struct irq_fwspec parent_fwspec , * fwspec = data ;
struct lpc18xx_gpio_pin_ic * ic = domain - > host_data ;
irq_hw_number_t hwirq ;
int ret ;
if ( nr_irqs ! = 1 )
return - EINVAL ;
hwirq = fwspec - > param [ 0 ] ;
if ( hwirq > = NR_LPC18XX_GPIO_PIN_IC_IRQS )
return - EINVAL ;
/*
* All LPC18xx / LPC43xx GPIO pin hardware interrupts are translated
* into edge interrupts 32. . .39 on parent Cortex - M3 / M4 NVIC
*/
parent_fwspec . fwnode = domain - > parent - > fwnode ;
parent_fwspec . param_count = 1 ;
parent_fwspec . param [ 0 ] = hwirq + 32 ;
ret = irq_domain_alloc_irqs_parent ( domain , virq , 1 , & parent_fwspec ) ;
if ( ret < 0 ) {
pr_err ( " failed to allocate parent irq %u: %d \n " ,
parent_fwspec . param [ 0 ] , ret ) ;
return ret ;
}
return irq_domain_set_hwirq_and_chip ( domain , virq , hwirq ,
& lpc18xx_gpio_pin_ic , ic ) ;
}
static const struct irq_domain_ops lpc18xx_gpio_pin_ic_domain_ops = {
. alloc = lpc18xx_gpio_pin_ic_domain_alloc ,
. xlate = irq_domain_xlate_twocell ,
. free = irq_domain_free_irqs_common ,
} ;
static int lpc18xx_gpio_pin_ic_probe ( struct lpc18xx_gpio_chip * gc )
{
struct device * dev = gc - > gpio . parent ;
struct irq_domain * parent_domain ;
struct device_node * parent_node ;
struct lpc18xx_gpio_pin_ic * ic ;
struct resource res ;
int ret , index ;
parent_node = of_irq_find_parent ( dev - > of_node ) ;
if ( ! parent_node )
return - ENXIO ;
parent_domain = irq_find_host ( parent_node ) ;
of_node_put ( parent_node ) ;
if ( ! parent_domain )
return - ENXIO ;
ic = devm_kzalloc ( dev , sizeof ( * ic ) , GFP_KERNEL ) ;
if ( ! ic )
return - ENOMEM ;
index = of_property_match_string ( dev - > of_node , " reg-names " ,
" gpio-pin-ic " ) ;
if ( index < 0 ) {
ret = - ENODEV ;
goto free_ic ;
}
ret = of_address_to_resource ( dev - > of_node , index , & res ) ;
if ( ret < 0 )
goto free_ic ;
ic - > base = devm_ioremap_resource ( dev , & res ) ;
if ( IS_ERR ( ic - > base ) ) {
ret = PTR_ERR ( ic - > base ) ;
goto free_ic ;
}
raw_spin_lock_init ( & ic - > lock ) ;
ic - > domain = irq_domain_add_hierarchy ( parent_domain , 0 ,
NR_LPC18XX_GPIO_PIN_IC_IRQS ,
dev - > of_node ,
& lpc18xx_gpio_pin_ic_domain_ops ,
ic ) ;
if ( ! ic - > domain ) {
pr_err ( " unable to add irq domain \n " ) ;
ret = - ENODEV ;
goto free_iomap ;
}
gc - > pin_ic = ic ;
return 0 ;
free_iomap :
devm_iounmap ( dev , ic - > base ) ;
free_ic :
devm_kfree ( dev , ic ) ;
return ret ;
}
2015-05-03 00:11:34 +03:00
static void lpc18xx_gpio_set ( struct gpio_chip * chip , unsigned offset , int value )
{
2015-12-07 11:13:57 +03:00
struct lpc18xx_gpio_chip * gc = gpiochip_get_data ( chip ) ;
2015-05-03 00:11:34 +03:00
writeb ( value ? 1 : 0 , gc - > base + offset ) ;
}
static int lpc18xx_gpio_get ( struct gpio_chip * chip , unsigned offset )
{
2015-12-07 11:13:57 +03:00
struct lpc18xx_gpio_chip * gc = gpiochip_get_data ( chip ) ;
2015-05-03 00:11:34 +03:00
return ! ! readb ( gc - > base + offset ) ;
}
static int lpc18xx_gpio_direction ( struct gpio_chip * chip , unsigned offset ,
bool out )
{
2015-12-07 11:13:57 +03:00
struct lpc18xx_gpio_chip * gc = gpiochip_get_data ( chip ) ;
2015-05-03 00:11:34 +03:00
unsigned long flags ;
u32 port , pin , dir ;
port = offset / LPC18XX_PINS_PER_PORT ;
pin = offset % LPC18XX_PINS_PER_PORT ;
spin_lock_irqsave ( & gc - > lock , flags ) ;
dir = readl ( gc - > base + LPC18XX_REG_DIR ( port ) ) ;
if ( out )
dir | = BIT ( pin ) ;
else
dir & = ~ BIT ( pin ) ;
writel ( dir , gc - > base + LPC18XX_REG_DIR ( port ) ) ;
spin_unlock_irqrestore ( & gc - > lock , flags ) ;
return 0 ;
}
static int lpc18xx_gpio_direction_input ( struct gpio_chip * chip ,
unsigned offset )
{
return lpc18xx_gpio_direction ( chip , offset , false ) ;
}
static int lpc18xx_gpio_direction_output ( struct gpio_chip * chip ,
unsigned offset , int value )
{
lpc18xx_gpio_set ( chip , offset , value ) ;
return lpc18xx_gpio_direction ( chip , offset , true ) ;
}
2016-09-11 15:14:37 +03:00
static const struct gpio_chip lpc18xx_chip = {
2015-05-03 00:11:34 +03:00
. label = " lpc18xx/43xx-gpio " ,
2015-10-11 18:34:16 +03:00
. request = gpiochip_generic_request ,
. free = gpiochip_generic_free ,
2015-05-03 00:11:34 +03:00
. direction_input = lpc18xx_gpio_direction_input ,
. direction_output = lpc18xx_gpio_direction_output ,
. set = lpc18xx_gpio_set ,
. get = lpc18xx_gpio_get ,
. ngpio = LPC18XX_MAX_PORTS * LPC18XX_PINS_PER_PORT ,
. owner = THIS_MODULE ,
} ;
static int lpc18xx_gpio_probe ( struct platform_device * pdev )
{
2018-11-29 01:28:47 +03:00
struct device * dev = & pdev - > dev ;
2015-05-03 00:11:34 +03:00
struct lpc18xx_gpio_chip * gc ;
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
int index , ret ;
2015-05-03 00:11:34 +03:00
2018-11-29 01:28:47 +03:00
gc = devm_kzalloc ( dev , sizeof ( * gc ) , GFP_KERNEL ) ;
2015-05-03 00:11:34 +03:00
if ( ! gc )
return - ENOMEM ;
gc - > gpio = lpc18xx_chip ;
platform_set_drvdata ( pdev , gc ) ;
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
index = of_property_match_string ( dev - > of_node , " reg-names " , " gpio " ) ;
if ( index < 0 ) {
/* To support backward compatibility take the first resource */
2019-03-11 21:54:57 +03:00
gc - > base = devm_platform_ioremap_resource ( pdev , 0 ) ;
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
} else {
struct resource res ;
ret = of_address_to_resource ( dev - > of_node , index , & res ) ;
if ( ret < 0 )
return ret ;
gc - > base = devm_ioremap_resource ( dev , & res ) ;
}
2015-05-03 00:11:34 +03:00
if ( IS_ERR ( gc - > base ) )
return PTR_ERR ( gc - > base ) ;
2018-11-29 01:28:47 +03:00
gc - > clk = devm_clk_get ( dev , NULL ) ;
2015-05-03 00:11:34 +03:00
if ( IS_ERR ( gc - > clk ) ) {
2018-11-29 01:28:47 +03:00
dev_err ( dev , " input clock not found \n " ) ;
2015-05-03 00:11:34 +03:00
return PTR_ERR ( gc - > clk ) ;
}
ret = clk_prepare_enable ( gc - > clk ) ;
if ( ret ) {
2018-11-29 01:28:47 +03:00
dev_err ( dev , " unable to enable clock \n " ) ;
2015-05-03 00:11:34 +03:00
return ret ;
}
spin_lock_init ( & gc - > lock ) ;
2018-11-29 01:28:47 +03:00
gc - > gpio . parent = dev ;
2015-05-03 00:11:34 +03:00
2018-11-29 01:28:48 +03:00
ret = devm_gpiochip_add_data ( dev , & gc - > gpio , gc ) ;
2015-05-03 00:11:34 +03:00
if ( ret ) {
2018-11-29 01:28:47 +03:00
dev_err ( dev , " failed to add gpio chip \n " ) ;
2015-05-03 00:11:34 +03:00
clk_disable_unprepare ( gc - > clk ) ;
return ret ;
}
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
/* On error GPIO pin interrupt controller just won't be registered */
lpc18xx_gpio_pin_ic_probe ( gc ) ;
2015-05-03 00:11:34 +03:00
return 0 ;
}
2023-09-28 10:06:52 +03:00
static void lpc18xx_gpio_remove ( struct platform_device * pdev )
2015-05-03 00:11:34 +03:00
{
struct lpc18xx_gpio_chip * gc = platform_get_drvdata ( pdev ) ;
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
if ( gc - > pin_ic )
irq_domain_remove ( gc - > pin_ic - > domain ) ;
2015-05-03 00:11:34 +03:00
clk_disable_unprepare ( gc - > clk ) ;
}
static const struct of_device_id lpc18xx_gpio_match [ ] = {
{ . compatible = " nxp,lpc1850-gpio " } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , lpc18xx_gpio_match ) ;
static struct platform_driver lpc18xx_gpio_driver = {
. probe = lpc18xx_gpio_probe ,
2023-09-28 10:06:52 +03:00
. remove_new = lpc18xx_gpio_remove ,
2015-05-03 00:11:34 +03:00
. driver = {
. name = " lpc18xx-gpio " ,
. of_match_table = lpc18xx_gpio_match ,
} ,
} ;
module_platform_driver ( lpc18xx_gpio_driver ) ;
MODULE_AUTHOR ( " Joachim Eastwood <manabian@gmail.com> " ) ;
gpio: lpc18xx: add GPIO pin interrupt controller support
The change adds support of LPC18xx/LPC43xx GPIO pin interrupt controller
block within SoC GPIO controller. The new interrupt controller driver
allows to configure and capture edge or level interrupts on 8 arbitrary
selectedinput GPIO pins, and lift the signals to be reported as NVIC rising
edge interrupts. Configuration of a particular GPIO pin to serve as
interrupt and its mapping to an interrupt on NVIC is done by SCU pin
controller, for more details see description of 'nxp,gpio-pin-interrupt'
device tree property of a GPIO pin [1].
From LPC18xx and LPC43xx User Manuals the GPIO controller consists of
the following blocks:
* GPIO pin interrupt block at 0x40087000, this change adds its support,
* GPIO GROUP0 interrupt block at 0x40088000,
* GPIO GROUP1 interrupt block at 0x40089000,
* GPIO port block at 0x400F4000, it is supported by the original driver.
While all 4 sub-controller blocks have their own I/O addresses, moreover
all 3 interrupt blocks are APB0 peripherals and high-speed GPIO block is
an AHB slave, according to the hardware manual the GPIO controller is
seen as a single block, and 4 sub-controllers have the shared reset signal
RGU #28 and clock to register interface CLK_CPU_GPIO on CCU1.
Likely support of two GPIO group interrupt blocks won't be added in short
term, because the mechanism to mask several interrupt sources is not well
defined.
[1] Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2018-11-29 01:48:41 +03:00
MODULE_AUTHOR ( " Vladimir Zapolskiy <vz@mleia.com> " ) ;
2015-05-03 00:11:34 +03:00
MODULE_DESCRIPTION ( " GPIO driver for LPC18xx/43xx " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;