GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / irqchip / irq-gic-common.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2002 ARM Limited, All Rights Reserved.
4  */
5
6 #include <linux/interrupt.h>
7 #include <linux/io.h>
8 #include <linux/irq.h>
9 #include <linux/irqchip/arm-gic.h>
10
11 #include "irq-gic-common.h"
12
13 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
14
15 void gic_enable_of_quirks(const struct device_node *np,
16                           const struct gic_quirk *quirks, void *data)
17 {
18         for (; quirks->desc; quirks++) {
19                 if (!quirks->compatible && !quirks->property)
20                         continue;
21                 if (quirks->compatible &&
22                     !of_device_is_compatible(np, quirks->compatible))
23                         continue;
24                 if (quirks->property &&
25                     !of_property_read_bool(np, quirks->property))
26                         continue;
27                 if (quirks->init(data))
28                         pr_info("GIC: enabling workaround for %s\n",
29                                 quirks->desc);
30         }
31 }
32
33 void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
34                 void *data)
35 {
36         for (; quirks->desc; quirks++) {
37                 if (quirks->compatible || quirks->property)
38                         continue;
39                 if (quirks->iidr != (quirks->mask & iidr))
40                         continue;
41                 if (quirks->init(data))
42                         pr_info("GIC: enabling workaround for %s\n",
43                                 quirks->desc);
44         }
45 }
46
47 int gic_configure_irq(unsigned int irq, unsigned int type,
48                        void __iomem *base, void (*sync_access)(void))
49 {
50         u32 confmask = 0x2 << ((irq % 16) * 2);
51         u32 confoff = (irq / 16) * 4;
52         u32 val, oldval;
53         int ret = 0;
54         unsigned long flags;
55
56         /*
57          * Read current configuration register, and insert the config
58          * for "irq", depending on "type".
59          */
60         raw_spin_lock_irqsave(&irq_controller_lock, flags);
61         val = oldval = readl_relaxed(base + confoff);
62         if (type & IRQ_TYPE_LEVEL_MASK)
63                 val &= ~confmask;
64         else if (type & IRQ_TYPE_EDGE_BOTH)
65                 val |= confmask;
66
67         /* If the current configuration is the same, then we are done */
68         if (val == oldval) {
69                 raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
70                 return 0;
71         }
72
73         /*
74          * Write back the new configuration, and possibly re-enable
75          * the interrupt. If we fail to write a new configuration for
76          * an SPI then WARN and return an error. If we fail to write the
77          * configuration for a PPI this is most likely because the GIC
78          * does not allow us to set the configuration or we are in a
79          * non-secure mode, and hence it may not be catastrophic.
80          */
81         writel_relaxed(val, base + confoff);
82         if (readl_relaxed(base + confoff) != val)
83                 ret = -EINVAL;
84
85         raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
86
87         if (sync_access)
88                 sync_access();
89
90         return ret;
91 }
92
93 void gic_dist_config(void __iomem *base, int gic_irqs,
94                      void (*sync_access)(void))
95 {
96         unsigned int i;
97
98         /*
99          * Set all global interrupts to be level triggered, active low.
100          */
101         for (i = 32; i < gic_irqs; i += 16)
102                 writel_relaxed(GICD_INT_ACTLOW_LVLTRIG,
103                                         base + GIC_DIST_CONFIG + i / 4);
104
105         /*
106          * Set priority on all global interrupts.
107          */
108         for (i = 32; i < gic_irqs; i += 4)
109                 writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
110
111         /*
112          * Deactivate and disable all SPIs. Leave the PPI and SGIs
113          * alone as they are in the redistributor registers on GICv3.
114          */
115         for (i = 32; i < gic_irqs; i += 32) {
116                 writel_relaxed(GICD_INT_EN_CLR_X32,
117                                base + GIC_DIST_ACTIVE_CLEAR + i / 8);
118                 writel_relaxed(GICD_INT_EN_CLR_X32,
119                                base + GIC_DIST_ENABLE_CLEAR + i / 8);
120         }
121
122         if (sync_access)
123                 sync_access();
124 }
125
126 void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void))
127 {
128         int i;
129
130         /*
131          * Deal with the banked PPI and SGI interrupts - disable all
132          * private interrupts. Make sure everything is deactivated.
133          */
134         for (i = 0; i < nr; i += 32) {
135                 writel_relaxed(GICD_INT_EN_CLR_X32,
136                                base + GIC_DIST_ACTIVE_CLEAR + i / 8);
137                 writel_relaxed(GICD_INT_EN_CLR_X32,
138                                base + GIC_DIST_ENABLE_CLEAR + i / 8);
139         }
140
141         /*
142          * Set priority on PPI and SGI interrupts
143          */
144         for (i = 0; i < nr; i += 4)
145                 writel_relaxed(GICD_INT_DEF_PRI_X4,
146                                         base + GIC_DIST_PRI + i * 4 / 4);
147
148         if (sync_access)
149                 sync_access();
150 }