Commit fb9fc0ff authored by Mao Minkai's avatar Mao Minkai Committed by guzitao
Browse files

sw64: add irq handling support

Sunway inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8Y8CY



--------------------------------

Add interrupt handling mechanism for basic SW64 support.

Signed-off-by: default avatarMao Minkai <maominkai@wxiat.com>
Reviewed-by: default avatarHe Sheng <hesheng@wxiat.com>
Signed-off-by: default avatarGu Zitao <guzitao@wxiat.com>
parent a491e203
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_SW64_HARDIRQ_H
#define _ASM_SW64_HARDIRQ_H

void ack_bad_irq(unsigned int irq);
#define ack_bad_irq ack_bad_irq

#include <linux/irq.h>

#define __ARCH_IRQ_STAT
typedef struct {
	u16		__softirq_pending;
	unsigned int	timer_irqs_event;
} ____cacheline_aligned irq_cpustat_t;

DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);

#define inc_irq_stat(member)	this_cpu_inc(irq_stat.member)
#define arch_irq_stat_cpu	arch_irq_stat_cpu
#define arch_irq_stat		arch_irq_stat
extern u64 arch_irq_stat_cpu(unsigned int cpu);
extern u64 arch_irq_stat(void);

#endif /* _ASM_SW64_HARDIRQ_H */
+16 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_SW64_HW_IRQ_H
#define _ASM_SW64_HW_IRQ_H

#include <asm/msi.h>

extern volatile unsigned long irq_err_count;
DECLARE_PER_CPU(unsigned long, irq_pmi_count);

#define ACTUAL_NR_IRQS	NR_IRQS

#ifdef CONFIG_PCI_MSI
typedef unsigned int vector_irq_t[PERCPU_MSI_IRQS];
DECLARE_PER_CPU(vector_irq_t, vector_irq);
#endif
#endif /* _ASM_SW64_HW_IRQ_H */
+31 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_SW64_IRQ_H
#define _ASM_SW64_IRQ_H

/*
 *	arch/sw/include/asm/irq.h
 *
 *	(C) 2012 OSKernel JN
 */

#include <linux/linkage.h>

#define NR_VECTORS_PERCPU	256
#define NR_IRQS_LEGACY		16
#define NR_IRQS			((NR_VECTORS_PERCPU + NR_IRQS_LEGACY) * NR_CPUS)

static inline int irq_canonicalize(int irq)
{
	/*
	 * XXX is this true for all Sw?  The old serial driver
	 * did it this way for years without any complaints, so....
	 */
	return ((irq == 2) ? 9 : irq);
}

struct pt_regs;
extern void (*perf_irq)(unsigned long vector, struct pt_regs *regs);
extern void fixup_irqs(void);
extern void sw64_timer_interrupt(void);

#endif /* _ASM_SW64_IRQ_H */
+48 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * This file contains declarations and inline functions for interfacing
 * with the IRQ handling routines in irq.c.
 */

#ifndef _ASM_SW64_IRQ_IMPL_H
#define _ASM_SW64_IRQ_IMPL_H

#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/profile.h>

#include <asm/sw64io.h>

#define SW64_PCIE0_INT_BASE 17
#define SW64_PCIE0_MSI_BASE 21

#define SW64_PCIE1_INT_BASE 277
#define SW64_PCIE1_MSI_BASE 281

#define RTC_IRQ		8
#define SWI2C_IRQ	14

enum sw64_irq_type {
	INT_IPI		= 1,
	INT_PC0		= 2,
	INT_PC1		= 3,
	INT_INTx	= 5,
	INT_MSI		= 6,
	INT_MT		= 7,
	INT_RTC		= 9,
	INT_FAULT	= 10,
	INT_VT_SERIAL	= 12,
	INT_VT_HOTPLUG	= 13,
	INT_DEV		= 17,
	INT_NMI		= 18,
	INT_LEGACY	= 31,
};

extern struct irqaction timer_irqaction;
extern void init_rtc_irq(irq_handler_t handler);
extern void handle_irq(int irq);
extern void handle_ipi(struct pt_regs *regs);
extern void __init sw64_init_irq(void);
extern irqreturn_t timer_interrupt(int irq, void *dev);

#endif /* _ASM_SW64_IRQ_IMPL_H */
+55 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_SW64_IRQFLAGS_H
#define _ASM_SW64_IRQFLAGS_H

#include <asm/hmcall.h>

#define IPL_MIN		0
#define IPL_MAX		7

#define getipl()		(rdps() & 7)
#define setipl(ipl)		((void) swpipl(ipl))

static inline unsigned long arch_local_save_flags(void)
{
	return rdps();
}

static inline void arch_local_irq_disable(void)
{
	setipl(IPL_MAX);
	barrier();
}

static inline unsigned long arch_local_irq_save(void)
{
	unsigned long flags = swpipl(IPL_MAX);

	barrier();
	return flags;
}

static inline void arch_local_irq_enable(void)
{
	barrier();
	setipl(IPL_MIN);
}

static inline void arch_local_irq_restore(unsigned long flags)
{
	barrier();
	setipl(flags);
	barrier();
}

static inline bool arch_irqs_disabled_flags(unsigned long flags)
{
	return flags > IPL_MIN;
}

static inline bool arch_irqs_disabled(void)
{
	return arch_irqs_disabled_flags(getipl());
}

#endif /* _ASM_SW64_IRQFLAGS_H */
Loading