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_ARRAY(a) a, __same_type(a, NULL) ? 0 : sizeof(a)/sizeof(*a) 101 102 #define INTC_HW_DESC(vectors, groups, mask_regs, \ 103 prio_regs, sense_regs, ack_regs) \ 104 { \ 105 _INTC_ARRAY(vectors), _INTC_ARRAY(groups), \ 106 _INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs), \ 107 _INTC_ARRAY(sense_regs), _INTC_ARRAY(ack_regs), \ 108 } 109 110 struct intc_desc { 111 char *name; 112 struct resource *resource; 113 unsigned int num_resources; 114 intc_enum force_enable; 115 intc_enum force_disable; 116 bool skip_syscore_suspend; 117 struct intc_hw_desc hw; 118 }; 119 120 #define DECLARE_INTC_DESC(symbol, chipname, vectors, groups, \ 121 mask_regs, prio_regs, sense_regs) \ 122 struct intc_desc symbol __initdata = { \ 123 .name = chipname, \ 124 .hw = INTC_HW_DESC(vectors, groups, mask_regs, \ 125 prio_regs, sense_regs, NULL), \ 126 } 127 128 #define DECLARE_INTC_DESC_ACK(symbol, chipname, vectors, groups, \ 129 mask_regs, prio_regs, sense_regs, ack_regs) \ 130 struct intc_desc symbol __initdata = { \ 131 .name = chipname, \ 132 .hw = INTC_HW_DESC(vectors, groups, mask_regs, \ 133 prio_regs, sense_regs, ack_regs), \ 134 } 135 136 int register_intc_controller(struct intc_desc *desc); 137 int intc_set_priority(unsigned int irq, unsigned int prio); 138 int intc_irq_lookup(const char *chipname, intc_enum enum_id); 139 void intc_finalize(void); 140 141 #ifdef CONFIG_INTC_USERIMASK 142 int register_intc_userimask(unsigned long addr); 143 #else 144 static inline int register_intc_userimask(unsigned long addr) 145 { 146 return 0; 147 } 148 #endif 149 150 #endif /* __SH_INTC_H */ 151