xref: /linux/arch/loongarch/include/asm/irq.h (revision 023087324000ae704cf3cfd0abf1fc30c6e0e8d5)
10603839bSHuacai Chen /* SPDX-License-Identifier: GPL-2.0 */
20603839bSHuacai Chen /*
30603839bSHuacai Chen  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
40603839bSHuacai Chen  */
50603839bSHuacai Chen #ifndef _ASM_IRQ_H
60603839bSHuacai Chen #define _ASM_IRQ_H
70603839bSHuacai Chen 
80603839bSHuacai Chen #include <linux/irqdomain.h>
90603839bSHuacai Chen #include <linux/irqreturn.h>
100603839bSHuacai Chen 
110603839bSHuacai Chen #define IRQ_STACK_SIZE			THREAD_SIZE
120603839bSHuacai Chen #define IRQ_STACK_START			(IRQ_STACK_SIZE - 16)
130603839bSHuacai Chen 
140603839bSHuacai Chen DECLARE_PER_CPU(unsigned long, irq_stack);
150603839bSHuacai Chen 
160603839bSHuacai Chen /*
170603839bSHuacai Chen  * The highest address on the IRQ stack contains a dummy frame which is
180603839bSHuacai Chen  * structured as follows:
190603839bSHuacai Chen  *
200603839bSHuacai Chen  *   top ------------
210603839bSHuacai Chen  *       | task sp  | <- irq_stack[cpu] + IRQ_STACK_START
220603839bSHuacai Chen  *       ------------
230603839bSHuacai Chen  *       |          | <- First frame of IRQ context
240603839bSHuacai Chen  *       ------------
250603839bSHuacai Chen  *
260603839bSHuacai Chen  * task sp holds a copy of the task stack pointer where the struct pt_regs
270603839bSHuacai Chen  * from exception entry can be found.
280603839bSHuacai Chen  */
290603839bSHuacai Chen 
300603839bSHuacai Chen static inline bool on_irq_stack(int cpu, unsigned long sp)
310603839bSHuacai Chen {
320603839bSHuacai Chen 	unsigned long low = per_cpu(irq_stack, cpu);
330603839bSHuacai Chen 	unsigned long high = low + IRQ_STACK_SIZE;
340603839bSHuacai Chen 
350603839bSHuacai Chen 	return (low <= sp && sp <= high);
360603839bSHuacai Chen }
370603839bSHuacai Chen 
380603839bSHuacai Chen int get_ipi_irq(void);
390603839bSHuacai Chen int get_pmc_irq(void);
400603839bSHuacai Chen int get_timer_irq(void);
410603839bSHuacai Chen void spurious_interrupt(void);
420603839bSHuacai Chen 
430603839bSHuacai Chen #define NR_IRQS_LEGACY 16
440603839bSHuacai Chen 
450603839bSHuacai Chen #define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
460603839bSHuacai Chen void arch_trigger_cpumask_backtrace(const struct cpumask *mask, bool exclude_self);
470603839bSHuacai Chen 
480603839bSHuacai Chen #define MAX_IO_PICS 2
490603839bSHuacai Chen #define NR_IRQS	(64 + (256 * MAX_IO_PICS))
500603839bSHuacai Chen 
512dfded47SJianmin Lv struct acpi_vector_group {
522dfded47SJianmin Lv 	int node;
532dfded47SJianmin Lv 	int pci_segment;
542dfded47SJianmin Lv 	struct irq_domain *parent;
552dfded47SJianmin Lv };
562dfded47SJianmin Lv extern struct acpi_vector_group pch_group[MAX_IO_PICS];
572dfded47SJianmin Lv extern struct acpi_vector_group msi_group[MAX_IO_PICS];
582dfded47SJianmin Lv 
590603839bSHuacai Chen #define CORES_PER_EIO_NODE	4
600603839bSHuacai Chen 
610603839bSHuacai Chen #define LOONGSON_CPU_UART0_VEC		10 /* CPU UART0 */
620603839bSHuacai Chen #define LOONGSON_CPU_THSENS_VEC		14 /* CPU Thsens */
630603839bSHuacai Chen #define LOONGSON_CPU_HT0_VEC		16 /* CPU HT0 irq vector base number */
640603839bSHuacai Chen #define LOONGSON_CPU_HT1_VEC		24 /* CPU HT1 irq vector base number */
650603839bSHuacai Chen 
660603839bSHuacai Chen /* IRQ number definitions */
670603839bSHuacai Chen #define LOONGSON_LPC_IRQ_BASE		0
680603839bSHuacai Chen #define LOONGSON_LPC_LAST_IRQ		(LOONGSON_LPC_IRQ_BASE + 15)
690603839bSHuacai Chen 
700603839bSHuacai Chen #define LOONGSON_CPU_IRQ_BASE		16
710603839bSHuacai Chen #define LOONGSON_CPU_LAST_IRQ		(LOONGSON_CPU_IRQ_BASE + 14)
720603839bSHuacai Chen 
730603839bSHuacai Chen #define LOONGSON_PCH_IRQ_BASE		64
740603839bSHuacai Chen #define LOONGSON_PCH_ACPI_IRQ		(LOONGSON_PCH_IRQ_BASE + 47)
750603839bSHuacai Chen #define LOONGSON_PCH_LAST_IRQ		(LOONGSON_PCH_IRQ_BASE + 64 - 1)
760603839bSHuacai Chen 
770603839bSHuacai Chen #define LOONGSON_MSI_IRQ_BASE		(LOONGSON_PCH_IRQ_BASE + 64)
780603839bSHuacai Chen #define LOONGSON_MSI_LAST_IRQ		(LOONGSON_PCH_IRQ_BASE + 256 - 1)
790603839bSHuacai Chen 
800603839bSHuacai Chen #define GSI_MIN_LPC_IRQ		LOONGSON_LPC_IRQ_BASE
810603839bSHuacai Chen #define GSI_MAX_LPC_IRQ		(LOONGSON_LPC_IRQ_BASE + 16 - 1)
820603839bSHuacai Chen #define GSI_MIN_CPU_IRQ		LOONGSON_CPU_IRQ_BASE
830603839bSHuacai Chen #define GSI_MAX_CPU_IRQ		(LOONGSON_CPU_IRQ_BASE + 48 - 1)
840603839bSHuacai Chen #define GSI_MIN_PCH_IRQ		LOONGSON_PCH_IRQ_BASE
850603839bSHuacai Chen #define GSI_MAX_PCH_IRQ		(LOONGSON_PCH_IRQ_BASE + 256 - 1)
860603839bSHuacai Chen 
870603839bSHuacai Chen extern int find_pch_pic(u32 gsi);
880603839bSHuacai Chen extern int eiointc_get_node(int id);
890603839bSHuacai Chen 
900603839bSHuacai Chen static inline void eiointc_enable(void)
910603839bSHuacai Chen {
920603839bSHuacai Chen 	uint64_t misc;
930603839bSHuacai Chen 
940603839bSHuacai Chen 	misc = iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC);
950603839bSHuacai Chen 	misc |= IOCSR_MISC_FUNC_EXT_IOI_EN;
960603839bSHuacai Chen 	iocsr_write64(misc, LOONGARCH_IOCSR_MISC_FUNC);
970603839bSHuacai Chen }
980603839bSHuacai Chen 
990603839bSHuacai Chen struct acpi_madt_lio_pic;
1000603839bSHuacai Chen struct acpi_madt_eio_pic;
1010603839bSHuacai Chen struct acpi_madt_ht_pic;
1020603839bSHuacai Chen struct acpi_madt_bio_pic;
1030603839bSHuacai Chen struct acpi_madt_msi_pic;
1040603839bSHuacai Chen struct acpi_madt_lpc_pic;
1050603839bSHuacai Chen 
1060603839bSHuacai Chen struct irq_domain *loongarch_cpu_irq_init(void);
1070603839bSHuacai Chen 
1080603839bSHuacai Chen struct irq_domain *liointc_acpi_init(struct irq_domain *parent,
1090603839bSHuacai Chen 					struct acpi_madt_lio_pic *acpi_liointc);
1100603839bSHuacai Chen struct irq_domain *eiointc_acpi_init(struct irq_domain *parent,
1110603839bSHuacai Chen 					struct acpi_madt_eio_pic *acpi_eiointc);
1120603839bSHuacai Chen 
1130603839bSHuacai Chen struct irq_domain *htvec_acpi_init(struct irq_domain *parent,
1140603839bSHuacai Chen 					struct acpi_madt_ht_pic *acpi_htvec);
115ee73f14eSHuacai Chen int pch_lpc_acpi_init(struct irq_domain *parent,
1160603839bSHuacai Chen 					struct acpi_madt_lpc_pic *acpi_pchlpc);
117*02308732SHuacai Chen #if IS_ENABLED(CONFIG_LOONGSON_PCH_MSI)
118*02308732SHuacai Chen int pch_msi_acpi_init(struct irq_domain *parent,
1190603839bSHuacai Chen 					struct acpi_madt_msi_pic *acpi_pchmsi);
120*02308732SHuacai Chen #else
121*02308732SHuacai Chen static inline int pch_msi_acpi_init(struct irq_domain *parent,
122*02308732SHuacai Chen 					struct acpi_madt_msi_pic *acpi_pchmsi)
123*02308732SHuacai Chen {
124*02308732SHuacai Chen 	return 0;
125*02308732SHuacai Chen }
126*02308732SHuacai Chen #endif
127bcdd75c5SHuacai Chen int pch_pic_acpi_init(struct irq_domain *parent,
1280603839bSHuacai Chen 					struct acpi_madt_bio_pic *acpi_pchpic);
129bcdd75c5SHuacai Chen int find_pch_pic(u32 gsi);
130*02308732SHuacai Chen struct fwnode_handle *get_pch_msi_handle(int pci_segment);
1310603839bSHuacai Chen 
1320603839bSHuacai Chen extern struct acpi_madt_lio_pic *acpi_liointc;
1330603839bSHuacai Chen extern struct acpi_madt_eio_pic *acpi_eiointc[MAX_IO_PICS];
1340603839bSHuacai Chen 
1350603839bSHuacai Chen extern struct acpi_madt_ht_pic *acpi_htintc;
1360603839bSHuacai Chen extern struct acpi_madt_lpc_pic *acpi_pchlpc;
1370603839bSHuacai Chen extern struct acpi_madt_msi_pic *acpi_pchmsi[MAX_IO_PICS];
1380603839bSHuacai Chen extern struct acpi_madt_bio_pic *acpi_pchpic[MAX_IO_PICS];
1390603839bSHuacai Chen 
1400603839bSHuacai Chen extern struct irq_domain *cpu_domain;
1410603839bSHuacai Chen extern struct irq_domain *liointc_domain;
142ee73f14eSHuacai Chen extern struct fwnode_handle *pch_lpc_handle;
143bcdd75c5SHuacai Chen extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS];
1440603839bSHuacai Chen 
14546859ac8SHuacai Chen extern irqreturn_t loongson3_ipi_interrupt(int irq, void *dev);
14646859ac8SHuacai Chen 
1470603839bSHuacai Chen #include <asm-generic/irq.h>
1480603839bSHuacai Chen 
1490603839bSHuacai Chen #endif /* _ASM_IRQ_H */
150