irqchip: replace the gpio IRQ driver with upstream

PD#151900: irqchip: replace the gpio IRQ driver with upstream v4.15-rc2

1) separate the driver from the pinctrl driver
2) add support for GPIOAO* of M8B as interrupt source
3) irq lines of GPIOAO* maximum up to eight
4) remove the GPIO IRQ Controller in AO domain

note that the driver does not support for detecting the double-edge signal
through the pin,if you have related needs, please consider using polling.

test pass on axg_skt, p212

Change-Id: Iaa8da8a0cbfa0fe90d26fc8c2b775e045c8768f2
Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
This commit is contained in:
Xingyu Chen
2017-09-30 14:53:15 +08:00
committed by Jianxin Pan
parent 51140c2a25
commit 690d31cb33
16 changed files with 584 additions and 553 deletions

View File

@@ -0,0 +1,38 @@
Amlogic meson GPIO interrupt controller
Meson SoCs contains an interrupt controller which is able to watch the SoC
pads and generate an interrupt on edge or level. The controller is essentially
a 256 pads to 8 GIC interrupt multiplexer, with a filter block to select edge
or level and polarity. It does not expose all 256 mux inputs because the
documentation shows that the upper part is not mapped to any pad. The actual
number of interrupt exposed depends on the SoC.
Required properties:
- compatible : must have "amlogic,meson8-gpio-intc” and either
“amlogic,meson8-gpio-intc” for meson8 SoCs (S802) or
“amlogic,meson8b-gpio-intc” for meson8b SoCs (S805) or
“amlogic,meson-gxbb-gpio-intc” for GXBB SoCs (S905) or
“amlogic,meson-gxl-gpio-intc” for GXL SoCs (S905X, S912) or
“amlogic,meson-axg-gpio-intc” for AXG SoCs (A113G, A113D) or
“amlogic,meson-txlx-gpio-intc” for TXLX SoCs (T962X, T962E)
- interrupt-parent : a phandle to the GIC the interrupts are routed to.
Usually this is provided at the root level of the device tree as it is
common to most of the SoC.
- reg : Specifies base physical address and size of the registers.
- interrupt-controller : Identifies the node as an interrupt controller.
- #interrupt-cells : Specifies the number of cells needed to encode an
interrupt source. The value must be 2.
- meson,channel-interrupts: Array with the 8 upstream hwirq numbers. These
are the hwirqs used on the parent interrupt controller.
Example:
gpio_interrupt: interrupt-controller@9880 {
compatible = "amlogic,meson-gxbb-gpio-intc",
"amlogic,meson-gpio-intc";
reg = <0x0 0x9880 0x0 0x10>;
interrupt-controller;
#interrupt-cells = <2>;
meson,channel-interrupts = <64 65 66 67 68 69 70 71>;
};

View File

@@ -14222,3 +14222,8 @@ F: drivers/amlogic/media/vout/lcd/lcd_extern/mipi_ST7701.c
AMLOGIC MESONGXL ADD SOUND DMIC MMAP FUNCTION
M: peipeng.zhao <peipeng.zhao@amlogic.com>
F: sound/soc/amlogic/meson/dmic.h
AMLOGIC GPIO IRQ
M: Xingyu Chen <xingyu.chen@amlogic.com>
F: drivers/amlogic/irqchip/*
F: Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt

View File

@@ -347,6 +347,16 @@
clock-names = "clk_i2c";
};
gpio_intc: interrupt-controller@9880 {
compatible = "amlogic,meson-gpio-intc",
"amlogic,meson8b-gpio-intc";
reg = <0xc1109880 0x10>;
interrupt-controller;
#interrupt-cells = <2>;
amlogic,channel-interrupts = <64 65 66 67 68 69 70 71>;
status = "okay";
};
pinctrl_cbus: pinctrl@c1109880 {
compatible = "amlogic,meson8b-cbus-pinctrl";
#address-cells = <1>;
@@ -357,25 +367,13 @@
reg = <0xc11080b0 0x28>,
<0xc11080e8 0x18>,
<0xc1108120 0x18>,
<0xc1108030 0x38>,
<0xc1109880 0x10>;
interrupts = <0 64 1>,
<0 65 1>,
<0 66 1>,
<0 67 1>,
<0 68 1>,
<0 69 1>,
<0 70 1>,
<0 71 1>;
<0xc1108030 0x38>;
reg-names = "mux",
"pull",
"pull-enable",
"gpio",
"irq";
"gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
a_i2c_master:a_i2c {
@@ -634,16 +632,11 @@
gpio_ao: ao-bank@c1108030 {
reg = <0xc8100014 0x4>,
<0xc810002c 0x4>,
<0xc8100024 0x8>,
<0xc8100084 0x4>;
interrupts = <0 200 1>,
<0 201 1>;
reg-names = "mux", "pull", "gpio", "irq";
<0xc810002c 0x4>,
<0xc8100024 0x8>;
reg-names = "mux", "pull", "gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
remote_pins:remote_pin {
mux {

View File

@@ -279,15 +279,10 @@
gpio_ao: ao-bank@ff800014{
reg = <0x0 0xff800014 0x0 0x8>,
<0x0 0xff80002c 0x0 0x4>,
<0x0 0xff800024 0x0 0x8>,
<0x0 0xff800084 0x0 0x4>;
interrupts = <0 200 1>,
<0 201 1>;
reg-names = "mux", "pull", "gpio", "irq";
<0x0 0xff800024 0x0 0x8>;
reg-names = "mux", "pull", "gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
@@ -301,25 +296,13 @@
reg = <0x0 0xff634480 0x0 0x40>,
<0x0 0xff6344e8 0x0 0x14>,
<0x0 0xff634520 0x0 0x14>,
<0x0 0xff634430 0x0 0x3c>,
<0x0 0xffd0f080 0x0 0x10>;
interrupts = <0 64 1>,
<0 65 1>,
<0 66 1>,
<0 67 1>,
<0 68 1>,
<0 69 1>,
<0 70 1>,
<0 71 1>;
<0x0 0xff634430 0x0 0x3c>;
reg-names = "mux",
"pull",
"pull-enable",
"gpio",
"irq";
"gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
@@ -337,6 +320,17 @@
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x25000>;
gpio_intc: interrupt-controller@f080 {
compatible = "amlogic,meson-gpio-intc",
"amlogic,meson-axg-gpio-intc";
reg = <0x0 0xf080 0x0 0x10>;
interrupt-controller;
#interrupt-cells = <2>;
amlogic,channel-interrupts =
<64 65 66 67 68 69 70 71>;
status = "okay";
};
meson_clk_msr {
compatible = "amlogic, gxl_measure";
reg = <0x0 0x18004 0x0 0x4

View File

@@ -378,15 +378,10 @@
gpio_ao: bank@14 {
reg = <0x0 0xc8100014 0x0 0x8>,
<0x0 0xc810002c 0x0 0x4>,
<0x0 0xc8100024 0x0 0x8>,
<0x0 0xc8100084 0x0 0x4>;
interrupts = <0 200 IRQ_TYPE_EDGE_RISING>,
<0 201 IRQ_TYPE_EDGE_RISING>;
reg-names = "mux", "pull", "gpio", "irq";
<0x0 0xc8100024 0x0 0x8>;
reg-names = "mux", "pull", "gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
@@ -400,22 +395,11 @@
reg = <0x0 0xc88344b0 0x0 0x28>,
<0x0 0xc88344e8 0x0 0x14>,
<0x0 0xc8834520 0x0 0x14>,
<0x0 0xc8834430 0x0 0x40>,
<0x0 0xc1109880 0x0 0x10>;
interrupts = <0 64 IRQ_TYPE_EDGE_RISING>,
<0 65 IRQ_TYPE_EDGE_RISING>,
<0 66 IRQ_TYPE_EDGE_RISING>,
<0 67 IRQ_TYPE_EDGE_RISING>,
<0 68 IRQ_TYPE_EDGE_RISING>,
<0 69 IRQ_TYPE_EDGE_RISING>,
<0 70 IRQ_TYPE_EDGE_RISING>,
<0 71 IRQ_TYPE_EDGE_RISING>;
<0x0 0xc8834430 0x0 0x40>;
reg-names = "mux", "pull",
"pull-enable", "gpio", "irq";
"pull-enable", "gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
@@ -432,6 +416,17 @@
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
gpio_intc: interrupt-controller@9880 {
compatible = "amlogic,meson-gpio-intc",
"amlogic,meson-gxl-gpio-intc";
reg = <0x0 0x9880 0x0 0x10>;
interrupt-controller;
#interrupt-cells = <2>;
amlogic,channel-interrupts =
<64 65 66 67 68 69 70 71>;
status = "okay";
};
meson_clk_msr{
compatible = "amlogic, gxl_measure";
reg = <0x0 0x875c 0x0 0x4

View File

@@ -461,15 +461,10 @@
gpio_ao: bank@14 {
reg = <0x0 0xc8100014 0x0 0x8>,
<0x0 0xc810002c 0x0 0x4>,
<0x0 0xc8100024 0x0 0x8>,
<0x0 0xc8100084 0x0 0x4>;
interrupts = <0 200 IRQ_TYPE_EDGE_RISING>,
<0 201 IRQ_TYPE_EDGE_RISING>;
reg-names = "mux", "pull", "gpio", "irq";
<0x0 0xc8100024 0x0 0x8>;
reg-names = "mux", "pull", "gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
@@ -483,22 +478,11 @@
reg = <0x0 0xc88344b0 0x0 0x28>,
<0x0 0xc88344e8 0x0 0x14>,
<0x0 0xc8834520 0x0 0x14>,
<0x0 0xc8834430 0x0 0x40>,
<0x0 0xc1109880 0x0 0x10>;
interrupts = <0 64 IRQ_TYPE_EDGE_RISING>,
<0 65 IRQ_TYPE_EDGE_RISING>,
<0 66 IRQ_TYPE_EDGE_RISING>,
<0 67 IRQ_TYPE_EDGE_RISING>,
<0 68 IRQ_TYPE_EDGE_RISING>,
<0 69 IRQ_TYPE_EDGE_RISING>,
<0 70 IRQ_TYPE_EDGE_RISING>,
<0 71 IRQ_TYPE_EDGE_RISING>;
<0x0 0xc8834430 0x0 0x40>;
reg-names = "mux", "pull",
"pull-enable", "gpio", "irq";
"pull-enable", "gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
@@ -515,6 +499,17 @@
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
gpio_intc: interrupt-controller@9880 {
compatible = "amlogic,meson-gpio-intc",
"amlogic,meson-gxl-gpio-intc";
reg = <0x0 0x9880 0x0 0x10>;
interrupt-controller;
#interrupt-cells = <2>;
amlogic,channel-interrupts =
<64 65 66 67 68 69 70 71>;
status = "okay";
};
meson_clk_msr{
compatible = "amlogic, gxl_measure";
reg = <0x0 0x875c 0x0 0x4

View File

@@ -305,15 +305,10 @@
gpio_ao: ao-bank@ff800014{
reg = <0x0 0xff800014 0x0 0x8>,
<0x0 0xff80002c 0x0 0x4>,
<0x0 0xff800024 0x0 0x8>,
<0x0 0xff800084 0x0 0x4>;
interrupts = <0 200 1>,
<0 201 1>;
reg-names = "mux", "pull", "gpio", "irq";
<0x0 0xff800024 0x0 0x8>;
reg-names = "mux", "pull", "gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
@@ -327,25 +322,13 @@
reg = <0x0 0xff6344b0 0x0 0x34>,
<0x0 0xff6344e8 0x0 0x14>,
<0x0 0xff634520 0x0 0x14>,
<0x0 0xff634430 0x0 0x3c>,
<0x0 0xffd0f080 0x0 0x10>;
interrupts = <0 64 1>,
<0 65 1>,
<0 66 1>,
<0 67 1>,
<0 68 1>,
<0 69 1>,
<0 70 1>,
<0 71 1>;
<0x0 0xff634430 0x0 0x3c>;
reg-names = "mux",
"pull",
"pull-enable",
"gpio",
"irq";
"gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
};
@@ -557,6 +540,17 @@
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x25000>;
gpio_intc: interrupt-controller@f080 {
compatible = "amlogic,meson-gpio-intc",
"amlogic,meson-txlx-gpio-intc";
reg = <0x0 0xf080 0x0 0x10>;
interrupt-controller;
#interrupt-cells = <2>;
amlogic,channel-interrupts =
<64 65 66 67 68 69 70 71>;
status = "okay";
};
meson_clk_msr {
compatible = "amlogic, gxl_measure";
reg = <0x0 0x18004 0x0 0x4

View File

@@ -330,6 +330,7 @@ CONFIG_AMLOGIC_IIO=y
CONFIG_AMLOGIC_SARADC=y
CONFIG_AMLOGIC_DDR_WINDOW_TOOL=m
CONFIG_AMLOGIC_TEE=y
CONFIG_AMLOGIC_GPIO_IRQ=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y

View File

@@ -302,6 +302,7 @@ CONFIG_AMLOGIC_IRBLASTER=y
CONFIG_AMLOGIC_IIO=y
CONFIG_AMLOGIC_SARADC=y
CONFIG_AMLOGIC_DDR_WINDOW_TOOL=m
CONFIG_AMLOGIC_GPIO_IRQ=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y

View File

@@ -124,5 +124,6 @@ source "drivers/amlogic/ledring/Kconfig"
source "drivers/amlogic/memory_ext/Kconfig"
source "drivers/amlogic/irqchip/Kconfig"
endmenu
endif

View File

@@ -114,3 +114,5 @@ obj-$(CONFIG_AMLOGIC_TEE) += tee/
obj-$(CONFIG_AMLOGIC_MEMORY_EXTEND) += memory_ext/
obj-$(CONFIG_AMLOGIC_LEDRING) += ledring/
obj-$(CONFIG_AMLOGIC_GPIO_IRQ) += irqchip/

View File

@@ -0,0 +1,7 @@
config AMLOGIC_GPIO_IRQ
bool "Meson GPIO Interrupt Multiplexer"
depends on IRQ_DOMAIN
depends on IRQ_DOMAIN_HIERARCHY
default n
help
Support Meson SoC Family GPIO Interrupt Multiplexer

View File

@@ -0,0 +1 @@
obj-$(CONFIG_AMLOGIC_GPIO_IRQ) += irq-meson-gpio.o

View File

@@ -0,0 +1,429 @@
/*
* Copyright (c) 2015 Endless Mobile, Inc.
* Author: Carlo Caione <carlo@endlessm.com>
* Copyright (c) 2016 BayLibre, SAS.
* Author: Jerome Brunet <jbrunet@baylibre.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
* The full GNU General Public License is included in this distribution
* in the file called COPYING.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/io.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/irqchip.h>
#include <linux/of.h>
#include <linux/of_address.h>
#define NUM_CHANNEL 8
#define MAX_INPUT_MUX 256
#define REG_EDGE_POL 0x00
#define REG_PIN_03_SEL 0x04
#define REG_PIN_47_SEL 0x08
#define REG_FILTER_SEL 0x0c
#define REG_EDGE_POL_MASK(x) (BIT(x) | BIT(16 + (x)))
#define REG_EDGE_POL_EDGE(x) BIT(x)
#define REG_EDGE_POL_LOW(x) BIT(16 + (x))
#define REG_PIN_SEL_SHIFT(x) (((x) % 4) * 8)
#define REG_FILTER_SEL_SHIFT(x) ((x) * 4)
struct meson_gpio_irq_params {
unsigned int nr_hwirq;
};
static const struct meson_gpio_irq_params meson8_params = {
.nr_hwirq = 134,
};
static const struct meson_gpio_irq_params meson8b_params = {
.nr_hwirq = 119,
};
static const struct meson_gpio_irq_params gxbb_params = {
.nr_hwirq = 133,
};
static const struct meson_gpio_irq_params gxl_params = {
.nr_hwirq = 110,
};
static const struct meson_gpio_irq_params axg_params = {
.nr_hwirq = 100,
};
static const struct meson_gpio_irq_params txlx_params = {
.nr_hwirq = 119,
};
static const struct of_device_id meson_irq_gpio_matches[] = {
{ .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params },
{ .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params },
{ .compatible = "amlogic,meson-gxbb-gpio-intc", .data = &gxbb_params },
{ .compatible = "amlogic,meson-gxl-gpio-intc", .data = &gxl_params },
{ .compatible = "amlogic,meson-axg-gpio-intc", .data = &axg_params },
{ .compatible = "amlogic,meson-txlx-gpio-intc", .data = &txlx_params },
{ }
};
struct meson_gpio_irq_controller {
unsigned int nr_hwirq;
void __iomem *base;
u32 channel_irqs[NUM_CHANNEL];
DECLARE_BITMAP(channel_map, NUM_CHANNEL);
spinlock_t lock;
};
static void meson_gpio_irq_update_bits(struct meson_gpio_irq_controller *ctl,
unsigned int reg, u32 mask, u32 val)
{
u32 tmp;
tmp = readl_relaxed(ctl->base + reg);
tmp &= ~mask;
tmp |= val;
writel_relaxed(tmp, ctl->base + reg);
}
static unsigned int meson_gpio_irq_channel_to_reg(unsigned int channel)
{
return (channel < 4) ? REG_PIN_03_SEL : REG_PIN_47_SEL;
}
static int
meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
unsigned long hwirq,
u32 **channel_hwirq)
{
unsigned int reg, idx;
spin_lock(&ctl->lock);
/* Find a free channel */
idx = find_first_zero_bit(ctl->channel_map, NUM_CHANNEL);
if (idx >= NUM_CHANNEL) {
spin_unlock(&ctl->lock);
pr_debug("No channel available\n");
return -ENOSPC;
}
/* Mark the channel as used */
set_bit(idx, ctl->channel_map);
/*
* Setup the mux of the channel to route the signal of the pad
* to the appropriate input of the GIC
*/
reg = meson_gpio_irq_channel_to_reg(idx);
meson_gpio_irq_update_bits(ctl, reg,
0xff << REG_PIN_SEL_SHIFT(idx),
hwirq << REG_PIN_SEL_SHIFT(idx));
/*
* Get the hwirq number assigned to this channel through
* a pointer the channel_irq table. The added benifit of this
* method is that we can also retrieve the channel index with
* it, using the table base.
*/
*channel_hwirq = &(ctl->channel_irqs[idx]);
spin_unlock(&ctl->lock);
pr_debug("hwirq %lu assigned to channel %d - irq %u\n",
hwirq, idx, **channel_hwirq);
return 0;
}
static unsigned int
meson_gpio_irq_get_channel_idx(struct meson_gpio_irq_controller *ctl,
u32 *channel_hwirq)
{
return channel_hwirq - ctl->channel_irqs;
}
static void
meson_gpio_irq_release_channel(struct meson_gpio_irq_controller *ctl,
u32 *channel_hwirq)
{
unsigned int idx;
idx = meson_gpio_irq_get_channel_idx(ctl, channel_hwirq);
clear_bit(idx, ctl->channel_map);
}
static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl,
unsigned int type,
u32 *channel_hwirq)
{
u32 val = 0;
unsigned int idx;
idx = meson_gpio_irq_get_channel_idx(ctl, channel_hwirq);
/*
* The controller has a filter block to operate in either LEVEL or
* EDGE mode, then signal is sent to the GIC. To enable LEVEL_LOW and
* EDGE_FALLING support (which the GIC does not support), the filter
* block is also able to invert the input signal it gets before
* providing it to the GIC.
*/
type &= IRQ_TYPE_SENSE_MASK;
if (type == IRQ_TYPE_EDGE_BOTH)
return -EINVAL;
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
val |= REG_EDGE_POL_EDGE(idx);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
val |= REG_EDGE_POL_LOW(idx);
spin_lock(&ctl->lock);
meson_gpio_irq_update_bits(ctl, REG_EDGE_POL,
REG_EDGE_POL_MASK(idx), val);
spin_unlock(&ctl->lock);
return 0;
}
static unsigned int meson_gpio_irq_type_output(unsigned int type)
{
unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
type &= ~IRQ_TYPE_SENSE_MASK;
/*
* The polarity of the signal provided to the GIC should always
* be high.
*/
if (sense & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
type |= IRQ_TYPE_LEVEL_HIGH;
else if (sense & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
type |= IRQ_TYPE_EDGE_RISING;
return type;
}
static int meson_gpio_irq_set_type(struct irq_data *data, unsigned int type)
{
struct meson_gpio_irq_controller *ctl = data->domain->host_data;
u32 *channel_hwirq = irq_data_get_irq_chip_data(data);
int ret;
ret = meson_gpio_irq_type_setup(ctl, type, channel_hwirq);
if (ret)
return ret;
return irq_chip_set_type_parent(data,
meson_gpio_irq_type_output(type));
}
static struct irq_chip meson_gpio_irq_chip = {
.name = "meson-gpio-irqchip",
.irq_mask = irq_chip_mask_parent,
.irq_unmask = irq_chip_unmask_parent,
.irq_eoi = irq_chip_eoi_parent,
.irq_set_type = meson_gpio_irq_set_type,
.irq_retrigger = irq_chip_retrigger_hierarchy,
#ifdef CONFIG_SMP
.irq_set_affinity = irq_chip_set_affinity_parent,
#endif
.flags = IRQCHIP_SET_TYPE_MASKED,
};
static int meson_gpio_irq_domain_translate(struct irq_domain *domain,
struct irq_fwspec *fwspec,
unsigned long *hwirq,
unsigned int *type)
{
if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
*hwirq = fwspec->param[0];
*type = fwspec->param[1];
return 0;
}
return -EINVAL;
}
static int meson_gpio_irq_allocate_gic_irq(struct irq_domain *domain,
unsigned int virq,
u32 hwirq,
unsigned int type)
{
struct irq_fwspec fwspec;
fwspec.fwnode = domain->parent->fwnode;
fwspec.param_count = 3;
fwspec.param[0] = 0; /* SPI */
fwspec.param[1] = hwirq;
fwspec.param[2] = meson_gpio_irq_type_output(type);
return irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
}
static int meson_gpio_irq_domain_alloc(struct irq_domain *domain,
unsigned int virq,
unsigned int nr_irqs,
void *data)
{
struct irq_fwspec *fwspec = data;
struct meson_gpio_irq_controller *ctl = domain->host_data;
unsigned long hwirq;
u32 *channel_hwirq;
unsigned int type;
int ret;
if (WARN_ON(nr_irqs != 1))
return -EINVAL;
ret = meson_gpio_irq_domain_translate(domain, fwspec, &hwirq, &type);
if (ret)
return ret;
ret = meson_gpio_irq_request_channel(ctl, hwirq, &channel_hwirq);
if (ret)
return ret;
ret = meson_gpio_irq_allocate_gic_irq(domain, virq,
*channel_hwirq, type);
if (ret < 0) {
pr_err("failed to allocate gic irq %u\n", *channel_hwirq);
meson_gpio_irq_release_channel(ctl, channel_hwirq);
return ret;
}
irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
&meson_gpio_irq_chip, channel_hwirq);
return 0;
}
static void meson_gpio_irq_domain_free(struct irq_domain *domain,
unsigned int virq,
unsigned int nr_irqs)
{
struct meson_gpio_irq_controller *ctl = domain->host_data;
struct irq_data *irq_data;
u32 *channel_hwirq;
if (WARN_ON(nr_irqs != 1))
return;
irq_domain_free_irqs_parent(domain, virq, 1);
irq_data = irq_domain_get_irq_data(domain, virq);
channel_hwirq = irq_data_get_irq_chip_data(irq_data);
meson_gpio_irq_release_channel(ctl, channel_hwirq);
}
static const struct irq_domain_ops meson_gpio_irq_domain_ops = {
.alloc = meson_gpio_irq_domain_alloc,
.free = meson_gpio_irq_domain_free,
.translate = meson_gpio_irq_domain_translate,
};
static int __init meson_gpio_irq_parse_dt(struct device_node *node,
struct meson_gpio_irq_controller *ctl)
{
const struct of_device_id *match;
const struct meson_gpio_irq_params *params;
int ret;
match = of_match_node(meson_irq_gpio_matches, node);
if (!match)
return -ENODEV;
params = match->data;
ctl->nr_hwirq = params->nr_hwirq;
ret = of_property_read_variable_u32_array(node,
"amlogic,channel-interrupts",
ctl->channel_irqs,
NUM_CHANNEL,
NUM_CHANNEL);
if (ret < 0) {
pr_err("can't get %d channel interrupts\n", NUM_CHANNEL);
return ret;
}
return 0;
}
static int __init meson_gpio_irq_of_init(struct device_node *node,
struct device_node *parent)
{
struct irq_domain *domain, *parent_domain;
struct meson_gpio_irq_controller *ctl;
int ret;
if (!parent) {
pr_err("missing parent interrupt node\n");
return -ENODEV;
}
parent_domain = irq_find_host(parent);
if (!parent_domain) {
pr_err("unable to obtain parent domain\n");
return -ENXIO;
}
ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
if (!ctl)
return -ENOMEM;
spin_lock_init(&ctl->lock);
ctl->base = of_iomap(node, 0);
if (!ctl->base) {
ret = -ENOMEM;
goto free_ctl;
}
ret = meson_gpio_irq_parse_dt(node, ctl);
if (ret)
goto free_channel_irqs;
domain = irq_domain_create_hierarchy(parent_domain, 0, ctl->nr_hwirq,
of_node_to_fwnode(node),
&meson_gpio_irq_domain_ops,
ctl);
if (!domain) {
pr_err("failed to add domain\n");
ret = -ENODEV;
goto free_channel_irqs;
}
pr_info("%d to %d gpio interrupt mux initialized\n",
ctl->nr_hwirq, NUM_CHANNEL);
return 0;
free_channel_irqs:
iounmap(ctl->base);
free_ctl:
kfree(ctl);
return ret;
}
IRQCHIP_DECLARE(meson_gpio_intc, "amlogic,meson-gpio-intc",
meson_gpio_irq_of_init);

View File

@@ -711,383 +711,84 @@ static int meson_gpio_get(struct gpio_chip *chip, unsigned int gpio)
return !!(val & BIT(bit));
}
/*
* NOP functions
*/
static void noop(struct irq_data *irqd) { }
static void meson_gpio_irq_enable(struct irq_data *irqd)
static int meson_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct meson_domain *domain = to_meson_domain(irqd->chip_data);
struct irq_data *parent_data;
unsigned long flags;
unsigned char cnt;
spin_lock_irqsave(&domain->irq_res.irq_res_lock, flags);
for (cnt = 0; cnt < domain->irq_res.irq_num; cnt++) {
if (domain->irq_res.gpio_irq[cnt].hwirq == irqd->hwirq) {
parent_data =
irq_get_irq_data(
domain->irq_res.gpio_irq[cnt].parent_virq);
/*enable the interrupt line of gpio in GIC controller*/
parent_data->chip->irq_unmask(parent_data);
}
}
spin_unlock_irqrestore(&domain->irq_res.irq_res_lock, flags);
}
static void meson_gpio_irq_disable(struct irq_data *irqd)
{
struct meson_domain *domain = to_meson_domain(irqd->chip_data);
struct irq_data *parent_data;
unsigned long flags;
unsigned char cnt;
spin_lock_irqsave(&domain->irq_res.irq_res_lock, flags);
for (cnt = 0; cnt < domain->irq_res.irq_num; cnt++) {
if (domain->irq_res.gpio_irq[cnt].hwirq == irqd->hwirq) {
parent_data =
irq_get_irq_data(
domain->irq_res.gpio_irq[cnt].parent_virq);
/*disable the interrupt line of gpio in GIC controller*/
parent_data->chip->irq_mask(parent_data);
}
}
spin_unlock_irqrestore(&domain->irq_res.irq_res_lock, flags);
}
/**
*free gpio irq when free_irq() is called, and another pin can use it again.
*/
static void meson_gpio_irq_shutdown(struct irq_data *irqd)
{
struct meson_domain *domain = to_meson_domain(irqd->chip_data);
unsigned long flags;
unsigned char cnt;
spin_lock_irqsave(&domain->irq_res.irq_res_lock, flags);
for (cnt = 0; cnt < domain->irq_res.irq_num; cnt++) {
if (domain->irq_res.gpio_irq[cnt].hwirq == irqd->hwirq)
domain->irq_res.gpio_irq[cnt].used_flag = 0;
}
spin_unlock_irqrestore(&domain->irq_res.irq_res_lock, flags);
}
static int meson_ee_gpio_irq_type(struct irq_data *irqd, unsigned int type)
{
struct meson_domain *domain = to_meson_domain(irqd->chip_data);
struct meson_domain *domain = to_meson_domain(chip);
struct meson_bank *bank;
struct irq_data *parent_data;
unsigned long flags;
unsigned int trigger_type[2];
unsigned char type_num;
unsigned char type_cnt;
unsigned char start_bit;
unsigned int gpio_virq;
unsigned char cnt;
unsigned char pin;
unsigned char irq_pin;
int ret;
struct irq_fwspec fwspec;
int hwirq;
int gpio;
type = type & IRQ_TYPE_SENSE_MASK;
gpio = chip->base + offset;
switch (type) {
case IRQ_TYPE_LEVEL_LOW:
trigger_type[0] = 0x10000;
type_num = 1;
break;
case IRQ_TYPE_LEVEL_HIGH:
trigger_type[0] = 0x0;
type_num = 1;
break;
case IRQ_TYPE_EDGE_RISING:
trigger_type[0] = 0x1;
type_num = 1;
break;
case IRQ_TYPE_EDGE_FALLING:
trigger_type[0] = 0x10001;
type_num = 1;
break;
case IRQ_TYPE_EDGE_BOTH:
trigger_type[0] = 0x1;
trigger_type[1] = 0x10001;
type_num = 2;
break;
default:
if (meson_get_bank(domain, gpio, &bank))
return -EINVAL;
if (bank->irq < 0) {
pr_warn("pinctrl-meson: no support irq for pin[%d]\n", gpio);
return -EINVAL;
}
for (type_cnt = 0; type_cnt < type_num; type_cnt++) {
/* dynamic allocate gpio irq for request pin*/
spin_lock_irqsave(&domain->irq_res.irq_res_lock, flags);
for (cnt = 0; cnt < domain->irq_res.irq_num; cnt++) {
if (domain->irq_res.gpio_irq[cnt].used_flag)
continue;
else {
domain->irq_res.gpio_irq[cnt].used_flag = 1;
domain->irq_res.gpio_irq[cnt].hwirq =
irqd->hwirq;
break;
}
}
spin_unlock_irqrestore(&domain->irq_res.irq_res_lock, flags);
if (domain->irq_res.irq_num == cnt) {
pr_err("meson_pinctrl: no more gpio irq available in EE GPIO INTC, allocate gpio irq for pin[%ld] failed.\n",
irqd->hwirq);
return -EINVAL;
}
regmap_update_bits(domain->reg_irq,
(GPIO_IRQ_EDGE_OFFSET * 4),
0x10001 << cnt,
trigger_type[type_cnt] << cnt);
/*the gpio hwirq eqaul to gpio offset in gpio chip*/
pin = domain->data->pin_base + irqd->hwirq;
ret = meson_get_bank(domain, pin, &bank);
if (ret)
return ret;
if (bank->irq < 0)
return -EINVAL;
irq_pin = bank->irq + pin - bank->first;
/*set pin select register*/
start_bit = (cnt & 3) << 3;
regmap_update_bits(domain->reg_irq,
(cnt < 4)?(GPIO_IRQ_MUX_0_3 * 4):(GPIO_IRQ_MUX_4_7 * 4),
0xff << start_bit,
irq_pin << start_bit);
/**
*TODO: support to configure the filter registers by
* the func interface.
* all filter registers for gpio will been set 0x7.
*/
start_bit = cnt << 2;
regmap_update_bits(domain->reg_irq,
(GPIO_IRQ_FILTER_OFFSET * 4),
0x7 << start_bit, 0x7 << start_bit);
parent_data =
irq_get_irq_data(
domain->irq_res.gpio_irq[cnt].parent_virq);
/*set trigger type of gpio in GIC controller*/
if (type & IRQ_TYPE_EDGE_BOTH)
parent_data->chip->irq_set_type(parent_data,
IRQ_TYPE_EDGE_RISING);
else
parent_data->chip->irq_set_type(parent_data,
IRQ_TYPE_LEVEL_HIGH);
gpio_virq = irq_find_mapping(domain->chip.irqdomain,
domain->irq_res.gpio_irq[cnt].hwirq);
pr_info("meson_pinctrl: gpio virq[%d] connect to GIC hwirq[%ld]\n",
gpio_virq,
parent_data->hwirq);
}
return 0;
}
static int meson_ao_gpio_irq_type(struct irq_data *irqd, unsigned int type)
{
struct meson_domain *domain = to_meson_domain(irqd->chip_data);
struct meson_bank *bank;
struct irq_data *parent_data;
unsigned long flags;
unsigned int trigger_type[2];
unsigned char type_num;
unsigned char type_cnt;
unsigned char start_bit;
unsigned int gpio_virq;
unsigned char cnt;
unsigned char pin;
unsigned char irq_pin;
int ret;
type = type & IRQ_TYPE_SENSE_MASK;
switch (type) {
case IRQ_TYPE_LEVEL_LOW:
trigger_type[0] = 0x10000;
type_num = 1;
break;
case IRQ_TYPE_LEVEL_HIGH:
trigger_type[0] = 0x0;
type_num = 1;
break;
case IRQ_TYPE_EDGE_RISING:
trigger_type[0] = 0x40000;
type_num = 1;
break;
case IRQ_TYPE_EDGE_FALLING:
trigger_type[0] = 0x50000;
type_num = 1;
break;
case IRQ_TYPE_EDGE_BOTH:
trigger_type[0] = 0x40000;
trigger_type[1] = 0x50000;
type_num = 2;
break;
default:
if (!domain->of_irq) {
pr_err("pinctrl-meson: invalid device node of gpio INTC\n");
return -EINVAL;
}
hwirq = gpio - bank->first + bank->irq;
for (type_cnt = 0; type_cnt < type_num; type_cnt++) {
/* dynamic allocate gpio irq for request pin*/
spin_lock_irqsave(&domain->irq_res.irq_res_lock, flags);
for (cnt = 0; cnt < domain->irq_res.irq_num; cnt++) {
if (domain->irq_res.gpio_irq[cnt].used_flag)
continue;
else {
domain->irq_res.gpio_irq[cnt].used_flag = 1;
domain->irq_res.gpio_irq[cnt].hwirq =
irqd->hwirq;
break;
}
}
spin_unlock_irqrestore(&domain->irq_res.irq_res_lock, flags);
if (domain->irq_res.irq_num == cnt) {
pr_err("meson_pinctrl: no more gpio irq available in AO GPIO INTC, allocate gpio irq for pin[%ld] failed.\n",
irqd->hwirq);
return -EINVAL;
}
/*set trigger type*/
regmap_update_bits(domain->reg_irq, 0,
0x50000 << cnt,
trigger_type[type_cnt] << cnt);
/*the gpio hwirq eqaul to gpio offset in gpio chip*/
pin = domain->data->pin_base + irqd->hwirq;
ret = meson_get_bank(domain, pin, &bank);
if (ret)
return ret;
if (bank->irq < 0)
return -EINVAL;
irq_pin = bank->irq + pin - bank->first;
/*set pin select register*/
start_bit = cnt << 2;
regmap_update_bits(domain->reg_irq, 0,
0xf << start_bit,
irq_pin << start_bit);
/**
*TODO: support to configure the filter registers by
* the func interface.
* all filter registers for gpio will been set 0x7.
*/
start_bit = cnt << 2;
regmap_update_bits(domain->reg_irq, 0,
0x700 << start_bit, 0x700 << start_bit);
parent_data =
irq_get_irq_data(
domain->irq_res.gpio_irq[cnt].parent_virq);
/*set trigger type of gpio in GIC controller*/
if (type & IRQ_TYPE_EDGE_BOTH)
parent_data->chip->irq_set_type(parent_data,
IRQ_TYPE_EDGE_RISING);
else
parent_data->chip->irq_set_type(parent_data,
IRQ_TYPE_LEVEL_HIGH);
gpio_virq = irq_find_mapping(domain->chip.irqdomain,
domain->irq_res.gpio_irq[cnt].hwirq);
pr_info("meson_pinctrl: gpio virq[%d] connect to GIC hwirq[%ld]\n",
gpio_virq,
parent_data->hwirq);
}
return 0;
fwspec.fwnode = of_node_to_fwnode(domain->of_irq);
fwspec.param_count = 2;
fwspec.param[0] = hwirq;
fwspec.param[1] = IRQ_TYPE_NONE;
return irq_create_fwspec_mapping(&fwspec);
}
static struct irq_chip meson_ee_gpio_irq_chip = {
.name = "GPIO-EE",
.irq_enable = meson_gpio_irq_enable,
.irq_disable = meson_gpio_irq_disable,
.irq_set_type = meson_ee_gpio_irq_type,
.irq_mask = noop,
.irq_unmask = noop,
.irq_shutdown = meson_gpio_irq_shutdown,
};
static struct irq_chip meson_ao_gpio_irq_chip = {
.name = "GPIO-AO",
.irq_enable = meson_gpio_irq_enable,
.irq_disable = meson_gpio_irq_disable,
.irq_set_type = meson_ao_gpio_irq_type,
.irq_mask = noop,
.irq_unmask = noop,
.irq_shutdown = meson_gpio_irq_shutdown,
};
struct meson_pinctrl_private meson_gxl_periphs = {
.pinmux_type = PINMUX_V1,
.pinctrl_data = &meson_gxl_periphs_pinctrl_data,
.irq_chip = &meson_ee_gpio_irq_chip,
.init = meson_gxl_periphs_init,
};
struct meson_pinctrl_private meson_gxl_aobus = {
.pinmux_type = PINMUX_V1,
.pinctrl_data = &meson_gxl_aobus_pinctrl_data,
.irq_chip = &meson_ao_gpio_irq_chip,
.init = meson_gxl_aobus_init,
};
struct meson_pinctrl_private meson_m8b_cbus = {
.pinmux_type = PINMUX_V1,
.pinctrl_data = &meson8b_cbus_pinctrl_data,
.irq_chip = &meson_ee_gpio_irq_chip,
.init = NULL,
};
struct meson_pinctrl_private meson_m8b_aobus = {
.pinmux_type = PINMUX_V1,
.pinctrl_data = &meson8b_aobus_pinctrl_data,
.irq_chip = &meson_ao_gpio_irq_chip,
.init = NULL,
};
struct meson_pinctrl_private meson_axg_periphs = {
.pinmux_type = PINMUX_V2,
.pinctrl_data = &meson_axg_periphs_pinctrl_data,
.irq_chip = &meson_ee_gpio_irq_chip,
.init = NULL,
};
struct meson_pinctrl_private meson_axg_aobus = {
.pinmux_type = PINMUX_V2,
.pinctrl_data = &meson_axg_aobus_pinctrl_data,
.irq_chip = &meson_ao_gpio_irq_chip,
.init = meson_axg_aobus_init,
};
struct meson_pinctrl_private meson_txlx_periphs = {
.pinmux_type = PINMUX_V1,
.pinctrl_data = &meson_txlx_periphs_pinctrl_data,
.irq_chip = &meson_ee_gpio_irq_chip,
.init = NULL,
};
struct meson_pinctrl_private meson_txlx_aobus = {
.pinmux_type = PINMUX_V1,
.pinctrl_data = &meson_txlx_aobus_pinctrl_data,
.irq_chip = &meson_ao_gpio_irq_chip,
.init = meson_txlx_aobus_init,
};
@@ -1145,6 +846,7 @@ static int meson_gpiolib_register(struct meson_pinctrl *pc)
domain->chip.direction_output = meson_gpio_direction_output;
domain->chip.get = meson_gpio_get;
domain->chip.set = meson_gpio_set;
domain->chip.to_irq = meson_gpio_to_irq;
domain->chip.set_pull = meson_gpio_pull_set;
domain->chip.base = domain->data->pin_base;
domain->chip.ngpio = domain->data->num_pins;
@@ -1205,30 +907,6 @@ static struct regmap *meson_map_resource(struct meson_pinctrl *pc,
return devm_regmap_init_mmio(pc->dev, base, &meson_regmap_config);
}
static int meson_irq_parse_and_map(struct meson_pinctrl *pc,
struct device_node *node)
{
struct meson_domain *domain = pc->domain;
int cnt;
domain->irq_res.irq_num = of_irq_count(node);
if (!domain->irq_res.irq_num) {
dev_err(pc->dev, "meson_pinctrl: can't find valid property 'interrupts'\n");
return -EINVAL;
}
domain->irq_res.gpio_irq = devm_kzalloc(pc->dev,
sizeof(struct meson_gpio_irq_desc)*(domain->irq_res.irq_num),
GFP_KERNEL);
if (IS_ERR_OR_NULL(domain->irq_res.gpio_irq))
return -ENOMEM;
for (cnt = 0; cnt < domain->irq_res.irq_num; cnt++) {
domain->irq_res.gpio_irq[cnt].parent_virq =
irq_of_parse_and_map(node, cnt);
}
return 0;
}
static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
struct device_node *node)
{
@@ -1255,6 +933,9 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
domain = pc->domain;
domain->data = pc->data->domain_data;
domain->of_irq = of_find_compatible_node(NULL,
NULL, "amlogic,meson-gpio-intc");
for_each_child_of_node(node, np) {
if (!of_find_property(np, "gpio-controller", NULL))
continue;
@@ -1284,76 +965,11 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
return PTR_ERR(domain->reg_gpio);
}
domain->reg_irq = meson_map_resource(pc, np, "irq");
if (IS_ERR(domain->reg_irq)) {
dev_err(pc->dev, "gpio irq registers not found\n");
return PTR_ERR(domain->reg_irq);
}
meson_irq_parse_and_map(pc, np);
break;
}
return 0;
}
void meson_gpio_irq_handler(struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct gpio_chip *gpio_chip = irq_desc_get_handler_data(desc);
struct meson_domain *domain = to_meson_domain(gpio_chip);
unsigned char cnt;
unsigned int parent_virq;
parent_virq = irq_desc_get_irq(desc);
chained_irq_enter(chip, desc);
for (cnt = 0; cnt < domain->irq_res.irq_num; cnt++) {
if (parent_virq == domain->irq_res.gpio_irq[cnt].parent_virq &&
domain->irq_res.gpio_irq[cnt].used_flag)
generic_handle_irq(irq_find_mapping(gpio_chip->irqdomain,
domain->irq_res.gpio_irq[cnt].hwirq));
}
chained_irq_exit(chip, desc);
}
static int meson_irq_setup(struct meson_pinctrl *pc, struct irq_chip *irq_chip)
{
struct meson_domain *domain = pc->domain;
struct irq_data *parent_data;
unsigned char cnt;
unsigned char ret;
spin_lock_init(&domain->irq_res.irq_res_lock);
ret = gpiochip_irqchip_add(&domain->chip,
irq_chip,
0,
handle_simple_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(pc->dev, "couldn't add irqchip to gpiochip.\n");
return ret;
}
/* Then register the chain on the parent IRQ */
for (cnt = 0; cnt < domain->irq_res.irq_num; cnt++) {
gpiochip_set_chained_irqchip(&domain->chip,
irq_chip,
domain->irq_res.gpio_irq[cnt].parent_virq,
meson_gpio_irq_handler);
/*disable the interrupt line of gpio in GIC controller*/
parent_data =
irq_get_irq_data(
domain->irq_res.gpio_irq[cnt].parent_virq);
parent_data->chip->irq_mask(parent_data);
}
return 0;
}
static int meson_pinctrl_add_function(struct meson_pinctrl *pc,
const char *name)
{
@@ -1546,8 +1162,6 @@ static int meson_pinctrl_probe(struct platform_device *pdev)
if (priv->init)
priv->init(pc);
meson_irq_setup(pc, priv->irq_chip);
return 0;
}

View File

@@ -116,41 +116,6 @@ struct meson_domain_data {
unsigned int num_pins;
};
/**
*enum meson_irq_register - registers offset of gpio irq
*/
enum meson_irq_register {
GPIO_IRQ_EDGE_OFFSET,
GPIO_IRQ_MUX_0_3,
GPIO_IRQ_MUX_4_7,
GPIO_IRQ_FILTER_OFFSET,
};
/**
* struct meson_gpio_irq_desc - describe the gpio irq
*
* @used_flag: indicate the 'parent_virq' whether be used or not
* @parent_virq: gpio virtual interrupt number
* @hwirq: hw irq for gpio
*/
struct meson_gpio_irq_desc {
unsigned char used_flag;
unsigned int parent_virq;
unsigned int hwirq;
};
/*struct meson_irq_res - describe resource for gpio irq
*
* @irq_num: number of gpio irq
* @irq_res_lock:
* @gpio_irq: a pointer to 'struct meson_gpio_irq_desc'
*/
struct meson_irq_resource {
unsigned char irq_num;
spinlock_t irq_res_lock;
struct meson_gpio_irq_desc *gpio_irq;
};
/**
* struct meson_domain
*
@@ -158,9 +123,7 @@ struct meson_irq_resource {
* @reg_pullen: registers for pull-enable settings
* @reg_pull: registers for pull settings
* @reg_gpio: registers for gpio settings
* @reg_irq: registers for gpio irq settings
* @chip: gpio chip associated with the domain
* @irq_res: irq resource
* @data: platform data for the domain
* @node: device tree node for the domain
*
@@ -172,11 +135,10 @@ struct meson_domain {
struct regmap *reg_pullen;
struct regmap *reg_pull;
struct regmap *reg_gpio;
struct regmap *reg_irq;
struct gpio_chip chip;
struct meson_irq_resource irq_res;
struct meson_domain_data *data;
struct device_node *of_irq;
struct device_node *of_node;
};
@@ -202,7 +164,6 @@ struct meson_pinctrl {
struct meson_pinctrl_private {
unsigned char pinmux_type;
struct meson_pinctrl_data *pinctrl_data;
struct irq_chip *irq_chip;
int (*init)(struct meson_pinctrl *pc);
};