source: rtems/bsps/powerpc/qoriq/irq/irq.c @ 8f8ccee

5
Last change on this file since 8f8ccee was 8f8ccee, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 23, 2018 at 7:50:39 AM

bsps: Move interrupt controller support to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

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