Skip to content

Commit b2fb4b7

Browse files
jbrun3tMarc Zyngier
authored andcommitted
irqchip/meson-gpio: Add support for meson sm1 SoCs
The meson sm1 SoCs uses the same type of GPIO interrupt controller IP block as the other meson SoCs, A total of 100 pins can be spied on: - 223:100 undefined (no interrupt) - 99:97 3 pins on bank GPIOE - 96:77 20 pins on bank GPIOX - 76:61 16 pins on bank GPIOA - 60:53 8 pins on bank GPIOC - 52:37 16 pins on bank BOOT - 36:28 9 pins on bank GPIOH - 27:12 16 pins on bank GPIOZ - 11:0 12 pins in the AO domain Mapping is the same as the g12a family but the sm1 controller allows to trig an irq on both edges of the input signal. This was not possible with the previous SoCs families Signed-off-by: Jerome Brunet <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Tested-by: Kevin Hilman <[email protected]> Reviewed-by: Kevin Hilman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent abc08aa commit b2fb4b7

File tree

1 file changed

+38
-14
lines changed

1 file changed

+38
-14
lines changed

drivers/irqchip/irq-meson-gpio.c

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,25 @@
2424
#define REG_PIN_47_SEL 0x08
2525
#define REG_FILTER_SEL 0x0c
2626

27-
#define REG_EDGE_POL_MASK(x) (BIT(x) | BIT(16 + (x)))
27+
/*
28+
* Note: The S905X3 datasheet reports that BOTH_EDGE is controlled by
29+
* bits 24 to 31. Tests on the actual HW show that these bits are
30+
* stuck at 0. Bits 8 to 15 are responsive and have the expected
31+
* effect.
32+
*/
2833
#define REG_EDGE_POL_EDGE(x) BIT(x)
2934
#define REG_EDGE_POL_LOW(x) BIT(16 + (x))
35+
#define REG_BOTH_EDGE(x) BIT(8 + (x))
36+
#define REG_EDGE_POL_MASK(x) ( \
37+
REG_EDGE_POL_EDGE(x) | \
38+
REG_EDGE_POL_LOW(x) | \
39+
REG_BOTH_EDGE(x))
3040
#define REG_PIN_SEL_SHIFT(x) (((x) % 4) * 8)
3141
#define REG_FILTER_SEL_SHIFT(x) ((x) * 4)
3242

3343
struct meson_gpio_irq_params {
3444
unsigned int nr_hwirq;
45+
bool support_edge_both;
3546
};
3647

3748
static const struct meson_gpio_irq_params meson8_params = {
@@ -54,18 +65,24 @@ static const struct meson_gpio_irq_params axg_params = {
5465
.nr_hwirq = 100,
5566
};
5667

68+
static const struct meson_gpio_irq_params sm1_params = {
69+
.nr_hwirq = 100,
70+
.support_edge_both = true,
71+
};
72+
5773
static const struct of_device_id meson_irq_gpio_matches[] = {
5874
{ .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params },
5975
{ .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params },
6076
{ .compatible = "amlogic,meson-gxbb-gpio-intc", .data = &gxbb_params },
6177
{ .compatible = "amlogic,meson-gxl-gpio-intc", .data = &gxl_params },
6278
{ .compatible = "amlogic,meson-axg-gpio-intc", .data = &axg_params },
6379
{ .compatible = "amlogic,meson-g12a-gpio-intc", .data = &axg_params },
80+
{ .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params },
6481
{ }
6582
};
6683

6784
struct meson_gpio_irq_controller {
68-
unsigned int nr_hwirq;
85+
const struct meson_gpio_irq_params *params;
6986
void __iomem *base;
7087
u32 channel_irqs[NUM_CHANNEL];
7188
DECLARE_BITMAP(channel_map, NUM_CHANNEL);
@@ -168,14 +185,22 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl,
168185
*/
169186
type &= IRQ_TYPE_SENSE_MASK;
170187

171-
if (type == IRQ_TYPE_EDGE_BOTH)
172-
return -EINVAL;
188+
/*
189+
* New controller support EDGE_BOTH trigger. This setting takes
190+
* precedence over the other edge/polarity settings
191+
*/
192+
if (type == IRQ_TYPE_EDGE_BOTH) {
193+
if (!ctl->params->support_edge_both)
194+
return -EINVAL;
173195

174-
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
175-
val |= REG_EDGE_POL_EDGE(idx);
196+
val |= REG_BOTH_EDGE(idx);
197+
} else {
198+
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
199+
val |= REG_EDGE_POL_EDGE(idx);
176200

177-
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
178-
val |= REG_EDGE_POL_LOW(idx);
201+
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
202+
val |= REG_EDGE_POL_LOW(idx);
203+
}
179204

180205
spin_lock(&ctl->lock);
181206

@@ -199,7 +224,7 @@ static unsigned int meson_gpio_irq_type_output(unsigned int type)
199224
*/
200225
if (sense & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
201226
type |= IRQ_TYPE_LEVEL_HIGH;
202-
else if (sense & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
227+
else
203228
type |= IRQ_TYPE_EDGE_RISING;
204229

205230
return type;
@@ -328,15 +353,13 @@ static int __init meson_gpio_irq_parse_dt(struct device_node *node,
328353
struct meson_gpio_irq_controller *ctl)
329354
{
330355
const struct of_device_id *match;
331-
const struct meson_gpio_irq_params *params;
332356
int ret;
333357

334358
match = of_match_node(meson_irq_gpio_matches, node);
335359
if (!match)
336360
return -ENODEV;
337361

338-
params = match->data;
339-
ctl->nr_hwirq = params->nr_hwirq;
362+
ctl->params = match->data;
340363

341364
ret = of_property_read_variable_u32_array(node,
342365
"amlogic,channel-interrupts",
@@ -385,7 +408,8 @@ static int __init meson_gpio_irq_of_init(struct device_node *node,
385408
if (ret)
386409
goto free_channel_irqs;
387410

388-
domain = irq_domain_create_hierarchy(parent_domain, 0, ctl->nr_hwirq,
411+
domain = irq_domain_create_hierarchy(parent_domain, 0,
412+
ctl->params->nr_hwirq,
389413
of_node_to_fwnode(node),
390414
&meson_gpio_irq_domain_ops,
391415
ctl);
@@ -396,7 +420,7 @@ static int __init meson_gpio_irq_of_init(struct device_node *node,
396420
}
397421

398422
pr_info("%d to %d gpio interrupt mux initialized\n",
399-
ctl->nr_hwirq, NUM_CHANNEL);
423+
ctl->params->nr_hwirq, NUM_CHANNEL);
400424

401425
return 0;
402426

0 commit comments

Comments
 (0)