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 /* Avoid IRQ0 (invalid for platform devices) */ 17#define evt2irq(evt) ((evt) >> 5) 18#define irq2evt(irq) ((irq) << 5) 19#else 20#define evt2irq(evt) (evt) 21#define irq2evt(irq) (irq) 22#endif 23 24typedef unsigned char intc_enum; 25 26struct 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 34struct 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 41struct intc_subgroup { 42 unsigned long reg, reg_width; 43 intc_enum parent_id; 44 intc_enum enum_ids[32]; 45}; 46 47struct 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 58struct 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 66struct 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 83struct 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 113struct 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) \ 125struct 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) \ 133struct 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 139int register_intc_controller(struct intc_desc *desc); 140int intc_set_priority(unsigned int irq, unsigned int prio); 141int intc_irq_lookup(const char *chipname, intc_enum enum_id); 142void intc_finalize(void); 143 144#ifdef CONFIG_INTC_USERIMASK 145int register_intc_userimask(unsigned long addr); 146#else 147static inline int register_intc_userimask(unsigned long addr) 148{ 149 return 0; 150} 151#endif 152 153#endif /* __SH_INTC_H */ 154