forked from thesofproject/sof
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterrupt.h
More file actions
182 lines (159 loc) · 4.93 KB
/
interrupt.h
File metadata and controls
182 lines (159 loc) · 4.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright(c) 2018 Intel Corporation. All rights reserved.
*
* Author: Janusz Jankowski <janusz.jankowski@linux.intel.com>
*/
#ifndef __SOF_DRIVERS_INTERRUPT_H__
#define __SOF_DRIVERS_INTERRUPT_H__
#include <arch/drivers/interrupt.h>
#include <platform/drivers/interrupt.h>
#include <sof/lib/cpu.h>
#include <sof/list.h>
#include <sof/sof.h>
#include <sof/spinlock.h>
#include <sof/trace/trace.h>
#include <user/trace.h>
#include <stdbool.h>
#include <stdint.h>
#define trace_irq(__e) trace_event(TRACE_CLASS_IRQ, __e)
#define trace_irq_error(__e, ...) \
trace_error(TRACE_CLASS_IRQ, __e, ##__VA_ARGS__)
/**
* \brief child IRQ descriptor for cascading IRQ controllers.
*/
struct irq_child {
int enable_count[PLATFORM_CORE_COUNT]; /**< IRQ enable counter */
struct list_item list; /**< head for IRQ descriptors,
* sharing this interrupt
*/
};
/**
* \brief interrupt client descriptor
*/
struct irq_desc {
int irq; /**< virtual IRQ number */
void (*handler)(void *arg); /**< interrupt handler function */
void *handler_arg; /**< interrupt handler argument */
uint32_t cpu_mask; /**< a mask of CPUs on which this
* interrupt is enabled
*/
struct list_item irq_list; /**< to link to other irq_desc */
};
/**
* \brief cascading IRQ controller operations.
*/
struct irq_cascade_ops {
void (*mask)(struct irq_desc *desc, uint32_t irq,
unsigned int cpu); /**< mask */
void (*unmask)(struct irq_desc *desc, uint32_t irq,
unsigned int cpu); /**< unmask */
};
/**
* \brief cascading interrupt controller descriptor.
*/
struct irq_cascade_desc {
const char *name; /**< name of the
* controller
*/
int irq_base; /**< first virtual IRQ
* number, assigned to
* this controller
*/
const struct irq_cascade_ops *ops; /**< cascading interrupt
* controller driver
* operations
*/
struct irq_desc desc; /**< the interrupt, that
* this controller is
* generating
*/
struct irq_cascade_desc *next; /**< link to the global
* list of interrupt
* controllers
*/
bool global_mask; /**< the controller
* cannot mask input
* interrupts per core
*/
spinlock_t lock; /**< protect child
* lists, enable and
* child counters
*/
int enable_count[PLATFORM_CORE_COUNT]; /**< enabled child
* interrupt counter
*/
unsigned int num_children[PLATFORM_CORE_COUNT]; /**< number of children
*/
struct irq_child child[PLATFORM_IRQ_CHILDREN]; /**< array of child
* lists - one per
* multiplexed IRQ
*/
};
/* A descriptor for cascading interrupt controller template */
struct irq_cascade_tmpl {
const char *name;
const struct irq_cascade_ops *ops;
int irq;
void (*handler)(void *arg);
bool global_mask;
};
/**
* \brief Cascading interrupt controller root.
*/
struct cascade_root {
spinlock_t lock; /**< locking mechanism */
struct irq_cascade_desc *list; /**< list of child cascade irqs */
int last_irq; /**< last registered cascade irq */
};
static inline struct cascade_root *cascade_root_get(void)
{
return sof_get()->cascade_root;
}
int interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg);
void interrupt_unregister(uint32_t irq, const void *arg);
uint32_t interrupt_enable(uint32_t irq, void *arg);
uint32_t interrupt_disable(uint32_t irq, void *arg);
void platform_interrupt_init(void);
void platform_interrupt_set(uint32_t irq);
void platform_interrupt_clear(uint32_t irq, uint32_t mask);
uint32_t platform_interrupt_get_enabled(void);
void interrupt_mask(uint32_t irq, unsigned int cpu);
void interrupt_unmask(uint32_t irq, unsigned int cpu);
/*
* On platforms, supporting cascading interrupts cascaded interrupt numbers
* are greater than or equal to PLATFORM_IRQ_HW_NUM
*/
#define interrupt_is_dsp_direct(irq) (!PLATFORM_IRQ_CHILDREN || \
irq < PLATFORM_IRQ_HW_NUM)
void interrupt_init(struct sof *sof);
int interrupt_cascade_register(const struct irq_cascade_tmpl *tmpl);
struct irq_cascade_desc *interrupt_get_parent(uint32_t irq);
int interrupt_get_irq(unsigned int irq, const char *cascade);
static inline void interrupt_set(int irq)
{
platform_interrupt_set(irq);
}
static inline void interrupt_clear_mask(int irq, uint32_t mask)
{
platform_interrupt_clear(irq, mask);
}
static inline void interrupt_clear(int irq)
{
interrupt_clear_mask(irq, 1);
}
static inline uint32_t interrupt_global_disable(void)
{
return arch_interrupt_global_disable();
}
static inline void interrupt_global_enable(uint32_t flags)
{
arch_interrupt_global_enable(flags);
}
/* disables all IRQ sources on current core */
#define irq_local_disable(flags) \
(flags = interrupt_global_disable())
/* re-enables IRQ sources on current core */
#define irq_local_enable(flags) \
interrupt_global_enable(flags)
#endif /* __SOF_DRIVERS_INTERRUPT_H__ */