Skip to content

Commit a32c7ca

Browse files
Srinivas Neelibrgl
Srinivas Neeli
authored andcommitted
gpio: gpio-xilinx: Add interrupt support
Adds interrupt support to the Xilinx GPIO driver so that rising and falling edge line events can be supported. Since interrupt support is an optional feature in the Xilinx IP, the driver continues to support devices which have no interrupt provided. Depends on OF_GPIO framework for of_xlate function to translate gpiospec to the GPIO number and flags. Signed-off-by: Robert Hancock <[email protected]> Signed-off-by: Shubhrajyoti Datta <[email protected]> Signed-off-by: Srinivas Neeli <[email protected]> Reviewed-by: Linus Walleij <[email protected]> Signed-off-by: Bartosz Golaszewski <[email protected]>
1 parent 37ef334 commit a32c7ca

File tree

2 files changed

+244
-4
lines changed

2 files changed

+244
-4
lines changed

drivers/gpio/Kconfig

+2
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ config GPIO_XGENE_SB
704704

705705
config GPIO_XILINX
706706
tristate "Xilinx GPIO support"
707+
select GPIOLIB_IRQCHIP
708+
depends on OF_GPIO
707709
help
708710
Say yes here to support the Xilinx FPGA GPIO device
709711

drivers/gpio/gpio-xilinx.c

+242-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
#include <linux/errno.h>
1111
#include <linux/gpio/driver.h>
1212
#include <linux/init.h>
13+
#include <linux/interrupt.h>
1314
#include <linux/io.h>
15+
#include <linux/irq.h>
1416
#include <linux/module.h>
1517
#include <linux/of_device.h>
1618
#include <linux/of_platform.h>
@@ -22,6 +24,11 @@
2224

2325
#define XGPIO_CHANNEL_OFFSET 0x8
2426

27+
#define XGPIO_GIER_OFFSET 0x11c /* Global Interrupt Enable */
28+
#define XGPIO_GIER_IE BIT(31)
29+
#define XGPIO_IPISR_OFFSET 0x120 /* IP Interrupt Status */
30+
#define XGPIO_IPIER_OFFSET 0x128 /* IP Interrupt Enable */
31+
2532
/* Read/Write access to the GPIO registers */
2633
#if defined(CONFIG_ARCH_ZYNQ) || defined(CONFIG_X86)
2734
# define xgpio_readreg(offset) readl(offset)
@@ -36,18 +43,30 @@
3643
* @gc: GPIO chip
3744
* @regs: register block
3845
* @gpio_width: GPIO width for every channel
39-
* @gpio_state: GPIO state shadow register
46+
* @gpio_state: GPIO write state shadow register
47+
* @gpio_last_irq_read: GPIO read state register from last interrupt
4048
* @gpio_dir: GPIO direction shadow register
4149
* @gpio_lock: Lock used for synchronization
50+
* @irq: IRQ used by GPIO device
51+
* @irqchip: IRQ chip
52+
* @irq_enable: GPIO IRQ enable/disable bitfield
53+
* @irq_rising_edge: GPIO IRQ rising edge enable/disable bitfield
54+
* @irq_falling_edge: GPIO IRQ falling edge enable/disable bitfield
4255
* @clk: clock resource for this driver
4356
*/
4457
struct xgpio_instance {
4558
struct gpio_chip gc;
4659
void __iomem *regs;
4760
unsigned int gpio_width[2];
4861
u32 gpio_state[2];
62+
u32 gpio_last_irq_read[2];
4963
u32 gpio_dir[2];
5064
spinlock_t gpio_lock; /* For serializing operations */
65+
int irq;
66+
struct irq_chip irqchip;
67+
u32 irq_enable[2];
68+
u32 irq_rising_edge[2];
69+
u32 irq_falling_edge[2];
5170
struct clk *clk;
5271
};
5372

@@ -276,6 +295,175 @@ static int xgpio_remove(struct platform_device *pdev)
276295
return 0;
277296
}
278297

298+
/**
299+
* xgpio_irq_ack - Acknowledge a child GPIO interrupt.
300+
* @irq_data: per IRQ and chip data passed down to chip functions
301+
* This currently does nothing, but irq_ack is unconditionally called by
302+
* handle_edge_irq and therefore must be defined.
303+
*/
304+
static void xgpio_irq_ack(struct irq_data *irq_data)
305+
{
306+
}
307+
308+
/**
309+
* xgpio_irq_mask - Write the specified signal of the GPIO device.
310+
* @irq_data: per IRQ and chip data passed down to chip functions
311+
*/
312+
static void xgpio_irq_mask(struct irq_data *irq_data)
313+
{
314+
unsigned long flags;
315+
struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
316+
int irq_offset = irqd_to_hwirq(irq_data);
317+
int index = xgpio_index(chip, irq_offset);
318+
int offset = xgpio_offset(chip, irq_offset);
319+
320+
spin_lock_irqsave(&chip->gpio_lock, flags);
321+
322+
chip->irq_enable[index] &= ~BIT(offset);
323+
324+
if (!chip->irq_enable[index]) {
325+
/* Disable per channel interrupt */
326+
u32 temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET);
327+
328+
temp &= ~BIT(index);
329+
xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, temp);
330+
}
331+
spin_unlock_irqrestore(&chip->gpio_lock, flags);
332+
}
333+
334+
/**
335+
* xgpio_irq_unmask - Write the specified signal of the GPIO device.
336+
* @irq_data: per IRQ and chip data passed down to chip functions
337+
*/
338+
static void xgpio_irq_unmask(struct irq_data *irq_data)
339+
{
340+
unsigned long flags;
341+
struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
342+
int irq_offset = irqd_to_hwirq(irq_data);
343+
int index = xgpio_index(chip, irq_offset);
344+
int offset = xgpio_offset(chip, irq_offset);
345+
u32 old_enable = chip->irq_enable[index];
346+
347+
spin_lock_irqsave(&chip->gpio_lock, flags);
348+
349+
chip->irq_enable[index] |= BIT(offset);
350+
351+
if (!old_enable) {
352+
/* Clear any existing per-channel interrupts */
353+
u32 val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET) &
354+
BIT(index);
355+
356+
if (val)
357+
xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val);
358+
359+
/* Update GPIO IRQ read data before enabling interrupt*/
360+
val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET +
361+
index * XGPIO_CHANNEL_OFFSET);
362+
chip->gpio_last_irq_read[index] = val;
363+
364+
/* Enable per channel interrupt */
365+
val = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET);
366+
val |= BIT(index);
367+
xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, val);
368+
}
369+
370+
spin_unlock_irqrestore(&chip->gpio_lock, flags);
371+
}
372+
373+
/**
374+
* xgpio_set_irq_type - Write the specified signal of the GPIO device.
375+
* @irq_data: Per IRQ and chip data passed down to chip functions
376+
* @type: Interrupt type that is to be set for the gpio pin
377+
*
378+
* Return:
379+
* 0 if interrupt type is supported otherwise -EINVAL
380+
*/
381+
static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
382+
{
383+
struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
384+
int irq_offset = irqd_to_hwirq(irq_data);
385+
int index = xgpio_index(chip, irq_offset);
386+
int offset = xgpio_offset(chip, irq_offset);
387+
388+
/*
389+
* The Xilinx GPIO hardware provides a single interrupt status
390+
* indication for any state change in a given GPIO channel (bank).
391+
* Therefore, only rising edge or falling edge triggers are
392+
* supported.
393+
*/
394+
switch (type & IRQ_TYPE_SENSE_MASK) {
395+
case IRQ_TYPE_EDGE_BOTH:
396+
chip->irq_rising_edge[index] |= BIT(offset);
397+
chip->irq_falling_edge[index] |= BIT(offset);
398+
break;
399+
case IRQ_TYPE_EDGE_RISING:
400+
chip->irq_rising_edge[index] |= BIT(offset);
401+
chip->irq_falling_edge[index] &= ~BIT(offset);
402+
break;
403+
case IRQ_TYPE_EDGE_FALLING:
404+
chip->irq_rising_edge[index] &= ~BIT(offset);
405+
chip->irq_falling_edge[index] |= BIT(offset);
406+
break;
407+
default:
408+
return -EINVAL;
409+
}
410+
411+
irq_set_handler_locked(irq_data, handle_edge_irq);
412+
return 0;
413+
}
414+
415+
/**
416+
* xgpio_irqhandler - Gpio interrupt service routine
417+
* @desc: Pointer to interrupt description
418+
*/
419+
static void xgpio_irqhandler(struct irq_desc *desc)
420+
{
421+
struct xgpio_instance *chip = irq_desc_get_handler_data(desc);
422+
struct irq_chip *irqchip = irq_desc_get_chip(desc);
423+
u32 num_channels = chip->gpio_width[1] ? 2 : 1;
424+
u32 offset = 0, index;
425+
u32 status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET);
426+
427+
xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, status);
428+
429+
chained_irq_enter(irqchip, desc);
430+
for (index = 0; index < num_channels; index++) {
431+
if ((status & BIT(index))) {
432+
unsigned long rising_events, falling_events, all_events;
433+
unsigned long flags;
434+
u32 data, bit;
435+
unsigned int irq;
436+
437+
spin_lock_irqsave(&chip->gpio_lock, flags);
438+
data = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET +
439+
index * XGPIO_CHANNEL_OFFSET);
440+
rising_events = data &
441+
~chip->gpio_last_irq_read[index] &
442+
chip->irq_enable[index] &
443+
chip->irq_rising_edge[index];
444+
falling_events = ~data &
445+
chip->gpio_last_irq_read[index] &
446+
chip->irq_enable[index] &
447+
chip->irq_falling_edge[index];
448+
dev_dbg(chip->gc.parent,
449+
"IRQ chan %u rising 0x%lx falling 0x%lx\n",
450+
index, rising_events, falling_events);
451+
all_events = rising_events | falling_events;
452+
chip->gpio_last_irq_read[index] = data;
453+
spin_unlock_irqrestore(&chip->gpio_lock, flags);
454+
455+
for_each_set_bit(bit, &all_events, 32) {
456+
irq = irq_find_mapping(chip->gc.irq.domain,
457+
offset + bit);
458+
generic_handle_irq(irq);
459+
}
460+
}
461+
offset += chip->gpio_width[index];
462+
}
463+
464+
chained_irq_exit(irqchip, desc);
465+
}
466+
279467
/**
280468
* xgpio_of_probe - Probe method for the GPIO device.
281469
* @pdev: pointer to the platform device
@@ -289,7 +477,10 @@ static int xgpio_probe(struct platform_device *pdev)
289477
struct xgpio_instance *chip;
290478
int status = 0;
291479
struct device_node *np = pdev->dev.of_node;
292-
u32 is_dual;
480+
u32 is_dual = 0;
481+
u32 cells = 2;
482+
struct gpio_irq_chip *girq;
483+
u32 temp;
293484

294485
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
295486
if (!chip)
@@ -305,6 +496,15 @@ static int xgpio_probe(struct platform_device *pdev)
305496
if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir[0]))
306497
chip->gpio_dir[0] = 0xFFFFFFFF;
307498

499+
/* Update cells with gpio-cells value */
500+
if (of_property_read_u32(np, "#gpio-cells", &cells))
501+
dev_dbg(&pdev->dev, "Missing gpio-cells property\n");
502+
503+
if (cells != 2) {
504+
dev_err(&pdev->dev, "#gpio-cells mismatch\n");
505+
return -EINVAL;
506+
}
507+
308508
/*
309509
* Check device node and parent device node for device width
310510
* and assume default width of 32
@@ -343,6 +543,7 @@ static int xgpio_probe(struct platform_device *pdev)
343543
chip->gc.parent = &pdev->dev;
344544
chip->gc.direction_input = xgpio_dir_in;
345545
chip->gc.direction_output = xgpio_dir_out;
546+
chip->gc.of_gpio_n_cells = cells;
346547
chip->gc.get = xgpio_get;
347548
chip->gc.set = xgpio_set;
348549
chip->gc.set_multiple = xgpio_set_multiple;
@@ -367,14 +568,51 @@ static int xgpio_probe(struct platform_device *pdev)
367568

368569
xgpio_save_regs(chip);
369570

571+
chip->irq = platform_get_irq_optional(pdev, 0);
572+
if (chip->irq <= 0)
573+
goto skip_irq;
574+
575+
chip->irqchip.name = "gpio-xilinx";
576+
chip->irqchip.irq_ack = xgpio_irq_ack;
577+
chip->irqchip.irq_mask = xgpio_irq_mask;
578+
chip->irqchip.irq_unmask = xgpio_irq_unmask;
579+
chip->irqchip.irq_set_type = xgpio_set_irq_type;
580+
581+
/* Disable per-channel interrupts */
582+
xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, 0);
583+
/* Clear any existing per-channel interrupts */
584+
temp = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET);
585+
xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, temp);
586+
/* Enable global interrupts */
587+
xgpio_writereg(chip->regs + XGPIO_GIER_OFFSET, XGPIO_GIER_IE);
588+
589+
girq = &chip->gc.irq;
590+
girq->chip = &chip->irqchip;
591+
girq->parent_handler = xgpio_irqhandler;
592+
girq->num_parents = 1;
593+
girq->parents = devm_kcalloc(&pdev->dev, 1,
594+
sizeof(*girq->parents),
595+
GFP_KERNEL);
596+
if (!girq->parents) {
597+
status = -ENOMEM;
598+
goto err_unprepare_clk;
599+
}
600+
girq->parents[0] = chip->irq;
601+
girq->default_type = IRQ_TYPE_NONE;
602+
girq->handler = handle_bad_irq;
603+
604+
skip_irq:
370605
status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);
371606
if (status) {
372607
dev_err(&pdev->dev, "failed to add GPIO chip\n");
373-
clk_disable_unprepare(chip->clk);
374-
return status;
608+
goto err_unprepare_clk;
375609
}
376610

377611
return 0;
612+
613+
err_unprepare_clk:
614+
clk_disable_unprepare(chip->clk);
615+
return status;
378616
}
379617

380618
static const struct of_device_id xgpio_of_match[] = {

0 commit comments

Comments
 (0)