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