oxnas: prepare platform and drivers for Linux 4.4
[openwrt.git] / target / linux / oxnas / files / drivers / irqchip / irq-rps.c
1 #include <linux/irqdomain.h>
2 #include <linux/irq.h>
3 #include <linux/of.h>
4 #include <linux/of_address.h>
5 #include <linux/of_irq.h>
6 #include <linux/irqchip/chained_irq.h>
7 #include <linux/err.h>
8 #include <linux/io.h>
9 #include <linux/version.h>
10
11 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
12 # include "irqchip.h"
13 #else
14 # include <linux/irqchip.h>
15 #endif
16
17 struct rps_chip_data {
18         void __iomem *base;
19         struct irq_chip chip;
20         struct irq_domain *domain;
21 } rps_data;
22
23 enum {
24         RPS_IRQ_BASE = 64,
25         RPS_IRQ_COUNT = 32,
26         PRS_HWIRQ_BASE = 0,
27
28         RPS_STATUS = 0,
29         RPS_RAW_STATUS = 4,
30         RPS_UNMASK = 8,
31         RPS_MASK = 0xc,
32 };
33
34 /*
35  * Routines to acknowledge, disable and enable interrupts
36  */
37 static void rps_mask_irq(struct irq_data *d)
38 {
39         struct rps_chip_data *chip_data = irq_data_get_irq_chip_data(d);
40         u32 mask = BIT(d->hwirq);
41
42         iowrite32(mask, chip_data->base + RPS_MASK);
43 }
44
45 static void rps_unmask_irq(struct irq_data *d)
46 {
47         struct rps_chip_data *chip_data = irq_data_get_irq_chip_data(d);
48         u32 mask = BIT(d->hwirq);
49
50         iowrite32(mask, chip_data->base + RPS_UNMASK);
51 }
52
53 static struct irq_chip rps_chip = {
54         .name                   = "RPS",
55         .irq_mask               = rps_mask_irq,
56         .irq_unmask             = rps_unmask_irq,
57 };
58
59 static int rps_irq_domain_xlate(struct irq_domain *d,
60                                 struct device_node *controller,
61                                 const u32 *intspec, unsigned int intsize,
62                                 unsigned long *out_hwirq,
63                                 unsigned int *out_type)
64 {
65 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0)
66         if (d->of_node != controller)
67 #else
68         if (irq_domain_get_of_node(d) != controller)
69 #endif
70                 return -EINVAL;
71         if (intsize < 1)
72                 return -EINVAL;
73
74         *out_hwirq = intspec[0];
75         /* Honestly I do not know the type */
76         *out_type = IRQ_TYPE_LEVEL_HIGH;
77
78         return 0;
79 }
80
81 static int rps_irq_domain_map(struct irq_domain *d, unsigned int irq,
82                                 irq_hw_number_t hw)
83 {
84         irq_set_chip_and_handler(irq, &rps_chip, handle_level_irq);
85 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
86         set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
87 #else
88         irq_set_probe(irq);
89 #endif
90         irq_set_chip_data(irq, d->host_data);
91         return 0;
92 }
93
94 const struct irq_domain_ops rps_irq_domain_ops = {
95         .map = rps_irq_domain_map,
96         .xlate = rps_irq_domain_xlate,
97 };
98
99 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
100 static void rps_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
101 #else
102 static void rps_handle_cascade_irq(struct irq_desc *desc)
103 #endif
104 {
105         struct rps_chip_data *chip_data = irq_desc_get_handler_data(desc);
106         struct irq_chip *chip = irq_desc_get_chip(desc);
107         unsigned int cascade_irq, rps_irq;
108         u32 status;
109
110         chained_irq_enter(chip, desc);
111
112         status = ioread32(chip_data->base + RPS_STATUS);
113         rps_irq = __ffs(status);
114         cascade_irq = irq_find_mapping(chip_data->domain, rps_irq);
115
116         if (unlikely(rps_irq >= RPS_IRQ_COUNT))
117 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0)
118                 handle_bad_irq(cascade_irq, desc);
119 #else
120                 handle_bad_irq(desc);
121 #endif
122         else
123                 generic_handle_irq(cascade_irq);
124
125         chained_irq_exit(chip, desc);
126 }
127
128 #ifdef CONFIG_OF
129 int __init rps_of_init(struct device_node *node, struct device_node *parent)
130 {
131         void __iomem *rps_base;
132         int irq_start = RPS_IRQ_BASE;
133         int irq_base;
134         int irq;
135
136         if (WARN_ON(!node))
137                 return -ENODEV;
138
139         rps_base = of_iomap(node, 0);
140         WARN(!rps_base, "unable to map rps registers\n");
141         rps_data.base = rps_base;
142
143         irq_base = irq_alloc_descs(irq_start, 0, RPS_IRQ_COUNT, numa_node_id());
144         if (IS_ERR_VALUE(irq_base)) {
145                 WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
146                      irq_start);
147                 irq_base = irq_start;
148         }
149
150         rps_data.domain = irq_domain_add_legacy(node, RPS_IRQ_COUNT, irq_base,
151                         PRS_HWIRQ_BASE, &rps_irq_domain_ops, &rps_data);
152
153         if (WARN_ON(!rps_data.domain))
154                 return -ENOMEM;
155
156         if (parent) {
157                 irq = irq_of_parse_and_map(node, 0);
158                 if (irq_set_handler_data(irq, &rps_data) != 0)
159                         BUG();
160                 irq_set_chained_handler(irq, rps_handle_cascade_irq);
161         }
162         return 0;
163
164 }
165
166 IRQCHIP_DECLARE(nas782x, "plxtech,nas782x-rps", rps_of_init);
167 #endif