Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/kernel/irq-gt641xx.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* GT641xx IRQ routines.
4
*
5
* Copyright (C) 2007 Yoichi Yuasa <[email protected]>
6
*/
7
#include <linux/hardirq.h>
8
#include <linux/init.h>
9
#include <linux/irq.h>
10
#include <linux/spinlock.h>
11
#include <linux/types.h>
12
13
#include <asm/gt64120.h>
14
15
#define GT641XX_IRQ_TO_BIT(irq) (1U << (irq - GT641XX_IRQ_BASE))
16
17
static DEFINE_RAW_SPINLOCK(gt641xx_irq_lock);
18
19
static void ack_gt641xx_irq(struct irq_data *d)
20
{
21
unsigned long flags;
22
u32 cause;
23
24
raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
25
cause = GT_READ(GT_INTRCAUSE_OFS);
26
cause &= ~GT641XX_IRQ_TO_BIT(d->irq);
27
GT_WRITE(GT_INTRCAUSE_OFS, cause);
28
raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
29
}
30
31
static void mask_gt641xx_irq(struct irq_data *d)
32
{
33
unsigned long flags;
34
u32 mask;
35
36
raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
37
mask = GT_READ(GT_INTRMASK_OFS);
38
mask &= ~GT641XX_IRQ_TO_BIT(d->irq);
39
GT_WRITE(GT_INTRMASK_OFS, mask);
40
raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
41
}
42
43
static void mask_ack_gt641xx_irq(struct irq_data *d)
44
{
45
unsigned long flags;
46
u32 cause, mask;
47
48
raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
49
mask = GT_READ(GT_INTRMASK_OFS);
50
mask &= ~GT641XX_IRQ_TO_BIT(d->irq);
51
GT_WRITE(GT_INTRMASK_OFS, mask);
52
53
cause = GT_READ(GT_INTRCAUSE_OFS);
54
cause &= ~GT641XX_IRQ_TO_BIT(d->irq);
55
GT_WRITE(GT_INTRCAUSE_OFS, cause);
56
raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
57
}
58
59
static void unmask_gt641xx_irq(struct irq_data *d)
60
{
61
unsigned long flags;
62
u32 mask;
63
64
raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
65
mask = GT_READ(GT_INTRMASK_OFS);
66
mask |= GT641XX_IRQ_TO_BIT(d->irq);
67
GT_WRITE(GT_INTRMASK_OFS, mask);
68
raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
69
}
70
71
static struct irq_chip gt641xx_irq_chip = {
72
.name = "GT641xx",
73
.irq_ack = ack_gt641xx_irq,
74
.irq_mask = mask_gt641xx_irq,
75
.irq_mask_ack = mask_ack_gt641xx_irq,
76
.irq_unmask = unmask_gt641xx_irq,
77
};
78
79
void gt641xx_irq_dispatch(void)
80
{
81
u32 cause, mask;
82
int i;
83
84
cause = GT_READ(GT_INTRCAUSE_OFS);
85
mask = GT_READ(GT_INTRMASK_OFS);
86
cause &= mask;
87
88
/*
89
* bit0 : logical or of all the interrupt bits.
90
* bit30: logical or of bits[29:26,20:1].
91
* bit31: logical or of bits[25:1].
92
*/
93
for (i = 1; i < 30; i++) {
94
if (cause & (1U << i)) {
95
do_IRQ(GT641XX_IRQ_BASE + i);
96
return;
97
}
98
}
99
100
atomic_inc(&irq_err_count);
101
}
102
103
void __init gt641xx_irq_init(void)
104
{
105
int i;
106
107
GT_WRITE(GT_INTRMASK_OFS, 0);
108
GT_WRITE(GT_INTRCAUSE_OFS, 0);
109
110
/*
111
* bit0 : logical or of all the interrupt bits.
112
* bit30: logical or of bits[29:26,20:1].
113
* bit31: logical or of bits[25:1].
114
*/
115
for (i = 1; i < 30; i++)
116
irq_set_chip_and_handler(GT641XX_IRQ_BASE + i,
117
&gt641xx_irq_chip, handle_level_irq);
118
}
119
120