1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 3 4 #include <linux/kernel.h> 5 #include <linux/init.h> 6 #include <linux/of.h> 7 #include <linux/of_address.h> 8 #include <linux/module.h> 9 #include <linux/irqdomain.h> 10 #include <linux/irqchip.h> 11 #include <linux/irq.h> 12 #include <linux/interrupt.h> 13 #include <linux/io.h> 14 #include <asm/irq.h> 15 16 #define INTC_IRQS 64 17 18 #define CK_INTC_ICR 0x00 19 #define CK_INTC_PEN31_00 0x14 20 #define CK_INTC_PEN63_32 0x2c 21 #define CK_INTC_NEN31_00 0x10 22 #define CK_INTC_NEN63_32 0x28 23 #define CK_INTC_SOURCE 0x40 24 #define CK_INTC_DUAL_BASE 0x100 25 26 #define GX_INTC_PEN31_00 0x00 27 #define GX_INTC_PEN63_32 0x04 28 #define GX_INTC_NEN31_00 0x40 29 #define GX_INTC_NEN63_32 0x44 30 #define GX_INTC_NMASK31_00 0x50 31 #define GX_INTC_NMASK63_32 0x54 32 #define GX_INTC_SOURCE 0x60 33 34 static void __iomem *reg_base; 35 static struct irq_domain *root_domain; 36 37 static int nr_irq = INTC_IRQS; 38 39 /* 40 * When controller support pulse signal, the PEN_reg will hold on signal 41 * without software trigger. 42 * 43 * So, to support pulse signal we need to clear IFR_reg and the address of 44 * IFR_offset is NEN_offset - 8. 45 */ 46 static void irq_ck_mask_set_bit(struct irq_data *d) 47 { 48 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 49 struct irq_chip_type *ct = irq_data_get_chip_type(d); 50 unsigned long ifr = ct->regs.mask - 8; 51 u32 mask = d->mask; 52 53 irq_gc_lock(gc); 54 *ct->mask_cache |= mask; 55 irq_reg_writel(gc, *ct->mask_cache, ct->regs.mask); 56 irq_reg_writel(gc, irq_reg_readl(gc, ifr) & ~mask, ifr); 57 irq_gc_unlock(gc); 58 } 59 60 static void __init ck_set_gc(struct device_node *node, void __iomem *reg_base, 61 u32 mask_reg, u32 irq_base) 62 { 63 struct irq_chip_generic *gc; 64 65 gc = irq_get_domain_generic_chip(root_domain, irq_base); 66 gc->reg_base = reg_base; 67 gc->chip_types[0].regs.mask = mask_reg; 68 gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; 69 gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; 70 71 if (of_find_property(node, "csky,support-pulse-signal", NULL)) 72 gc->chip_types[0].chip.irq_unmask = irq_ck_mask_set_bit; 73 } 74 75 static inline u32 build_channel_val(u32 idx, u32 magic) 76 { 77 u32 res; 78 79 /* 80 * Set the same index for each channel 81 */ 82 res = idx | (idx << 8) | (idx << 16) | (idx << 24); 83 84 /* 85 * Set the channel magic number in descending order. 86 * The magic is 0x00010203 for ck-intc 87 * The magic is 0x03020100 for gx6605s-intc 88 */ 89 return res | magic; 90 } 91 92 static inline void setup_irq_channel(u32 magic, void __iomem *reg_addr) 93 { 94 u32 i; 95 96 /* Setup 64 channel slots */ 97 for (i = 0; i < INTC_IRQS; i += 4) 98 writel(build_channel_val(i, magic), reg_addr + i); 99 } 100 101 static int __init 102 ck_intc_init_comm(struct device_node *node, struct device_node *parent) 103 { 104 int ret; 105 106 if (parent) { 107 pr_err("C-SKY Intc not a root irq controller\n"); 108 return -EINVAL; 109 } 110 111 reg_base = of_iomap(node, 0); 112 if (!reg_base) { 113 pr_err("C-SKY Intc unable to map: %p.\n", node); 114 return -EINVAL; 115 } 116 117 root_domain = irq_domain_add_linear(node, nr_irq, 118 &irq_generic_chip_ops, NULL); 119 if (!root_domain) { 120 pr_err("C-SKY Intc irq_domain_add failed.\n"); 121 return -ENOMEM; 122 } 123 124 ret = irq_alloc_domain_generic_chips(root_domain, 32, 1, 125 "csky_intc", handle_level_irq, 126 IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN, 0, 0); 127 if (ret) { 128 pr_err("C-SKY Intc irq_alloc_gc failed.\n"); 129 return -ENOMEM; 130 } 131 132 return 0; 133 } 134 135 static inline bool handle_irq_perbit(struct pt_regs *regs, u32 hwirq, 136 u32 irq_base) 137 { 138 if (hwirq == 0) 139 return 0; 140 141 handle_domain_irq(root_domain, irq_base + __fls(hwirq), regs); 142 143 return 1; 144 } 145 146 /* gx6605s 64 irqs interrupt controller */ 147 static void gx_irq_handler(struct pt_regs *regs) 148 { 149 bool ret; 150 151 retry: 152 ret = handle_irq_perbit(regs, 153 readl(reg_base + GX_INTC_PEN63_32), 32); 154 if (ret) 155 goto retry; 156 157 ret = handle_irq_perbit(regs, 158 readl(reg_base + GX_INTC_PEN31_00), 0); 159 if (ret) 160 goto retry; 161 } 162 163 static int __init 164 gx_intc_init(struct device_node *node, struct device_node *parent) 165 { 166 int ret; 167 168 ret = ck_intc_init_comm(node, parent); 169 if (ret) 170 return ret; 171 172 /* 173 * Initial enable reg to disable all interrupts 174 */ 175 writel(0x0, reg_base + GX_INTC_NEN31_00); 176 writel(0x0, reg_base + GX_INTC_NEN63_32); 177 178 /* 179 * Initial mask reg with all unmasked, because we only use enable reg 180 */ 181 writel(0x0, reg_base + GX_INTC_NMASK31_00); 182 writel(0x0, reg_base + GX_INTC_NMASK63_32); 183 184 setup_irq_channel(0x03020100, reg_base + GX_INTC_SOURCE); 185 186 ck_set_gc(node, reg_base, GX_INTC_NEN31_00, 0); 187 ck_set_gc(node, reg_base, GX_INTC_NEN63_32, 32); 188 189 set_handle_irq(gx_irq_handler); 190 191 return 0; 192 } 193 IRQCHIP_DECLARE(csky_gx6605s_intc, "csky,gx6605s-intc", gx_intc_init); 194 195 /* 196 * C-SKY simple 64 irqs interrupt controller, dual-together could support 128 197 * irqs. 198 */ 199 static void ck_irq_handler(struct pt_regs *regs) 200 { 201 bool ret; 202 void __iomem *reg_pen_lo = reg_base + CK_INTC_PEN31_00; 203 void __iomem *reg_pen_hi = reg_base + CK_INTC_PEN63_32; 204 205 retry: 206 /* handle 0 - 63 irqs */ 207 ret = handle_irq_perbit(regs, readl(reg_pen_hi), 32); 208 if (ret) 209 goto retry; 210 211 ret = handle_irq_perbit(regs, readl(reg_pen_lo), 0); 212 if (ret) 213 goto retry; 214 215 if (nr_irq == INTC_IRQS) 216 return; 217 218 /* handle 64 - 127 irqs */ 219 ret = handle_irq_perbit(regs, 220 readl(reg_pen_hi + CK_INTC_DUAL_BASE), 96); 221 if (ret) 222 goto retry; 223 224 ret = handle_irq_perbit(regs, 225 readl(reg_pen_lo + CK_INTC_DUAL_BASE), 64); 226 if (ret) 227 goto retry; 228 } 229 230 static int __init 231 ck_intc_init(struct device_node *node, struct device_node *parent) 232 { 233 int ret; 234 235 ret = ck_intc_init_comm(node, parent); 236 if (ret) 237 return ret; 238 239 /* Initial enable reg to disable all interrupts */ 240 writel(0, reg_base + CK_INTC_NEN31_00); 241 writel(0, reg_base + CK_INTC_NEN63_32); 242 243 /* Enable irq intc */ 244 writel(BIT(31), reg_base + CK_INTC_ICR); 245 246 ck_set_gc(node, reg_base, CK_INTC_NEN31_00, 0); 247 ck_set_gc(node, reg_base, CK_INTC_NEN63_32, 32); 248 249 setup_irq_channel(0x00010203, reg_base + CK_INTC_SOURCE); 250 251 set_handle_irq(ck_irq_handler); 252 253 return 0; 254 } 255 IRQCHIP_DECLARE(ck_intc, "csky,apb-intc", ck_intc_init); 256 257 static int __init 258 ck_dual_intc_init(struct device_node *node, struct device_node *parent) 259 { 260 int ret; 261 262 /* dual-apb-intc up to 128 irq sources*/ 263 nr_irq = INTC_IRQS * 2; 264 265 ret = ck_intc_init(node, parent); 266 if (ret) 267 return ret; 268 269 /* Initial enable reg to disable all interrupts */ 270 writel(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE); 271 writel(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE); 272 273 ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN31_00, 64); 274 ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN63_32, 96); 275 276 setup_irq_channel(0x00010203, 277 reg_base + CK_INTC_SOURCE + CK_INTC_DUAL_BASE); 278 279 return 0; 280 } 281 IRQCHIP_DECLARE(ck_dual_intc, "csky,dual-apb-intc", ck_dual_intc_init); 282