irqchip/meson-gpio: support more than 8 channels gpio irq
authorQianggui Song <qianggui.song@amlogic.com>
Fri, 25 Feb 2022 05:52:04 +0000 (13:52 +0800)
committerMarc Zyngier <maz@kernel.org>
Fri, 4 Mar 2022 17:01:03 +0000 (17:01 +0000)
Current meson gpio irqchip driver only support 8 channels for gpio irq
line, later chips may have more then 8 channels, so need to modify code
to support more.

Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20220225055207.1048-3-qianggui.song@amlogic.com
drivers/irqchip/irq-meson-gpio.c

index d90ff0b9248072c56b5a91fa8ecf449ea588680c..63841e1578f5a52c0c02b1381c3b054b015d9cd8 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 
-#define NUM_CHANNEL 8
+#define MAX_NUM_CHANNEL 64
 #define MAX_INPUT_MUX 256
 
 #define REG_EDGE_POL   0x00
@@ -60,6 +60,7 @@ struct irq_ctl_ops {
 
 struct meson_gpio_irq_params {
        unsigned int nr_hwirq;
+       unsigned int nr_channels;
        bool support_edge_both;
        unsigned int edge_both_offset;
        unsigned int edge_single_offset;
@@ -81,6 +82,7 @@ struct meson_gpio_irq_params {
        .edge_single_offset = 0,                                \
        .pol_low_offset = 16,                                   \
        .pin_sel_mask = 0xff,                                   \
+       .nr_channels = 8,                                       \
 
 #define INIT_MESON_A1_COMMON_DATA(irqs)                                \
        INIT_MESON_COMMON(irqs, meson_a1_gpio_irq_init,         \
@@ -90,6 +92,7 @@ struct meson_gpio_irq_params {
        .edge_single_offset = 8,                                \
        .pol_low_offset = 0,                                    \
        .pin_sel_mask = 0x7f,                                   \
+       .nr_channels = 8,                                       \
 
 static const struct meson_gpio_irq_params meson8_params = {
        INIT_MESON8_COMMON_DATA(134)
@@ -136,8 +139,8 @@ static const struct of_device_id meson_irq_gpio_matches[] = {
 struct meson_gpio_irq_controller {
        const struct meson_gpio_irq_params *params;
        void __iomem *base;
-       u32 channel_irqs[NUM_CHANNEL];
-       DECLARE_BITMAP(channel_map, NUM_CHANNEL);
+       u32 channel_irqs[MAX_NUM_CHANNEL];
+       DECLARE_BITMAP(channel_map, MAX_NUM_CHANNEL);
        spinlock_t lock;
 };
 
@@ -207,8 +210,8 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
        spin_lock_irqsave(&ctl->lock, flags);
 
        /* Find a free channel */
-       idx = find_first_zero_bit(ctl->channel_map, NUM_CHANNEL);
-       if (idx >= NUM_CHANNEL) {
+       idx = find_first_zero_bit(ctl->channel_map, ctl->params->nr_channels);
+       if (idx >= ctl->params->nr_channels) {
                spin_unlock_irqrestore(&ctl->lock, flags);
                pr_err("No channel available\n");
                return -ENOSPC;
@@ -450,10 +453,10 @@ static int meson_gpio_irq_parse_dt(struct device_node *node, struct meson_gpio_i
        ret = of_property_read_variable_u32_array(node,
                                                  "amlogic,channel-interrupts",
                                                  ctl->channel_irqs,
-                                                 NUM_CHANNEL,
-                                                 NUM_CHANNEL);
+                                                 ctl->params->nr_channels,
+                                                 ctl->params->nr_channels);
        if (ret < 0) {
-               pr_err("can't get %d channel interrupts\n", NUM_CHANNEL);
+               pr_err("can't get %d channel interrupts\n", ctl->params->nr_channels);
                return ret;
        }
 
@@ -507,7 +510,7 @@ static int meson_gpio_irq_of_init(struct device_node *node, struct device_node *
        }
 
        pr_info("%d to %d gpio interrupt mux initialized\n",
-               ctl->params->nr_hwirq, NUM_CHANNEL);
+               ctl->params->nr_hwirq, ctl->params->nr_channels);
 
        return 0;