Skip to content

Commit

Permalink
Loongarch: Support loongarch avec
Browse files Browse the repository at this point in the history
Introduce the advanced extended interrupt controllers. This feature will
allow each core to have 256 independent interrupt vectors and MSI
interrupts can be independently routed to any vector on any CPU.

[ tglx: Fixed up coding style. Made on/offline functions void ]

Co-developed-by: Jianmin Lv <lvjianmin@loongson.cn>
Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
Co-developed-by: Liupu Wang <wangliupu@loongson.cn>
Signed-off-by: Liupu Wang <wangliupu@loongson.cn>
Signed-off-by: Tianyang Zhang <zhangtianyang@loongson.cn>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20240604125026.18745-1-zhangtianyang@loongson.cn
  • Loading branch information
Tianyang Zhang authored and Thomas Gleixner committed Jun 23, 2024
1 parent 986b6ad commit 760d7e7
Show file tree
Hide file tree
Showing 14 changed files with 517 additions and 10 deletions.
1 change: 1 addition & 0 deletions arch/loongarch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ config LOONGARCH
select GENERIC_ENTRY
select GENERIC_GETTIMEOFDAY
select GENERIC_IOREMAP if !ARCH_IOREMAP
select GENERIC_IRQ_MATRIX_ALLOCATOR
select GENERIC_IRQ_MULTI_HANDLER
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
Expand Down
1 change: 1 addition & 0 deletions arch/loongarch/include/asm/cpu-features.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,6 @@
#define cpu_has_guestid cpu_opt(LOONGARCH_CPU_GUESTID)
#define cpu_has_hypervisor cpu_opt(LOONGARCH_CPU_HYPERVISOR)
#define cpu_has_ptw cpu_opt(LOONGARCH_CPU_PTW)
#define cpu_has_avecint cpu_opt(LOONGARCH_CPU_AVECINT)

#endif /* __ASM_CPU_FEATURES_H */
2 changes: 2 additions & 0 deletions arch/loongarch/include/asm/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ enum cpu_type_enum {
#define CPU_FEATURE_GUESTID 24 /* CPU has GuestID feature */
#define CPU_FEATURE_HYPERVISOR 25 /* CPU has hypervisor (running in VM) */
#define CPU_FEATURE_PTW 26 /* CPU has hardware page table walker */
#define CPU_FEATURE_AVECINT 27 /* CPU has avec interrupt */

#define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG)
#define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM)
Expand Down Expand Up @@ -127,5 +128,6 @@ enum cpu_type_enum {
#define LOONGARCH_CPU_GUESTID BIT_ULL(CPU_FEATURE_GUESTID)
#define LOONGARCH_CPU_HYPERVISOR BIT_ULL(CPU_FEATURE_HYPERVISOR)
#define LOONGARCH_CPU_PTW BIT_ULL(CPU_FEATURE_PTW)
#define LOONGARCH_CPU_AVECINT BIT_ULL(CPU_FEATURE_AVECINT)

#endif /* _ASM_CPU_H */
10 changes: 10 additions & 0 deletions arch/loongarch/include/asm/hw_irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@

extern atomic_t irq_err_count;

/*
* 256 vectors Map:
*
* 0 - 15: mapping legacy IPs, e.g. IP0-12.
* 16 - 255: mapping a vector for external IRQ.
*
*/
#define NR_VECTORS 256
#define IRQ_MATRIX_BITS NR_VECTORS
#define NR_LEGACY_VECTORS 16
/*
* interrupt-retrigger: NOP for now. This may not be appropriate for all
* machines, we'll see ...
Expand Down
12 changes: 11 additions & 1 deletion arch/loongarch/include/asm/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ extern struct acpi_vector_group msi_group[MAX_IO_PICS];
#define LOONGSON_LPC_LAST_IRQ (LOONGSON_LPC_IRQ_BASE + 15)

#define LOONGSON_CPU_IRQ_BASE 16
#define LOONGSON_CPU_LAST_IRQ (LOONGSON_CPU_IRQ_BASE + 14)
#define LOONGSON_CPU_LAST_IRQ (LOONGSON_CPU_IRQ_BASE + 15)

#define LOONGSON_PCH_IRQ_BASE 64
#define LOONGSON_PCH_ACPI_IRQ (LOONGSON_PCH_IRQ_BASE + 47)
Expand Down Expand Up @@ -101,6 +101,16 @@ int pch_msi_acpi_init(struct irq_domain *parent,
struct acpi_madt_msi_pic *acpi_pchmsi);
int pch_pic_acpi_init(struct irq_domain *parent,
struct acpi_madt_bio_pic *acpi_pchpic);

#ifdef CONFIG_ACPI
int __init pch_msi_acpi_init_v2(struct irq_domain *parent,
struct acpi_madt_msi_pic *pch_msi_entry);
int __init loongarch_avec_acpi_init(struct irq_domain *parent);
void complete_irq_moving(void);
void loongarch_avec_offline_cpu(unsigned int cpu);
void loongarch_avec_online_cpu(unsigned int cpu);
#endif

int find_pch_pic(u32 gsi);
struct fwnode_handle *get_pch_msi_handle(int pci_segment);

Expand Down
20 changes: 15 additions & 5 deletions arch/loongarch/include/asm/loongarch.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@
#define CPUCFG1_RPLV BIT(23)
#define CPUCFG1_HUGEPG BIT(24)
#define CPUCFG1_CRC32 BIT(25)
#define CPUCFG1_MSGINT BIT(26)

#define LOONGARCH_CPUCFG2 0x2
#define CPUCFG2_FP BIT(0)
Expand Down Expand Up @@ -252,8 +251,8 @@
#define CSR_ESTAT_EXC_WIDTH 6
#define CSR_ESTAT_EXC (_ULCAST_(0x3f) << CSR_ESTAT_EXC_SHIFT)
#define CSR_ESTAT_IS_SHIFT 0
#define CSR_ESTAT_IS_WIDTH 14
#define CSR_ESTAT_IS (_ULCAST_(0x3fff) << CSR_ESTAT_IS_SHIFT)
#define CSR_ESTAT_IS_WIDTH 15
#define CSR_ESTAT_IS (_ULCAST_(0x7fff) << CSR_ESTAT_IS_SHIFT)

#define LOONGARCH_CSR_ERA 0x6 /* ERA */

Expand Down Expand Up @@ -999,10 +998,18 @@
#define CSR_FWPC_SKIP_SHIFT 16
#define CSR_FWPC_SKIP (_ULCAST_(1) << CSR_FWPC_SKIP_SHIFT)

#define LOONGARCH_CSR_IRR0 0xa0
#define LOONGARCH_CSR_IRR1 0xa1
#define LOONGARCH_CSR_IRR2 0xa2
#define LOONGARCH_CSR_IRR3 0xa3
#define LOONGARCH_CSR_IRR_BASE LOONGARCH_CSR_IRR0

#define LOONGARCH_CSR_ILR 0xa4

/*
* CSR_ECFG IM
*/
#define ECFG0_IM 0x00001fff
#define ECFG0_IM 0x00005fff
#define ECFGB_SIP0 0
#define ECFGF_SIP0 (_ULCAST_(1) << ECFGB_SIP0)
#define ECFGB_SIP1 1
Expand Down Expand Up @@ -1045,6 +1052,7 @@
#define IOCSRF_EIODECODE BIT_ULL(9)
#define IOCSRF_FLATMODE BIT_ULL(10)
#define IOCSRF_VM BIT_ULL(11)
#define IOCSRF_AVEC BIT_ULL(15)

#define LOONGARCH_IOCSR_VENDOR 0x10

Expand All @@ -1055,6 +1063,7 @@
#define LOONGARCH_IOCSR_MISC_FUNC 0x420
#define IOCSR_MISC_FUNC_TIMER_RESET BIT_ULL(21)
#define IOCSR_MISC_FUNC_EXT_IOI_EN BIT_ULL(48)
#define IOCSR_MISC_FUNC_AVEC_EN BIT_ULL(51)

#define LOONGARCH_IOCSR_CPUTEMP 0x428

Expand Down Expand Up @@ -1375,9 +1384,10 @@ __BUILD_CSR_OP(tlbidx)
#define INT_TI 11 /* Timer */
#define INT_IPI 12
#define INT_NMI 13
#define INT_AVEC 14

/* ExcCodes corresponding to interrupts */
#define EXCCODE_INT_NUM (INT_NMI + 1)
#define EXCCODE_INT_NUM (INT_AVEC + 1)
#define EXCCODE_INT_START 64
#define EXCCODE_INT_END (EXCCODE_INT_START + EXCCODE_INT_NUM - 1)

Expand Down
2 changes: 2 additions & 0 deletions arch/loongarch/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,11 @@ extern int __cpu_logical_map[NR_CPUS];
#define ACTION_BOOT_CPU 0
#define ACTION_RESCHEDULE 1
#define ACTION_CALL_FUNCTION 2
#define ACTION_CLEAR_VECT 3
#define SMP_BOOT_CPU BIT(ACTION_BOOT_CPU)
#define SMP_RESCHEDULE BIT(ACTION_RESCHEDULE)
#define SMP_CALL_FUNCTION BIT(ACTION_CALL_FUNCTION)
#define SMP_CLEAR_VECT BIT(ACTION_CLEAR_VECT)

struct secondary_data {
unsigned long stack;
Expand Down
3 changes: 2 additions & 1 deletion arch/loongarch/kernel/cpu-probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
elf_hwcap |= HWCAP_LOONGARCH_CRC32;
}


config = read_cpucfg(LOONGARCH_CPUCFG2);
if (config & CPUCFG2_LAM) {
c->options |= LOONGARCH_CPU_LAM;
Expand Down Expand Up @@ -176,6 +175,8 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
c->options |= LOONGARCH_CPU_EIODECODE;
if (config & IOCSRF_VM)
c->options |= LOONGARCH_CPU_HYPERVISOR;
if (config & IOCSRF_AVEC)
c->options |= LOONGARCH_CPU_AVECINT;

config = csr_read32(LOONGARCH_CSR_ASID);
config = (config & CSR_ASID_BIT) >> CSR_ASID_BIT_SHIFT;
Expand Down
5 changes: 5 additions & 0 deletions arch/loongarch/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ static irqreturn_t loongson_ipi_interrupt(int irq, void *dev)
per_cpu(irq_stat, cpu).ipi_irqs[IPI_CALL_FUNCTION]++;
}

if (action & SMP_CLEAR_VECT)
complete_irq_moving();

return IRQ_HANDLED;
}

Expand Down Expand Up @@ -388,6 +391,7 @@ int loongson_cpu_disable(void)
irq_migrate_all_off_this_cpu();
clear_csr_ecfg(ECFG0_IM);
local_irq_restore(flags);
loongarch_avec_offline_cpu(cpu);
local_flush_tlb_all();

return 0;
Expand Down Expand Up @@ -566,6 +570,7 @@ asmlinkage void start_secondary(void)
* early is dangerous.
*/
WARN_ON_ONCE(!irqs_disabled());
loongarch_avec_online_cpu(cpu);
loongson_smp_finish();

cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
Expand Down
2 changes: 1 addition & 1 deletion drivers/irqchip/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ obj-$(CONFIG_LS1X_IRQ) += irq-ls1x.o
obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) += irq-ti-sci-intr.o
obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) += irq-ti-sci-inta.o
obj-$(CONFIG_TI_PRUSS_INTC) += irq-pruss-intc.o
obj-$(CONFIG_IRQ_LOONGARCH_CPU) += irq-loongarch-cpu.o
obj-$(CONFIG_IRQ_LOONGARCH_CPU) += irq-loongarch-cpu.o irq-loongarch-avec.o
obj-$(CONFIG_LOONGSON_LIOINTC) += irq-loongson-liointc.o
obj-$(CONFIG_LOONGSON_EIOINTC) += irq-loongson-eiointc.o
obj-$(CONFIG_LOONGSON_HTPIC) += irq-loongson-htpic.o
Expand Down
Loading

0 comments on commit 760d7e7

Please sign in to comment.