source: rtems/c/src/lib/libbsp/powerpc/qoriq/irq/irq.c @ df62e51

5
Last change on this file since df62e51 was df62e51, checked in by Sebastian Huber <sebastian.huber@…>, on 09/08/17 at 08:11:20

bsp/qoriq: Virtual interrupt controller support

Update #3085.

  • Property mode set to 100644
File size: 9.1 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup QorIQ
5 *
6 * @brief Interrupt implementation.
7 */
8
9/*
10 * Copyright (c) 2010, 2017 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#include <sys/param.h>
24
25#include <rtems.h>
26
27#include <libcpu/powerpc-utility.h>
28
29#include <asm/epapr_hcalls.h>
30
31#include <bsp.h>
32#include <bsp/irq.h>
33#include <bsp/irq-generic.h>
34#include <bsp/vectors.h>
35#include <bsp/utility.h>
36#include <bsp/qoriq.h>
37
38RTEMS_INTERRUPT_LOCK_DEFINE(static, lock, "QorIQ IRQ")
39
40#define SPURIOUS 0xffff
41
42#ifdef QORIQ_IS_HYPERVISOR_GUEST
43
44void bsp_interrupt_set_affinity(
45        rtems_vector_number vector,
46        const Processor_mask *affinity
47)
48{
49        uint32_t config;
50        unsigned int priority;
51        uint32_t destination;
52        uint32_t new_destination;
53        rtems_interrupt_lock_context lock_context;
54
55        new_destination = _Processor_mask_Find_last_set(affinity) - 1;
56
57        rtems_interrupt_lock_acquire(&lock, &lock_context);
58        ev_int_get_config(vector, &config, &priority, &destination);
59        ev_int_set_config(vector, config, priority, new_destination);
60        rtems_interrupt_lock_release(&lock, &lock_context);
61}
62
63void bsp_interrupt_get_affinity(
64        rtems_vector_number vector,
65        Processor_mask *affinity
66)
67{
68        uint32_t config;
69        unsigned int priority;
70        uint32_t destination;
71
72        ev_int_get_config(vector, &config, &priority, &destination);
73        _Processor_mask_From_uint32_t(affinity, destination, 0);
74}
75
76void bsp_interrupt_vector_enable(rtems_vector_number vector)
77{
78        bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
79        ev_int_set_mask(vector, 0);
80}
81
82void bsp_interrupt_vector_disable(rtems_vector_number vector)
83{
84        bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
85        ev_int_set_mask(vector, 1);
86}
87
88void bsp_interrupt_dispatch(void)
89{
90        unsigned int vector;
91
92        ev_int_iack(0, &vector);
93
94        if (vector != SPURIOUS) {
95                uint32_t msr;
96
97                msr = ppc_external_exceptions_enable();
98                bsp_interrupt_handler_dispatch(vector);
99                ppc_external_exceptions_disable(msr);
100
101                ev_int_eoi(vector);
102        } else {
103                bsp_interrupt_handler_default(vector);
104        }
105}
106
107rtems_status_code bsp_interrupt_facility_initialize(void)
108{
109        return RTEMS_SUCCESSFUL;
110}
111
112#else /* !QORIQ_IS_HYPERVISOR_GUEST */
113
114#define VPR_MSK BSP_BBIT32(0)
115#define VPR_A BSP_BBIT32(1)
116#define VPR_P BSP_BBIT32(8)
117#define VPR_S BSP_BBIT32(9)
118#define VPR_PRIORITY(val) BSP_BFLD32(val, 12, 15)
119#define VPR_PRIORITY_GET(reg) BSP_BFLD32GET(reg, 12, 15)
120#define VPR_PRIORITY_SET(reg, val) BSP_BFLD32SET(reg, val, 12, 15)
121#define VPR_VECTOR(val) BSP_BFLD32(val, 16, 31)
122#define VPR_VECTOR_GET(reg) BSP_BFLD32GET(reg, 16, 31)
123#define VPR_VECTOR_SET(reg, val) BSP_BFLD32SET(reg, val, 16, 31)
124
125#define GCR_RST BSP_BBIT32(0)
126#define GCR_M BSP_BBIT32(2)
127
128#define SRC_CFG_IDX(i) ((i) - QORIQ_IRQ_EXT_BASE)
129
130static const uint16_t src_cfg_offsets [] = {
131        [SRC_CFG_IDX(QORIQ_IRQ_EXT_0)] = 0x10000 >> 4,
132        [SRC_CFG_IDX(QORIQ_IRQ_EXT_1)] = 0x10020 >> 4,
133        [SRC_CFG_IDX(QORIQ_IRQ_EXT_2)] = 0x10040 >> 4,
134        [SRC_CFG_IDX(QORIQ_IRQ_EXT_3)] = 0x10060 >> 4,
135        [SRC_CFG_IDX(QORIQ_IRQ_EXT_4)] = 0x10080 >> 4,
136        [SRC_CFG_IDX(QORIQ_IRQ_EXT_5)] = 0x100a0 >> 4,
137        [SRC_CFG_IDX(QORIQ_IRQ_EXT_6)] = 0x100c0 >> 4,
138        [SRC_CFG_IDX(QORIQ_IRQ_EXT_7)] = 0x100e0 >> 4,
139        [SRC_CFG_IDX(QORIQ_IRQ_EXT_8)] = 0x10100 >> 4,
140        [SRC_CFG_IDX(QORIQ_IRQ_EXT_9)] = 0x10120 >> 4,
141        [SRC_CFG_IDX(QORIQ_IRQ_EXT_10)] = 0x10140 >> 4,
142        [SRC_CFG_IDX(QORIQ_IRQ_EXT_11)] = 0x10160 >> 4,
143        [SRC_CFG_IDX(QORIQ_IRQ_IPI_0)] = 0x010a0 >> 4,
144        [SRC_CFG_IDX(QORIQ_IRQ_IPI_1)] = 0x010b0 >> 4,
145        [SRC_CFG_IDX(QORIQ_IRQ_IPI_2)] = 0x010c0 >> 4,
146        [SRC_CFG_IDX(QORIQ_IRQ_IPI_3)] = 0x010d0 >> 4,
147        [SRC_CFG_IDX(QORIQ_IRQ_MI_0)] = 0x11600 >> 4,
148        [SRC_CFG_IDX(QORIQ_IRQ_MI_1)] = 0x11620 >> 4,
149        [SRC_CFG_IDX(QORIQ_IRQ_MI_2)] = 0x11640 >> 4,
150        [SRC_CFG_IDX(QORIQ_IRQ_MI_3)] = 0x11660 >> 4,
151        [SRC_CFG_IDX(QORIQ_IRQ_MI_4)] = 0x11680 >> 4,
152        [SRC_CFG_IDX(QORIQ_IRQ_MI_5)] = 0x116a0 >> 4,
153        [SRC_CFG_IDX(QORIQ_IRQ_MI_6)] = 0x116c0 >> 4,
154        [SRC_CFG_IDX(QORIQ_IRQ_MI_7)] = 0x116e0 >> 4,
155        [SRC_CFG_IDX(QORIQ_IRQ_MSI_0)] = 0x11c00 >> 4,
156        [SRC_CFG_IDX(QORIQ_IRQ_MSI_1)] = 0x11c20 >> 4,
157        [SRC_CFG_IDX(QORIQ_IRQ_MSI_2)] = 0x11c40 >> 4,
158        [SRC_CFG_IDX(QORIQ_IRQ_MSI_3)] = 0x11c60 >> 4,
159        [SRC_CFG_IDX(QORIQ_IRQ_MSI_4)] = 0x11c80 >> 4,
160        [SRC_CFG_IDX(QORIQ_IRQ_MSI_5)] = 0x11ca0 >> 4,
161        [SRC_CFG_IDX(QORIQ_IRQ_MSI_6)] = 0x11cc0 >> 4,
162        [SRC_CFG_IDX(QORIQ_IRQ_MSI_7)] = 0x11ce0 >> 4,
163        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_0)] = 0x01120 >> 4,
164        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_1)] = 0x01160 >> 4,
165        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_2)] = 0x011a0 >> 4,
166        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_3)] = 0x011e0 >> 4,
167        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_0)] = 0x02120 >> 4,
168        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_1)] = 0x02160 >> 4,
169        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_2)] = 0x021a0 >> 4,
170        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_3)] = 0x021e0 >> 4
171};
172
173static volatile qoriq_pic_src_cfg *get_src_cfg(rtems_vector_number vector)
174{
175        uint32_t n = MIN(RTEMS_ARRAY_SIZE(qoriq.pic.ii_0), QORIQ_IRQ_EXT_BASE);
176
177        if (vector < n) {
178                return &qoriq.pic.ii_0 [vector];
179        } else if (vector < QORIQ_IRQ_EXT_BASE) {
180                return &qoriq.pic.ii_1 [vector - n];
181        } else {
182                uintptr_t offs = ((uintptr_t)
183                        src_cfg_offsets [vector - QORIQ_IRQ_EXT_BASE]) << 4;
184
185                return (volatile qoriq_pic_src_cfg *) ((uintptr_t) &qoriq.pic + offs);
186        }
187}
188
189rtems_status_code qoriq_pic_set_priority(
190        rtems_vector_number vector,
191        int new_priority,
192        int *old_priority
193)
194{
195        rtems_status_code sc = RTEMS_SUCCESSFUL;
196        uint32_t old_vpr = 0;
197
198        if (bsp_interrupt_is_valid_vector(vector)) {
199                volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
200
201                if (QORIQ_PIC_PRIORITY_IS_VALID(new_priority)) {
202                        rtems_interrupt_lock_context lock_context;
203
204                        rtems_interrupt_lock_acquire(&lock, &lock_context);
205                        old_vpr = src_cfg->vpr;
206                        src_cfg->vpr = VPR_PRIORITY_SET(old_vpr, (uint32_t) new_priority);
207                        rtems_interrupt_lock_release(&lock, &lock_context);
208                } else if (new_priority < 0) {
209                        old_vpr = src_cfg->vpr;
210                } else {
211                        sc = RTEMS_INVALID_PRIORITY;
212                }
213        } else {
214                sc = RTEMS_INVALID_ID;
215        }
216
217        if (old_priority != NULL) {
218                *old_priority = (int) VPR_PRIORITY_GET(old_vpr);
219        }
220
221        return sc;
222}
223
224void bsp_interrupt_set_affinity(
225        rtems_vector_number vector,
226        const Processor_mask *affinity
227)
228{
229        volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
230
231        src_cfg->dr = _Processor_mask_To_uint32_t(affinity, 0);
232}
233
234void bsp_interrupt_get_affinity(
235        rtems_vector_number vector,
236        Processor_mask *affinity
237)
238{
239        volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
240
241        _Processor_mask_From_uint32_t(affinity, src_cfg->dr, 0);
242}
243
244static void pic_vector_enable(rtems_vector_number vector, uint32_t msk)
245{
246        volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
247        rtems_interrupt_lock_context lock_context;
248
249        bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
250
251        rtems_interrupt_lock_acquire(&lock, &lock_context);
252        src_cfg->vpr = (src_cfg->vpr & ~VPR_MSK) | msk;
253        rtems_interrupt_lock_release(&lock, &lock_context);
254}
255
256void bsp_interrupt_vector_enable(rtems_vector_number vector)
257{
258        pic_vector_enable(vector, 0);
259}
260
261void bsp_interrupt_vector_disable(rtems_vector_number vector)
262{
263        pic_vector_enable(vector, VPR_MSK);
264}
265
266static void qoriq_interrupt_dispatch(void)
267{
268        rtems_vector_number vector = qoriq.pic.iack;
269
270        if (vector != SPURIOUS) {
271                uint32_t msr = ppc_external_exceptions_enable();
272
273                bsp_interrupt_handler_dispatch(vector);
274
275                ppc_external_exceptions_disable(msr);
276
277                qoriq.pic.eoi = 0;
278                qoriq.pic.whoami;
279        } else {
280                bsp_interrupt_handler_default(vector);
281        }
282}
283
284#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
285static int qoriq_external_exception_handler(BSP_Exception_frame *frame, unsigned exception_number)
286{
287        qoriq_interrupt_dispatch();
288
289        return 0;
290}
291#else
292void bsp_interrupt_dispatch(void)
293{
294        qoriq_interrupt_dispatch();
295}
296#endif
297
298static bool pic_is_ipi(rtems_vector_number vector)
299{
300        return QORIQ_IRQ_IPI_0 <= vector && vector <= QORIQ_IRQ_IPI_3;
301}
302
303static void pic_reset(void)
304{
305        qoriq.pic.gcr = GCR_RST;
306        while ((qoriq.pic.gcr & GCR_RST) != 0) {
307                /* Wait */
308        }
309}
310
311static void pic_global_timer_init(void)
312{
313        int i = 0;
314
315        qoriq.pic.tcra = 0;
316        qoriq.pic.tcrb = 0;
317
318        for (i = 0; i < 4; ++i) {
319                qoriq.pic.gta [0].bcr = GTBCR_CI;
320                qoriq.pic.gtb [0].bcr = GTBCR_CI;
321        }
322}
323
324rtems_status_code bsp_interrupt_facility_initialize(void)
325{
326        rtems_vector_number i = 0;
327        uint32_t processor_id = ppc_processor_id();
328
329#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
330        if (ppc_exc_set_handler(ASM_EXT_VECTOR, qoriq_external_exception_handler)) {
331                return RTEMS_IO_ERROR;
332        }
333#endif
334
335        if (processor_id == 0) {
336                /* Core 0 must do the basic initialization */
337
338                pic_reset();
339
340                for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) {
341                        volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(i);
342
343                        src_cfg->vpr = VPR_MSK | VPR_P | VPR_PRIORITY(1) | VPR_VECTOR(i);
344
345                        if (!pic_is_ipi(i)) {
346                                src_cfg->dr = 0x1;
347                        }
348                }
349
350                qoriq.pic.mer03 = 0xf;
351                qoriq.pic.mer47 = 0xf;
352                qoriq.pic.svr = SPURIOUS;
353                qoriq.pic.gcr = GCR_M;
354
355                pic_global_timer_init();
356        }
357
358        qoriq.pic.ctpr = 0;
359
360        for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) {
361                qoriq.pic.iack;
362                qoriq.pic.eoi = 0;
363                qoriq.pic.whoami;
364        }
365
366        return RTEMS_SUCCESSFUL;
367}
368
369#endif /* QORIQ_IS_HYPERVISOR_GUEST */
Note: See TracBrowser for help on using the repository browser.