162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef __ASM_IRQFLAGS_ARCV2_H
762306a36Sopenharmony_ci#define __ASM_IRQFLAGS_ARCV2_H
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <asm/arcregs.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/* status32 Bits */
1262306a36Sopenharmony_ci#define STATUS_AD_BIT	19   /* Disable Align chk: core supports non-aligned */
1362306a36Sopenharmony_ci#define STATUS_IE_BIT	31
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define STATUS_AD_MASK		(1<<STATUS_AD_BIT)
1662306a36Sopenharmony_ci#define STATUS_IE_MASK		(1<<STATUS_IE_BIT)
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* status32 Bits as encoded/expected by CLRI/SETI */
1962306a36Sopenharmony_ci#define CLRI_STATUS_IE_BIT	4
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define CLRI_STATUS_E_MASK	0xF
2262306a36Sopenharmony_ci#define CLRI_STATUS_IE_MASK	(1 << CLRI_STATUS_IE_BIT)
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define AUX_USER_SP		0x00D
2562306a36Sopenharmony_ci#define AUX_IRQ_CTRL		0x00E
2662306a36Sopenharmony_ci#define AUX_IRQ_ACT		0x043	/* Active Intr across all levels */
2762306a36Sopenharmony_ci#define AUX_IRQ_LVL_PEND	0x200	/* Pending Intr across all levels */
2862306a36Sopenharmony_ci#define AUX_IRQ_HINT		0x201	/* For generating Soft Interrupts */
2962306a36Sopenharmony_ci#define AUX_IRQ_PRIORITY	0x206
3062306a36Sopenharmony_ci#define ICAUSE			0x40a
3162306a36Sopenharmony_ci#define AUX_IRQ_SELECT		0x40b
3262306a36Sopenharmony_ci#define AUX_IRQ_ENABLE		0x40c
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* Was Intr taken in User Mode */
3562306a36Sopenharmony_ci#define AUX_IRQ_ACT_BIT_U	31
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/*
3862306a36Sopenharmony_ci * Hardware supports 16 priorities (0 highest, 15 lowest)
3962306a36Sopenharmony_ci * Linux by default runs at 1, priority 0 reserved for NMI style interrupts
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_ci#define ARCV2_IRQ_DEF_PRIO	1
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/* seed value for status register */
4462306a36Sopenharmony_ci#ifdef CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS
4562306a36Sopenharmony_ci#define __AD_ENB	STATUS_AD_MASK
4662306a36Sopenharmony_ci#else
4762306a36Sopenharmony_ci#define __AD_ENB	0
4862306a36Sopenharmony_ci#endif
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#define ISA_INIT_STATUS_BITS	(STATUS_IE_MASK | __AD_ENB | \
5162306a36Sopenharmony_ci					(ARCV2_IRQ_DEF_PRIO << 1))
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#ifndef __ASSEMBLY__
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/*
5662306a36Sopenharmony_ci * Save IRQ state and disable IRQs
5762306a36Sopenharmony_ci */
5862306a36Sopenharmony_cistatic inline long arch_local_irq_save(void)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	unsigned long flags;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	__asm__ __volatile__("	clri %0	\n" : "=r" (flags) : : "memory");
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	return flags;
6562306a36Sopenharmony_ci}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci/*
6862306a36Sopenharmony_ci * restore saved IRQ state
6962306a36Sopenharmony_ci */
7062306a36Sopenharmony_cistatic inline void arch_local_irq_restore(unsigned long flags)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	__asm__ __volatile__("	seti %0	\n" : : "r" (flags) : "memory");
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci/*
7662306a36Sopenharmony_ci * Unconditionally Enable IRQs
7762306a36Sopenharmony_ci */
7862306a36Sopenharmony_cistatic inline void arch_local_irq_enable(void)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	unsigned int irqact = read_aux_reg(AUX_IRQ_ACT);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	if (irqact & 0xffff)
8362306a36Sopenharmony_ci		write_aux_reg(AUX_IRQ_ACT, irqact & ~0xffff);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	__asm__ __volatile__("	seti	\n" : : : "memory");
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci/*
8962306a36Sopenharmony_ci * Unconditionally Disable IRQs
9062306a36Sopenharmony_ci */
9162306a36Sopenharmony_cistatic inline void arch_local_irq_disable(void)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	__asm__ __volatile__("	clri	\n" : : : "memory");
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/*
9762306a36Sopenharmony_ci * save IRQ state
9862306a36Sopenharmony_ci */
9962306a36Sopenharmony_cistatic inline long arch_local_save_flags(void)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	unsigned long temp;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	__asm__ __volatile__(
10462306a36Sopenharmony_ci	"	lr  %0, [status32]	\n"
10562306a36Sopenharmony_ci	: "=&r"(temp)
10662306a36Sopenharmony_ci	:
10762306a36Sopenharmony_ci	: "memory");
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	/* To be compatible with irq_save()/irq_restore()
11062306a36Sopenharmony_ci	 * encode the irq bits as expected by CLRI/SETI
11162306a36Sopenharmony_ci	 * (this was needed to make CONFIG_TRACE_IRQFLAGS work)
11262306a36Sopenharmony_ci	 */
11362306a36Sopenharmony_ci	temp = (1 << 5) |
11462306a36Sopenharmony_ci		((!!(temp & STATUS_IE_MASK)) << CLRI_STATUS_IE_BIT) |
11562306a36Sopenharmony_ci		((temp >> 1) & CLRI_STATUS_E_MASK);
11662306a36Sopenharmony_ci	return temp;
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci/*
12062306a36Sopenharmony_ci * Query IRQ state
12162306a36Sopenharmony_ci */
12262306a36Sopenharmony_cistatic inline int arch_irqs_disabled_flags(unsigned long flags)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	return !(flags & CLRI_STATUS_IE_MASK);
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistatic inline int arch_irqs_disabled(void)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	return arch_irqs_disabled_flags(arch_local_save_flags());
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic inline void arc_softirq_trigger(int irq)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	write_aux_reg(AUX_IRQ_HINT, irq);
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic inline void arc_softirq_clear(int irq)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	write_aux_reg(AUX_IRQ_HINT, 0);
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci#else
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci#ifdef CONFIG_TRACE_IRQFLAGS
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci.macro TRACE_ASM_IRQ_DISABLE
14762306a36Sopenharmony_ci	bl	trace_hardirqs_off
14862306a36Sopenharmony_ci.endm
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci.macro TRACE_ASM_IRQ_ENABLE
15162306a36Sopenharmony_ci	bl	trace_hardirqs_on
15262306a36Sopenharmony_ci.endm
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci#else
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci.macro TRACE_ASM_IRQ_DISABLE
15762306a36Sopenharmony_ci.endm
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci.macro TRACE_ASM_IRQ_ENABLE
16062306a36Sopenharmony_ci.endm
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci#endif
16362306a36Sopenharmony_ci.macro IRQ_DISABLE  scratch
16462306a36Sopenharmony_ci	clri
16562306a36Sopenharmony_ci	TRACE_ASM_IRQ_DISABLE
16662306a36Sopenharmony_ci.endm
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci.macro IRQ_ENABLE  scratch
16962306a36Sopenharmony_ci	TRACE_ASM_IRQ_ENABLE
17062306a36Sopenharmony_ci	seti
17162306a36Sopenharmony_ci.endm
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci#endif	/* __ASSEMBLY__ */
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci#endif
176