Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

irqchip/irq-csky-mpintc: Add triger type

Support 4 triger types:
- IRQ_TYPE_LEVEL_HIGH
- IRQ_TYPE_LEVEL_LOW
- IRQ_TYPE_EDGE_RISING
- IRQ_TYPE_EDGE_FALLING

All of above could be set in DeviceTree file and it still compatible
with the old DeviceTree format.

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

authored by

Guo Ren and committed by
Marc Zyngier
648f835a 17c88892

+77 -1
+77 -1
drivers/irqchip/irq-csky-mpintc.c
··· 32 32 #define INTCG_CIDSTR 0x1000 33 33 34 34 #define INTCL_PICTLR 0x0 35 + #define INTCL_CFGR 0x14 35 36 #define INTCL_SIGR 0x60 36 37 #define INTCL_HPPIR 0x68 37 38 #define INTCL_RDYIR 0x6c ··· 41 40 #define INTCL_CACR 0xb4 42 41 43 42 static DEFINE_PER_CPU(void __iomem *, intcl_reg); 43 + 44 + static unsigned long *__trigger; 45 + 46 + #define IRQ_OFFSET(irq) ((irq < COMM_IRQ_BASE) ? irq : (irq - COMM_IRQ_BASE)) 47 + 48 + #define TRIG_BYTE_OFFSET(i) ((((i) * 2) / 32) * 4) 49 + #define TRIG_BIT_OFFSET(i) (((i) * 2) % 32) 50 + 51 + #define TRIG_VAL(trigger, irq) (trigger << TRIG_BIT_OFFSET(IRQ_OFFSET(irq))) 52 + #define TRIG_VAL_MSK(irq) (~(3 << TRIG_BIT_OFFSET(IRQ_OFFSET(irq)))) 53 + 54 + #define TRIG_BASE(irq) \ 55 + (TRIG_BYTE_OFFSET(IRQ_OFFSET(irq)) + ((irq < COMM_IRQ_BASE) ? \ 56 + (this_cpu_read(intcl_reg) + INTCL_CFGR) : (INTCG_base + INTCG_CICFGR))) 57 + 58 + static DEFINE_SPINLOCK(setup_lock); 59 + static void setup_trigger(unsigned long irq, unsigned long trigger) 60 + { 61 + unsigned int tmp; 62 + 63 + spin_lock(&setup_lock); 64 + 65 + /* setup trigger */ 66 + tmp = readl_relaxed(TRIG_BASE(irq)) & TRIG_VAL_MSK(irq); 67 + 68 + writel_relaxed(tmp | TRIG_VAL(trigger, irq), TRIG_BASE(irq)); 69 + 70 + spin_unlock(&setup_lock); 71 + } 44 72 45 73 static void csky_mpintc_handler(struct pt_regs *regs) 46 74 { ··· 86 56 { 87 57 void __iomem *reg_base = this_cpu_read(intcl_reg); 88 58 59 + setup_trigger(d->hwirq, __trigger[d->hwirq]); 60 + 89 61 writel_relaxed(d->hwirq, reg_base + INTCL_SENR); 90 62 } 91 63 ··· 103 71 void __iomem *reg_base = this_cpu_read(intcl_reg); 104 72 105 73 writel_relaxed(d->hwirq, reg_base + INTCL_CACR); 74 + } 75 + 76 + static int csky_mpintc_set_type(struct irq_data *d, unsigned int type) 77 + { 78 + switch (type & IRQ_TYPE_SENSE_MASK) { 79 + case IRQ_TYPE_LEVEL_HIGH: 80 + __trigger[d->hwirq] = 0; 81 + break; 82 + case IRQ_TYPE_LEVEL_LOW: 83 + __trigger[d->hwirq] = 1; 84 + break; 85 + case IRQ_TYPE_EDGE_RISING: 86 + __trigger[d->hwirq] = 2; 87 + break; 88 + case IRQ_TYPE_EDGE_FALLING: 89 + __trigger[d->hwirq] = 3; 90 + break; 91 + default: 92 + return -EINVAL; 93 + } 94 + 95 + return 0; 106 96 } 107 97 108 98 #ifdef CONFIG_SMP ··· 159 105 .irq_eoi = csky_mpintc_eoi, 160 106 .irq_enable = csky_mpintc_enable, 161 107 .irq_disable = csky_mpintc_disable, 108 + .irq_set_type = csky_mpintc_set_type, 162 109 #ifdef CONFIG_SMP 163 110 .irq_set_affinity = csky_irq_set_affinity, 164 111 #endif ··· 180 125 return 0; 181 126 } 182 127 128 + static int csky_irq_domain_xlate_cells(struct irq_domain *d, 129 + struct device_node *ctrlr, const u32 *intspec, 130 + unsigned int intsize, unsigned long *out_hwirq, 131 + unsigned int *out_type) 132 + { 133 + if (WARN_ON(intsize < 1)) 134 + return -EINVAL; 135 + 136 + *out_hwirq = intspec[0]; 137 + if (intsize > 1) 138 + *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; 139 + else 140 + *out_type = IRQ_TYPE_LEVEL_HIGH; 141 + 142 + return 0; 143 + } 144 + 183 145 static const struct irq_domain_ops csky_irqdomain_ops = { 184 146 .map = csky_irqdomain_map, 185 - .xlate = irq_domain_xlate_onecell, 147 + .xlate = csky_irq_domain_xlate_cells, 186 148 }; 187 149 188 150 #ifdef CONFIG_SMP ··· 232 160 ret = of_property_read_u32(node, "csky,num-irqs", &nr_irq); 233 161 if (ret < 0) 234 162 nr_irq = INTC_IRQS; 163 + 164 + __trigger = kcalloc(nr_irq, sizeof(unsigned long), GFP_KERNEL); 165 + if (__trigger == NULL) 166 + return -ENXIO; 235 167 236 168 if (INTCG_base == NULL) { 237 169 INTCG_base = ioremap(mfcr("cr<31, 14>"),