Skip to content

Commit 92af5d4

Browse files
author
Marc Zyngier
committed
Merge branch irq/meson-gpio into irq/irqchip-next
* irq/meson-gpio: : . : Expand meson-gpio support to deal with the new Meson-S4 SoC : . irqchip/meson-gpio: Add support for meson s4 SoCs irqchip/meson-gpio: add select trigger type callback irqchip/meson-gpio: support more than 8 channels gpio irq dt-bindings: interrupt-controller: New binding for Meson-S4 SoCs Signed-off-by: Marc Zyngier <maz@kernel.org>
2 parents 8e6958c + d6c47d2 commit 92af5d4

2 files changed

Lines changed: 91 additions & 16 deletions

File tree

Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Required properties:
1818
"amlogic,meson-g12a-gpio-intc" for G12A SoCs (S905D2, S905X2, S905Y2)
1919
"amlogic,meson-sm1-gpio-intc" for SM1 SoCs (S905D3, S905X3, S905Y3)
2020
"amlogic,meson-a1-gpio-intc" for A1 SoCs (A113L)
21+
"amlogic,meson-s4-gpio-intc" for S4 SoCs (S802X2, S905Y4, S805X2G, S905W2)
2122
- reg : Specifies base physical address and size of the registers.
2223
- interrupt-controller : Identifies the node as an interrupt controller.
2324
- #interrupt-cells : Specifies the number of cells needed to encode an

drivers/irqchip/irq-meson-gpio.c

Lines changed: 90 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <linux/of.h>
1717
#include <linux/of_address.h>
1818

19-
#define NUM_CHANNEL 8
19+
#define MAX_NUM_CHANNEL 64
2020
#define MAX_INPUT_MUX 256
2121

2222
#define REG_EDGE_POL 0x00
@@ -26,6 +26,8 @@
2626

2727
/* use for A1 like chips */
2828
#define REG_PIN_A1_SEL 0x04
29+
/* Used for s4 chips */
30+
#define REG_EDGE_POL_S4 0x1c
2931

3032
/*
3133
* Note: The S905X3 datasheet reports that BOTH_EDGE is controlled by
@@ -51,15 +53,22 @@ static void meson_a1_gpio_irq_sel_pin(struct meson_gpio_irq_controller *ctl,
5153
unsigned int channel,
5254
unsigned long hwirq);
5355
static void meson_a1_gpio_irq_init(struct meson_gpio_irq_controller *ctl);
56+
static int meson8_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
57+
unsigned int type, u32 *channel_hwirq);
58+
static int meson_s4_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
59+
unsigned int type, u32 *channel_hwirq);
5460

5561
struct irq_ctl_ops {
5662
void (*gpio_irq_sel_pin)(struct meson_gpio_irq_controller *ctl,
5763
unsigned int channel, unsigned long hwirq);
5864
void (*gpio_irq_init)(struct meson_gpio_irq_controller *ctl);
65+
int (*gpio_irq_set_type)(struct meson_gpio_irq_controller *ctl,
66+
unsigned int type, u32 *channel_hwirq);
5967
};
6068

6169
struct meson_gpio_irq_params {
6270
unsigned int nr_hwirq;
71+
unsigned int nr_channels;
6372
bool support_edge_both;
6473
unsigned int edge_both_offset;
6574
unsigned int edge_single_offset;
@@ -68,28 +77,44 @@ struct meson_gpio_irq_params {
6877
struct irq_ctl_ops ops;
6978
};
7079

71-
#define INIT_MESON_COMMON(irqs, init, sel) \
80+
#define INIT_MESON_COMMON(irqs, init, sel, type) \
7281
.nr_hwirq = irqs, \
7382
.ops = { \
7483
.gpio_irq_init = init, \
7584
.gpio_irq_sel_pin = sel, \
85+
.gpio_irq_set_type = type, \
7686
},
7787

7888
#define INIT_MESON8_COMMON_DATA(irqs) \
7989
INIT_MESON_COMMON(irqs, meson_gpio_irq_init_dummy, \
80-
meson8_gpio_irq_sel_pin) \
90+
meson8_gpio_irq_sel_pin, \
91+
meson8_gpio_irq_set_type) \
8192
.edge_single_offset = 0, \
8293
.pol_low_offset = 16, \
8394
.pin_sel_mask = 0xff, \
95+
.nr_channels = 8, \
8496

8597
#define INIT_MESON_A1_COMMON_DATA(irqs) \
8698
INIT_MESON_COMMON(irqs, meson_a1_gpio_irq_init, \
87-
meson_a1_gpio_irq_sel_pin) \
99+
meson_a1_gpio_irq_sel_pin, \
100+
meson8_gpio_irq_set_type) \
88101
.support_edge_both = true, \
89102
.edge_both_offset = 16, \
90103
.edge_single_offset = 8, \
91104
.pol_low_offset = 0, \
92105
.pin_sel_mask = 0x7f, \
106+
.nr_channels = 8, \
107+
108+
#define INIT_MESON_S4_COMMON_DATA(irqs) \
109+
INIT_MESON_COMMON(irqs, meson_a1_gpio_irq_init, \
110+
meson_a1_gpio_irq_sel_pin, \
111+
meson_s4_gpio_irq_set_type) \
112+
.support_edge_both = true, \
113+
.edge_both_offset = 0, \
114+
.edge_single_offset = 12, \
115+
.pol_low_offset = 0, \
116+
.pin_sel_mask = 0xff, \
117+
.nr_channels = 12, \
93118

94119
static const struct meson_gpio_irq_params meson8_params = {
95120
INIT_MESON8_COMMON_DATA(134)
@@ -121,6 +146,10 @@ static const struct meson_gpio_irq_params a1_params = {
121146
INIT_MESON_A1_COMMON_DATA(62)
122147
};
123148

149+
static const struct meson_gpio_irq_params s4_params = {
150+
INIT_MESON_S4_COMMON_DATA(82)
151+
};
152+
124153
static const struct of_device_id meson_irq_gpio_matches[] = {
125154
{ .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params },
126155
{ .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params },
@@ -130,14 +159,15 @@ static const struct of_device_id meson_irq_gpio_matches[] = {
130159
{ .compatible = "amlogic,meson-g12a-gpio-intc", .data = &axg_params },
131160
{ .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params },
132161
{ .compatible = "amlogic,meson-a1-gpio-intc", .data = &a1_params },
162+
{ .compatible = "amlogic,meson-s4-gpio-intc", .data = &s4_params },
133163
{ }
134164
};
135165

136166
struct meson_gpio_irq_controller {
137167
const struct meson_gpio_irq_params *params;
138168
void __iomem *base;
139-
u32 channel_irqs[NUM_CHANNEL];
140-
DECLARE_BITMAP(channel_map, NUM_CHANNEL);
169+
u32 channel_irqs[MAX_NUM_CHANNEL];
170+
DECLARE_BITMAP(channel_map, MAX_NUM_CHANNEL);
141171
spinlock_t lock;
142172
};
143173

@@ -207,8 +237,8 @@ meson_gpio_irq_request_channel(struct meson_gpio_irq_controller *ctl,
207237
spin_lock_irqsave(&ctl->lock, flags);
208238

209239
/* Find a free channel */
210-
idx = find_first_zero_bit(ctl->channel_map, NUM_CHANNEL);
211-
if (idx >= NUM_CHANNEL) {
240+
idx = find_first_zero_bit(ctl->channel_map, ctl->params->nr_channels);
241+
if (idx >= ctl->params->nr_channels) {
212242
spin_unlock_irqrestore(&ctl->lock, flags);
213243
pr_err("No channel available\n");
214244
return -ENOSPC;
@@ -256,9 +286,8 @@ meson_gpio_irq_release_channel(struct meson_gpio_irq_controller *ctl,
256286
clear_bit(idx, ctl->channel_map);
257287
}
258288

259-
static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl,
260-
unsigned int type,
261-
u32 *channel_hwirq)
289+
static int meson8_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
290+
unsigned int type, u32 *channel_hwirq)
262291
{
263292
u32 val = 0;
264293
unsigned int idx;
@@ -299,6 +328,51 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl,
299328
return 0;
300329
}
301330

331+
/*
332+
* gpio irq relative registers for s4
333+
* -PADCTRL_GPIO_IRQ_CTRL0
334+
* bit[31]: enable/disable all the irq lines
335+
* bit[12-23]: single edge trigger
336+
* bit[0-11]: polarity trigger
337+
*
338+
* -PADCTRL_GPIO_IRQ_CTRL[X]
339+
* bit[0-16]: 7 bits to choose gpio source for irq line 2*[X] - 2
340+
* bit[16-22]:7 bits to choose gpio source for irq line 2*[X] - 1
341+
* where X = 1-6
342+
*
343+
* -PADCTRL_GPIO_IRQ_CTRL[7]
344+
* bit[0-11]: both edge trigger
345+
*/
346+
static int meson_s4_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
347+
unsigned int type, u32 *channel_hwirq)
348+
{
349+
u32 val = 0;
350+
unsigned int idx;
351+
352+
idx = meson_gpio_irq_get_channel_idx(ctl, channel_hwirq);
353+
354+
type &= IRQ_TYPE_SENSE_MASK;
355+
356+
meson_gpio_irq_update_bits(ctl, REG_EDGE_POL_S4, BIT(idx), 0);
357+
358+
if (type == IRQ_TYPE_EDGE_BOTH) {
359+
val |= BIT(ctl->params->edge_both_offset + idx);
360+
meson_gpio_irq_update_bits(ctl, REG_EDGE_POL_S4,
361+
BIT(ctl->params->edge_both_offset + idx), val);
362+
return 0;
363+
}
364+
365+
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
366+
val |= BIT(ctl->params->pol_low_offset + idx);
367+
368+
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
369+
val |= BIT(ctl->params->edge_single_offset + idx);
370+
371+
meson_gpio_irq_update_bits(ctl, REG_EDGE_POL,
372+
BIT(idx) | BIT(12 + idx), val);
373+
return 0;
374+
};
375+
302376
static unsigned int meson_gpio_irq_type_output(unsigned int type)
303377
{
304378
unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
@@ -323,7 +397,7 @@ static int meson_gpio_irq_set_type(struct irq_data *data, unsigned int type)
323397
u32 *channel_hwirq = irq_data_get_irq_chip_data(data);
324398
int ret;
325399

326-
ret = meson_gpio_irq_type_setup(ctl, type, channel_hwirq);
400+
ret = ctl->params->ops.gpio_irq_set_type(ctl, type, channel_hwirq);
327401
if (ret)
328402
return ret;
329403

@@ -450,10 +524,10 @@ static int meson_gpio_irq_parse_dt(struct device_node *node, struct meson_gpio_i
450524
ret = of_property_read_variable_u32_array(node,
451525
"amlogic,channel-interrupts",
452526
ctl->channel_irqs,
453-
NUM_CHANNEL,
454-
NUM_CHANNEL);
527+
ctl->params->nr_channels,
528+
ctl->params->nr_channels);
455529
if (ret < 0) {
456-
pr_err("can't get %d channel interrupts\n", NUM_CHANNEL);
530+
pr_err("can't get %d channel interrupts\n", ctl->params->nr_channels);
457531
return ret;
458532
}
459533

@@ -507,7 +581,7 @@ static int meson_gpio_irq_of_init(struct device_node *node, struct device_node *
507581
}
508582

509583
pr_info("%d to %d gpio interrupt mux initialized\n",
510-
ctl->params->nr_hwirq, NUM_CHANNEL);
584+
ctl->params->nr_hwirq, ctl->params->nr_channels);
511585

512586
return 0;
513587

0 commit comments

Comments
 (0)