arm64: dts: r8a7796: Enable HSCIF DMA
[linux-2.6/btrfs-unstable.git] / drivers / irqchip / irq-gemini.c
blob495224c743ee7c63ef2e209a928a120f78303376
1 /*
2 * irqchip for the Cortina Systems Gemini Copyright (C) 2017 Linus
3 * Walleij <linus.walleij@linaro.org>
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>
21 #include <asm/exception.h>
22 #include <asm/mach/irq.h>
24 #define GEMINI_NUM_IRQS 32
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)
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
45 struct gemini_irq_data {
46 void __iomem *base;
47 struct irq_chip chip;
48 struct irq_domain *domain;
51 static void gemini_irq_mask(struct irq_data *d)
53 struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
54 unsigned int mask;
56 mask = readl(GEMINI_IRQ_MASK(g->base));
57 mask &= ~BIT(irqd_to_hwirq(d));
58 writel(mask, GEMINI_IRQ_MASK(g->base));
61 static void gemini_irq_unmask(struct irq_data *d)
63 struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
64 unsigned int mask;
66 mask = readl(GEMINI_IRQ_MASK(g->base));
67 mask |= BIT(irqd_to_hwirq(d));
68 writel(mask, GEMINI_IRQ_MASK(g->base));
71 static void gemini_irq_ack(struct irq_data *d)
73 struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
75 writel(BIT(irqd_to_hwirq(d)), GEMINI_IRQ_CLEAR(g->base));
78 static int gemini_irq_set_type(struct irq_data *d, unsigned int trigger)
80 struct gemini_irq_data *g = irq_data_get_irq_chip_data(d);
81 int offset = irqd_to_hwirq(d);
82 u32 mode, polarity;
84 mode = readl(GEMINI_IRQ_MODE(g->base));
85 polarity = readl(GEMINI_IRQ_POLARITY(g->base));
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);
106 writel(mode, GEMINI_IRQ_MODE(g->base));
107 writel(polarity, GEMINI_IRQ_POLARITY(g->base));
109 return 0;
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,
120 /* Local static for the IRQ entry call */
121 static struct gemini_irq_data girq;
123 asmlinkage void __exception_irq_entry gemini_irqchip_handle_irq(struct pt_regs *regs)
125 struct gemini_irq_data *g = &girq;
126 int irq;
127 u32 status;
129 while ((status = readl(GEMINI_IRQ_STATUS(g->base)))) {
130 irq = ffs(status) - 1;
131 handle_domain_irq(g->domain, irq, regs);
135 static int gemini_irqdomain_map(struct irq_domain *d, unsigned int irq,
136 irq_hw_number_t hwirq)
138 struct gemini_irq_data *g = d->host_data;
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);
145 return 0;
148 static void gemini_irqdomain_unmap(struct irq_domain *d, unsigned int irq)
150 irq_set_chip_and_handler(irq, NULL, NULL);
151 irq_set_chip_data(irq, NULL);
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,
160 int __init gemini_of_init_irq(struct device_node *node,
161 struct device_node *parent)
163 struct gemini_irq_data *g = &girq;
166 * Disable the idle handler by default since it is buggy
167 * For more info see arch/arm/mach-gemini/idle.c
169 cpu_idle_poll_ctrl(true);
171 g->base = of_iomap(node, 0);
172 WARN(!g->base, "unable to map gemini irq registers\n");
174 /* Disable all interrupts */
175 writel(0, GEMINI_IRQ_MASK(g->base));
176 writel(0, GEMINI_FIQ_MASK(g->base));
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);
182 return 0;
184 IRQCHIP_DECLARE(gemini, "cortina,gemini-interrupt-controller",
185 gemini_of_init_irq);