1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef __SH_INTC_H 3 #define __SH_INTC_H 4 5 #include <linux/ioport.h> 6 7 #ifdef CONFIG_SUPERH 8 #define INTC_NR_IRQS 512 9 #else 10 #define INTC_NR_IRQS 1024 11 #endif 12 13 /* 14 * Convert back and forth between INTEVT and IRQ values. 15 */ 16 #ifdef CONFIG_CPU_HAS_INTEVT 17 #define evt2irq(evt) (((evt) >> 5) - 16) 18 #define irq2evt(irq) (((irq) + 16) << 5) 19 #else 20 #define evt2irq(evt) (evt) 21 #define irq2evt(irq) (irq) 22 #endif 23 24 typedef unsigned char intc_enum; 25 26 struct intc_vect { 27 intc_enum enum_id; 28 unsigned short vect; 29 }; 30 31 #define INTC_VECT(enum_id, vect) { enum_id, vect } 32 #define INTC_IRQ(enum_id, irq) INTC_VECT(enum_id, irq2evt(irq)) 33 34 struct intc_group { 35 intc_enum enum_id; 36 intc_enum enum_ids[32]; 37 }; 38 39 #define INTC_GROUP(enum_id, ids...) { enum_id, { ids } } 40 41 struct intc_subgroup { 42 unsigned long reg, reg_width; 43 intc_enum parent_id; 44 intc_enum enum_ids[32]; 45 }; 46 47 struct intc_mask_reg { 48 unsigned long set_reg, clr_reg, reg_width; 49 intc_enum enum_ids[32]; 50 #ifdef CONFIG_INTC_BALANCING 51 unsigned long dist_reg; 52 #endif 53 #ifdef CONFIG_SMP 54 unsigned long smp; 55 #endif 56 }; 57 58 struct intc_prio_reg { 59 unsigned long set_reg, clr_reg, reg_width, field_width; 60 intc_enum enum_ids[16]; 61 #ifdef CONFIG_SMP 62 unsigned long smp; 63 #endif 64 }; 65 66 struct intc_sense_reg { 67 unsigned long reg, reg_width, field_width; 68 intc_enum enum_ids[16]; 69 }; 70 71 #ifdef CONFIG_INTC_BALANCING 72 #define INTC_SMP_BALANCING(reg) .dist_reg = (reg) 73 #else 74 #define INTC_SMP_BALANCING(reg) 75 #endif 76 77 #ifdef CONFIG_SMP 78 #define INTC_SMP(stride, nr) .smp = (stride) | ((nr) << 8) 79 #else 80 #define INTC_SMP(stride, nr) 81 #endif 82 83 struct intc_hw_desc { 84 struct intc_vect *vectors; 85 unsigned int nr_vectors; 86 struct intc_group *groups; 87 unsigned int nr_groups; 88 struct intc_mask_reg *mask_regs; 89 unsigned int nr_mask_regs; 90 struct intc_prio_reg *prio_regs; 91 unsigned int nr_prio_regs; 92 struct intc_sense_reg *sense_regs; 93 unsigned int nr_sense_regs; 94 struct intc_mask_reg *ack_regs; 95 unsigned int nr_ack_regs; 96 struct intc_subgroup *subgroups; 97 unsigned int nr_subgroups; 98 }; 99 100 #define _INTC_SIZEOF_OR_ZERO(a) (_Generic(a, \ 101 typeof(NULL): 0, \ 102 default: sizeof(a))) 103 #define _INTC_ARRAY(a) a, _INTC_SIZEOF_OR_ZERO(a)/sizeof(*a) 104 105 #define INTC_HW_DESC(vectors, groups, mask_regs, \ 106 prio_regs, sense_regs, ack_regs) \ 107 { \ 108 _INTC_ARRAY(vectors), _INTC_ARRAY(groups), \ 109 _INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs), \ 110 _INTC_ARRAY(sense_regs), _INTC_ARRAY(ack_regs), \ 111 } 112 113 struct intc_desc { 114 char *name; 115 struct resource *resource; 116 unsigned int num_resources; 117 intc_enum force_enable; 118 intc_enum force_disable; 119 bool skip_syscore_suspend; 120 struct intc_hw_desc hw; 121 }; 122 123 #define DECLARE_INTC_DESC(symbol, chipname, vectors, groups, \ 124 mask_regs, prio_regs, sense_regs) \ 125 struct intc_desc symbol __initdata = { \ 126 .name = chipname, \ 127 .hw = INTC_HW_DESC(vectors, groups, mask_regs, \ 128 prio_regs, sense_regs, NULL), \ 129 } 130 131 #define DECLARE_INTC_DESC_ACK(symbol, chipname, vectors, groups, \ 132 mask_regs, prio_regs, sense_regs, ack_regs) \ 133 struct intc_desc symbol __initdata = { \ 134 .name = chipname, \ 135 .hw = INTC_HW_DESC(vectors, groups, mask_regs, \ 136 prio_regs, sense_regs, ack_regs), \ 137 } 138 139 int register_intc_controller(struct intc_desc *desc); 140 int intc_set_priority(unsigned int irq, unsigned int prio); 141 int intc_irq_lookup(const char *chipname, intc_enum enum_id); 142 void intc_finalize(void); 143 144 #ifdef CONFIG_INTC_USERIMASK 145 int register_intc_userimask(unsigned long addr); 146 #else 147 static inline int register_intc_userimask(unsigned long addr) 148 { 149 return 0; 150 } 151 #endif 152 153 #endif /* __SH_INTC_H */ 154