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_relaxed(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 u32 irq; 139 140 if (hwirq == 0) 141 return 0; 142 143 while (hwirq) { 144 irq = __ffs(hwirq); 145 hwirq &= ~BIT(irq); 146 handle_domain_irq(root_domain, irq_base + irq, regs); 147 } 148 149 return 1; 150 } 151 152 /* gx6605s 64 irqs interrupt controller */ 153 static void gx_irq_handler(struct pt_regs *regs) 154 { 155 bool ret; 156 157 do { 158 ret = handle_irq_perbit(regs, 159 readl_relaxed(reg_base + GX_INTC_PEN31_00), 0); 160 ret |= handle_irq_perbit(regs, 161 readl_relaxed(reg_base + GX_INTC_PEN63_32), 32); 162 } while (ret); 163 } 164 165 static int __init 166 gx_intc_init(struct device_node *node, struct device_node *parent) 167 { 168 int ret; 169 170 ret = ck_intc_init_comm(node, parent); 171 if (ret) 172 return ret; 173 174 /* 175 * Initial enable reg to disable all interrupts 176 */ 177 writel_relaxed(0x0, reg_base + GX_INTC_NEN31_00); 178 writel_relaxed(0x0, reg_base + GX_INTC_NEN63_32); 179 180 /* 181 * Initial mask reg with all unmasked, because we only use enalbe reg 182 */ 183 writel_relaxed(0x0, reg_base + GX_INTC_NMASK31_00); 184 writel_relaxed(0x0, reg_base + GX_INTC_NMASK63_32); 185 186 setup_irq_channel(0x03020100, reg_base + GX_INTC_SOURCE); 187 188 ck_set_gc(node, reg_base, GX_INTC_NEN31_00, 0); 189 ck_set_gc(node, reg_base, GX_INTC_NEN63_32, 32); 190 191 set_handle_irq(gx_irq_handler); 192 193 return 0; 194 } 195 IRQCHIP_DECLARE(csky_gx6605s_intc, "csky,gx6605s-intc", gx_intc_init); 196 197 /* 198 * C-SKY simple 64 irqs interrupt controller, dual-together could support 128 199 * irqs. 200 */ 201 static void ck_irq_handler(struct pt_regs *regs) 202 { 203 bool ret; 204 void __iomem *reg_pen_lo = reg_base + CK_INTC_PEN31_00; 205 void __iomem *reg_pen_hi = reg_base + CK_INTC_PEN63_32; 206 207 do { 208 /* handle 0 - 31 irqs */ 209 ret = handle_irq_perbit(regs, readl_relaxed(reg_pen_lo), 0); 210 ret |= handle_irq_perbit(regs, readl_relaxed(reg_pen_hi), 32); 211 212 if (nr_irq == INTC_IRQS) 213 continue; 214 215 /* handle 64 - 127 irqs */ 216 ret |= handle_irq_perbit(regs, 217 readl_relaxed(reg_pen_lo + CK_INTC_DUAL_BASE), 64); 218 ret |= handle_irq_perbit(regs, 219 readl_relaxed(reg_pen_hi + CK_INTC_DUAL_BASE), 96); 220 } while (ret); 221 } 222 223 static int __init 224 ck_intc_init(struct device_node *node, struct device_node *parent) 225 { 226 int ret; 227 228 ret = ck_intc_init_comm(node, parent); 229 if (ret) 230 return ret; 231 232 /* Initial enable reg to disable all interrupts */ 233 writel_relaxed(0, reg_base + CK_INTC_NEN31_00); 234 writel_relaxed(0, reg_base + CK_INTC_NEN63_32); 235 236 /* Enable irq intc */ 237 writel_relaxed(BIT(31), reg_base + CK_INTC_ICR); 238 239 ck_set_gc(node, reg_base, CK_INTC_NEN31_00, 0); 240 ck_set_gc(node, reg_base, CK_INTC_NEN63_32, 32); 241 242 setup_irq_channel(0x00010203, reg_base + CK_INTC_SOURCE); 243 244 set_handle_irq(ck_irq_handler); 245 246 return 0; 247 } 248 IRQCHIP_DECLARE(ck_intc, "csky,apb-intc", ck_intc_init); 249 250 static int __init 251 ck_dual_intc_init(struct device_node *node, struct device_node *parent) 252 { 253 int ret; 254 255 /* dual-apb-intc up to 128 irq sources*/ 256 nr_irq = INTC_IRQS * 2; 257 258 ret = ck_intc_init(node, parent); 259 if (ret) 260 return ret; 261 262 /* Initial enable reg to disable all interrupts */ 263 writel_relaxed(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE); 264 writel_relaxed(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE); 265 266 ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN31_00, 64); 267 ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN63_32, 96); 268 269 setup_irq_channel(0x00010203, 270 reg_base + CK_INTC_SOURCE + CK_INTC_DUAL_BASE); 271 272 return 0; 273 } 274 IRQCHIP_DECLARE(ck_dual_intc, "csky,dual-apb-intc", ck_dual_intc_init); 275