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