Merge branch 'for-linus-4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
[linux-2.6-block.git] / drivers / irqchip / irq-gemini.c
1 /*
2  * irqchip for the Cortina Systems Gemini Copyright (C) 2017 Linus
3  * Walleij <linus.walleij@linaro.org>
4  *
5  * Based on arch/arm/mach-gemini/irq.c
6  * Copyright (C) 2001-2006 Storlink, Corp.
7  * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
8  */
9 #include <linux/bitops.h>
10 #include <linux/irq.h>
11 #include <linux/io.h>
12 #include <linux/irqchip.h>
13 #include <linux/irqchip/versatile-fpga.h>
14 #include <linux/irqdomain.h>
15 #include <linux/module.h>
16 #include <linux/of.h>
17 #include <linux/of_address.h>
18 #include <linux/of_irq.h>
19 #include <linux/cpu.h>
20
21 #include <asm/exception.h>
22 #include <asm/mach/irq.h>
23
24 #define GEMINI_NUM_IRQS 32
25
26 #define GEMINI_IRQ_SOURCE(base_addr)    (base_addr + 0x00)
27 #define GEMINI_IRQ_MASK(base_addr)      (base_addr + 0x04)
28 #define GEMINI_IRQ_CLEAR(base_addr)     (base_addr + 0x08)
29 #define GEMINI_IRQ_MODE(base_addr)      (base_addr + 0x0C)
30 #define GEMINI_IRQ_POLARITY(base_addr)  (base_addr + 0x10)
31 #define GEMINI_IRQ_STATUS(base_addr)    (base_addr + 0x14)
32 #define GEMINI_FIQ_SOURCE(base_addr)    (base_addr + 0x20)
33 #define GEMINI_FIQ_MASK(base_addr)      (base_addr + 0x24)
34 #define GEMINI_FIQ_CLEAR(base_addr)     (base_addr + 0x28)
35 #define GEMINI_FIQ_MODE(base_addr)      (base_addr + 0x2C)
36 #define GEMINI_FIQ_POLARITY(base_addr)  (base_addr + 0x30)
37 #define GEMINI_FIQ_STATUS(base_addr)    (base_addr + 0x34)
38
39 /**
40  * struct gemini_irq_data - irq data container for the Gemini IRQ controller
41  * @base: memory offset in virtual memory
42  * @chip: chip container for this instance
43  * @domain: IRQ domain for this instance
44  */
45 struct gemini_irq_data {
46         void __iomem *base;
47         struct irq_chip chip;
48         struct irq_domain *domain;
49 };
50
51 static void gemini_irq_mask(struct irq_data *d)
52 {
53         struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
54         unsigned int mask;
55
56         mask = readl(GEMINI_IRQ_MASK(g->base));
57         mask &= ~BIT(irqd_to_hwirq(d));
58         writel(mask, GEMINI_IRQ_MASK(g->base));
59 }
60
61 static void gemini_irq_unmask(struct irq_data *d)
62 {
63         struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
64         unsigned int mask;
65
66         mask = readl(GEMINI_IRQ_MASK(g->base));
67         mask |= BIT(irqd_to_hwirq(d));
68         writel(mask, GEMINI_IRQ_MASK(g->base));
69 }
70
71 static void gemini_irq_ack(struct irq_data *d)
72 {
73         struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
74
75         writel(BIT(irqd_to_hwirq(d)), GEMINI_IRQ_CLEAR(g->base));
76 }
77
78 static int gemini_irq_set_type(struct irq_data *d, unsigned int trigger)
79 {
80         struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
81         int offset = irqd_to_hwirq(d);
82         u32 mode, polarity;
83
84         mode = readl(GEMINI_IRQ_MODE(g->base));
85         polarity = readl(GEMINI_IRQ_POLARITY(g->base));
86
87         if (trigger & (IRQ_TYPE_LEVEL_HIGH)) {
88                 irq_set_handler_locked(d, handle_level_irq);
89                 /* Disable edge detection */
90                 mode &= ~BIT(offset);
91                 polarity &= ~BIT(offset);
92         } else if (trigger & IRQ_TYPE_EDGE_RISING) {
93                 irq_set_handler_locked(d, handle_edge_irq);
94                 mode |= BIT(offset);
95                 polarity |= BIT(offset);
96         } else if (trigger & IRQ_TYPE_EDGE_FALLING) {
97                 irq_set_handler_locked(d, handle_edge_irq);
98                 mode |= BIT(offset);
99                 polarity &= ~BIT(offset);
100         } else {
101                 irq_set_handler_locked(d, handle_bad_irq);
102                 pr_warn("GEMINI IRQ: no supported trigger selected for line %d\n",
103                         offset);
104         }
105
106         writel(mode, GEMINI_IRQ_MODE(g->base));
107         writel(polarity, GEMINI_IRQ_POLARITY(g->base));
108
109         return 0;
110 }
111
112 static struct irq_chip gemini_irq_chip = {
113         .name           = "GEMINI",
114         .irq_ack        = gemini_irq_ack,
115         .irq_mask       = gemini_irq_mask,
116         .irq_unmask     = gemini_irq_unmask,
117         .irq_set_type   = gemini_irq_set_type,
118 };
119
120 /* Local static for the IRQ entry call */
121 static struct gemini_irq_data girq;
122
123 asmlinkage void __exception_irq_entry gemini_irqchip_handle_irq(struct pt_regs *regs)
124 {
125         struct gemini_irq_data *g = &girq;
126         int irq;
127         u32 status;
128
129         while ((status = readl(GEMINI_IRQ_STATUS(g->base)))) {
130                 irq = ffs(status) - 1;
131                 handle_domain_irq(g->domain, irq, regs);
132         }
133 }
134
135 static int gemini_irqdomain_map(struct irq_domain *d, unsigned int irq,
136                                 irq_hw_number_t hwirq)
137 {
138         struct gemini_irq_data *g = d->host_data;
139
140         irq_set_chip_data(irq, g);
141         /* All IRQs should set up their type, flags as bad by default */
142         irq_set_chip_and_handler(irq, &gemini_irq_chip, handle_bad_irq);
143         irq_set_probe(irq);
144
145         return 0;
146 }
147
148 static void gemini_irqdomain_unmap(struct irq_domain *d, unsigned int irq)
149 {
150         irq_set_chip_and_handler(irq, NULL, NULL);
151         irq_set_chip_data(irq, NULL);
152 }
153
154 static const struct irq_domain_ops gemini_irqdomain_ops = {
155         .map = gemini_irqdomain_map,
156         .unmap = gemini_irqdomain_unmap,
157         .xlate = irq_domain_xlate_onetwocell,
158 };
159
160 int __init gemini_of_init_irq(struct device_node *node,
161                               struct device_node *parent)
162 {
163         struct gemini_irq_data *g = &girq;
164
165         /*
166          * Disable the idle handler by default since it is buggy
167          * For more info see arch/arm/mach-gemini/idle.c
168          */
169         cpu_idle_poll_ctrl(true);
170
171         g->base = of_iomap(node, 0);
172         WARN(!g->base, "unable to map gemini irq registers\n");
173
174         /* Disable all interrupts */
175         writel(0, GEMINI_IRQ_MASK(g->base));
176         writel(0, GEMINI_FIQ_MASK(g->base));
177
178         g->domain = irq_domain_add_simple(node, GEMINI_NUM_IRQS, 0,
179                                           &gemini_irqdomain_ops, g);
180         set_handle_irq(gemini_irqchip_handle_irq);
181
182         return 0;
183 }
184 IRQCHIP_DECLARE(gemini, "cortina,gemini-interrupt-controller",
185                 gemini_of_init_irq);