source: rtems/bsps/powerpc/qoriq/irq/irq.c

Last change on this file was 19e2dbd, checked in by Vincenzo Calabretta <vincenzo.calabretta@…>, on 04/16/24 at 08:08:25

bsp/qoriq: Include missing processormaskimpl.h

  • Property mode set to 100644
File size: 19.8 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSBSPsPowerPCQorIQ
7 *
8 * @brief Interrupt implementation.
9 */
10
11/*
12 * Copyright (C) 2010, 2017 embedded brains GmbH & Co. KG
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 *    notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 *    notice, this list of conditions and the following disclaimer in the
21 *    documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include <sys/param.h>
37#include <sys/bitset.h>
38
39#include <rtems.h>
40
41#include <libcpu/powerpc-utility.h>
42
43#include <asm/epapr_hcalls.h>
44
45#include <bsp.h>
46#include <bsp/irq-generic.h>
47#include <bsp/vectors.h>
48#include <bsp/utility.h>
49#include <bsp/qoriq.h>
50#include <rtems/score/processormaskimpl.h>
51
52#ifdef RTEMS_SMP
53#include <rtems/score/smpimpl.h>
54#endif
55
56RTEMS_INTERRUPT_LOCK_DEFINE(static, lock, "QorIQ IRQ")
57
58#define SPURIOUS 0xffff
59
60#ifdef QORIQ_IS_HYPERVISOR_GUEST
61
62rtems_status_code bsp_interrupt_set_affinity(
63        rtems_vector_number vector,
64        const Processor_mask *affinity
65)
66{
67        uint32_t config;
68        unsigned int priority;
69        uint32_t destination;
70        uint32_t new_destination;
71        rtems_interrupt_lock_context lock_context;
72
73        new_destination = _Processor_mask_Find_last_set(affinity) - 1;
74
75        rtems_interrupt_lock_acquire(&lock, &lock_context);
76        ev_int_get_config(vector, &config, &priority, &destination);
77        ev_int_set_config(vector, config, priority, new_destination);
78        rtems_interrupt_lock_release(&lock, &lock_context);
79        return RTEMS_SUCCESSFUL;
80}
81
82rtems_status_code bsp_interrupt_get_affinity(
83        rtems_vector_number vector,
84        Processor_mask *affinity
85)
86{
87        uint32_t config;
88        unsigned int priority;
89        uint32_t destination;
90
91        ev_int_get_config(vector, &config, &priority, &destination);
92        _Processor_mask_From_uint32_t(affinity, destination, 0);
93        return RTEMS_SUCCESSFUL;
94}
95
96rtems_status_code bsp_interrupt_get_attributes(
97  rtems_vector_number         vector,
98  rtems_interrupt_attributes *attributes
99)
100{
101  return RTEMS_SUCCESSFUL;
102}
103
104rtems_status_code bsp_interrupt_is_pending(
105  rtems_vector_number vector,
106  bool               *pending
107)
108{
109  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
110  bsp_interrupt_assert(pending != NULL);
111  *pending = false;
112  return RTEMS_UNSATISFIED;
113}
114
115rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
116{
117  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
118  return RTEMS_UNSATISFIED;
119}
120
121#if defined(RTEMS_SMP)
122rtems_status_code bsp_interrupt_raise_on(
123  rtems_vector_number vector,
124  uint32_t            cpu_index
125)
126{
127  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
128  return RTEMS_UNSATISFIED;
129}
130#endif
131
132rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
133{
134  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
135  return RTEMS_UNSATISFIED;
136}
137
138rtems_status_code bsp_interrupt_vector_is_enabled(
139  rtems_vector_number vector,
140  bool               *enabled
141)
142{
143  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
144  bsp_interrupt_assert(enabled != NULL);
145  *enabled = false;
146  return RTEMS_UNSATISFIED;
147}
148
149rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
150{
151        bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
152        ev_int_set_mask(vector, 0);
153        return RTEMS_SUCCESSFUL;
154}
155
156rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
157{
158        bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
159        ev_int_set_mask(vector, 1);
160        return RTEMS_SUCCESSFUL;
161}
162
163void bsp_interrupt_dispatch(uintptr_t exception_number)
164{
165        unsigned int vector;
166
167        if (exception_number == 10) {
168                qoriq_decrementer_dispatch();
169                return;
170        }
171
172#ifdef RTEMS_SMP
173        if (exception_number == 36) {
174                _SMP_Inter_processor_interrupt_handler(_Per_CPU_Get());
175                return;
176        }
177#endif
178
179        /*
180         * This works only if the "has-external-proxy" property is present in the
181         * "epapr,hv-pic" device tree node.
182         */
183        PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_EPR, vector);
184
185        if (vector != SPURIOUS) {
186                uint32_t msr;
187
188                msr = ppc_external_exceptions_enable();
189                bsp_interrupt_handler_dispatch(vector);
190                ppc_external_exceptions_disable(msr);
191
192                ev_int_eoi(vector);
193        } else {
194                bsp_interrupt_handler_default(vector);
195        }
196}
197
198void bsp_interrupt_facility_initialize(void)
199{
200        unsigned int i;
201
202        for (i = 0; i < BSP_INTERRUPT_VECTOR_COUNT; ++i) {
203                uint32_t config;
204                unsigned int priority;
205                uint32_t destination;
206                unsigned int err;
207
208                err = ev_int_get_config(i, &config, &priority, &destination);
209                if (err != EV_SUCCESS)
210                        continue;
211
212                priority = QORIQ_PIC_PRIORITY_DEFAULT;
213
214                ev_int_set_config(i, config, priority, destination);
215        }
216
217        return RTEMS_SUCCESSFUL;
218}
219
220#else /* !QORIQ_IS_HYPERVISOR_GUEST */
221
222#define VPR_MSK BSP_BBIT32(0)
223#define VPR_A BSP_BBIT32(1)
224#define VPR_P BSP_BBIT32(8)
225#define VPR_S BSP_BBIT32(9)
226#define VPR_PRIORITY(val) BSP_BFLD32(val, 12, 15)
227#define VPR_PRIORITY_GET(reg) BSP_BFLD32GET(reg, 12, 15)
228#define VPR_PRIORITY_SET(reg, val) BSP_BFLD32SET(reg, val, 12, 15)
229#define VPR_VECTOR(val) BSP_BFLD32(val, 16, 31)
230#define VPR_VECTOR_GET(reg) BSP_BFLD32GET(reg, 16, 31)
231#define VPR_VECTOR_SET(reg, val) BSP_BFLD32SET(reg, val, 16, 31)
232
233#define GCR_RST BSP_BBIT32(0)
234#define GCR_M BSP_BBIT32(2)
235
236#define SRC_CFG_IDX(i) ((i) - QORIQ_IRQ_EXT_BASE)
237
238static const uint16_t src_cfg_offsets [] = {
239        [SRC_CFG_IDX(QORIQ_IRQ_EXT_0)] = 0x10000 >> 4,
240        [SRC_CFG_IDX(QORIQ_IRQ_EXT_1)] = 0x10020 >> 4,
241        [SRC_CFG_IDX(QORIQ_IRQ_EXT_2)] = 0x10040 >> 4,
242        [SRC_CFG_IDX(QORIQ_IRQ_EXT_3)] = 0x10060 >> 4,
243        [SRC_CFG_IDX(QORIQ_IRQ_EXT_4)] = 0x10080 >> 4,
244        [SRC_CFG_IDX(QORIQ_IRQ_EXT_5)] = 0x100a0 >> 4,
245        [SRC_CFG_IDX(QORIQ_IRQ_EXT_6)] = 0x100c0 >> 4,
246        [SRC_CFG_IDX(QORIQ_IRQ_EXT_7)] = 0x100e0 >> 4,
247        [SRC_CFG_IDX(QORIQ_IRQ_EXT_8)] = 0x10100 >> 4,
248        [SRC_CFG_IDX(QORIQ_IRQ_EXT_9)] = 0x10120 >> 4,
249        [SRC_CFG_IDX(QORIQ_IRQ_EXT_10)] = 0x10140 >> 4,
250        [SRC_CFG_IDX(QORIQ_IRQ_EXT_11)] = 0x10160 >> 4,
251        [SRC_CFG_IDX(QORIQ_IRQ_IPI_0)] = 0x010a0 >> 4,
252        [SRC_CFG_IDX(QORIQ_IRQ_IPI_1)] = 0x010b0 >> 4,
253        [SRC_CFG_IDX(QORIQ_IRQ_IPI_2)] = 0x010c0 >> 4,
254        [SRC_CFG_IDX(QORIQ_IRQ_IPI_3)] = 0x010d0 >> 4,
255        [SRC_CFG_IDX(QORIQ_IRQ_MI_0)] = 0x11600 >> 4,
256        [SRC_CFG_IDX(QORIQ_IRQ_MI_1)] = 0x11620 >> 4,
257        [SRC_CFG_IDX(QORIQ_IRQ_MI_2)] = 0x11640 >> 4,
258        [SRC_CFG_IDX(QORIQ_IRQ_MI_3)] = 0x11660 >> 4,
259        [SRC_CFG_IDX(QORIQ_IRQ_MI_4)] = 0x11680 >> 4,
260        [SRC_CFG_IDX(QORIQ_IRQ_MI_5)] = 0x116a0 >> 4,
261        [SRC_CFG_IDX(QORIQ_IRQ_MI_6)] = 0x116c0 >> 4,
262        [SRC_CFG_IDX(QORIQ_IRQ_MI_7)] = 0x116e0 >> 4,
263        [SRC_CFG_IDX(QORIQ_IRQ_MSI_0)] = 0x11c00 >> 4,
264        [SRC_CFG_IDX(QORIQ_IRQ_MSI_1)] = 0x11c20 >> 4,
265        [SRC_CFG_IDX(QORIQ_IRQ_MSI_2)] = 0x11c40 >> 4,
266        [SRC_CFG_IDX(QORIQ_IRQ_MSI_3)] = 0x11c60 >> 4,
267        [SRC_CFG_IDX(QORIQ_IRQ_MSI_4)] = 0x11c80 >> 4,
268        [SRC_CFG_IDX(QORIQ_IRQ_MSI_5)] = 0x11ca0 >> 4,
269        [SRC_CFG_IDX(QORIQ_IRQ_MSI_6)] = 0x11cc0 >> 4,
270        [SRC_CFG_IDX(QORIQ_IRQ_MSI_7)] = 0x11ce0 >> 4,
271        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_0)] = 0x01120 >> 4,
272        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_1)] = 0x01160 >> 4,
273        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_2)] = 0x011a0 >> 4,
274        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_3)] = 0x011e0 >> 4,
275        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_0)] = 0x02120 >> 4,
276        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_1)] = 0x02160 >> 4,
277        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_2)] = 0x021a0 >> 4,
278        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_3)] = 0x021e0 >> 4
279};
280
281static volatile qoriq_pic_src_cfg *get_src_cfg(rtems_vector_number vector)
282{
283        uint32_t n = MIN(RTEMS_ARRAY_SIZE(qoriq.pic.ii_0), QORIQ_IRQ_EXT_BASE);
284
285        if (vector < n) {
286                return &qoriq.pic.ii_0 [vector];
287        } else if (vector < QORIQ_IRQ_EXT_BASE) {
288                return &qoriq.pic.ii_1 [vector - n];
289        } else {
290                uintptr_t offs = ((uintptr_t)
291                        src_cfg_offsets [vector - QORIQ_IRQ_EXT_BASE]) << 4;
292
293                return (volatile qoriq_pic_src_cfg *) ((uintptr_t) &qoriq.pic + offs);
294        }
295}
296
297static bool pic_is_ipi(rtems_vector_number vector)
298{
299        return (vector - QORIQ_IRQ_IPI_BASE) < 4;
300}
301
302rtems_status_code qoriq_pic_set_priority(
303        rtems_vector_number vector,
304        int new_priority,
305        int *old_priority
306)
307{
308        rtems_status_code sc = RTEMS_SUCCESSFUL;
309        uint32_t old_vpr = 0;
310
311        if (QORIQ_IRQ_IS_MSI(vector)) {
312                return RTEMS_UNSATISFIED;
313        }
314
315        if (bsp_interrupt_is_valid_vector(vector)) {
316                volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
317
318                if (QORIQ_PIC_PRIORITY_IS_VALID(new_priority)) {
319                        rtems_interrupt_lock_context lock_context;
320
321                        rtems_interrupt_lock_acquire(&lock, &lock_context);
322                        old_vpr = src_cfg->vpr;
323                        src_cfg->vpr = VPR_PRIORITY_SET(old_vpr, (uint32_t) new_priority);
324                        rtems_interrupt_lock_release(&lock, &lock_context);
325                } else if (new_priority < 0) {
326                        old_vpr = src_cfg->vpr;
327                } else {
328                        sc = RTEMS_INVALID_PRIORITY;
329                }
330        } else {
331                sc = RTEMS_INVALID_ID;
332        }
333
334        if (old_priority != NULL) {
335                *old_priority = (int) VPR_PRIORITY_GET(old_vpr);
336        }
337
338        return sc;
339}
340
341rtems_status_code qoriq_pic_set_sense_and_polarity(
342  rtems_vector_number vector,
343  qoriq_eirq_sense_and_polarity new_sense_and_polarity,
344  qoriq_eirq_sense_and_polarity *old_sense_and_polarity
345)
346{
347        rtems_status_code sc = RTEMS_SUCCESSFUL;
348        uint32_t old_vpr = 0;
349        volatile qoriq_pic_src_cfg *src_cfg;
350        rtems_interrupt_lock_context lock_context;
351        uint32_t new_p_s = 0;
352
353        if (!QORIQ_IRQ_IS_EXT(vector)) {
354                return RTEMS_UNSATISFIED;
355        }
356
357        if (new_sense_and_polarity == QORIQ_EIRQ_TRIGGER_EDGE_RISING ||
358            new_sense_and_polarity == QORIQ_EIRQ_TRIGGER_LEVEL_HIGH) {
359                new_p_s |= VPR_P;
360        }
361
362        if (new_sense_and_polarity == QORIQ_EIRQ_TRIGGER_LEVEL_HIGH ||
363            new_sense_and_polarity == QORIQ_EIRQ_TRIGGER_LEVEL_LOW) {
364                new_p_s |= VPR_S;
365        }
366
367        src_cfg = get_src_cfg(vector);
368
369        rtems_interrupt_lock_acquire(&lock, &lock_context);
370        old_vpr = src_cfg->vpr;
371        src_cfg->vpr = (old_vpr & ~(VPR_P | VPR_S)) | new_p_s;
372        rtems_interrupt_lock_release(&lock, &lock_context);
373
374        if (old_sense_and_polarity != NULL) {
375                if ((old_vpr & VPR_P) == 0) {
376                        if ((old_vpr & VPR_S) == 0) {
377                                *old_sense_and_polarity =
378                                        QORIQ_EIRQ_TRIGGER_EDGE_FALLING;
379                        } else {
380                                *old_sense_and_polarity =
381                                        QORIQ_EIRQ_TRIGGER_LEVEL_LOW;
382                        }
383                } else {
384                        if ((old_vpr & VPR_S) == 0) {
385                                *old_sense_and_polarity =
386                                        QORIQ_EIRQ_TRIGGER_EDGE_RISING;
387                        } else {
388                                *old_sense_and_polarity =
389                                        QORIQ_EIRQ_TRIGGER_LEVEL_HIGH;
390                        }
391                }
392        }
393
394        return sc;
395}
396
397rtems_status_code bsp_interrupt_set_affinity(
398        rtems_vector_number vector,
399        const Processor_mask *affinity
400)
401{
402        volatile qoriq_pic_src_cfg *src_cfg;
403
404        if (pic_is_ipi(vector)) {
405                return RTEMS_UNSATISFIED;
406        }
407
408        if (QORIQ_IRQ_IS_MSI(vector)) {
409                return RTEMS_UNSATISFIED;
410        }
411
412        src_cfg = get_src_cfg(vector);
413        src_cfg->dr = _Processor_mask_To_uint32_t(affinity, 0);
414        return RTEMS_SUCCESSFUL;
415}
416
417rtems_status_code bsp_interrupt_get_affinity(
418        rtems_vector_number vector,
419        Processor_mask *affinity
420)
421{
422        volatile qoriq_pic_src_cfg *src_cfg;
423
424        if (pic_is_ipi(vector)) {
425                return RTEMS_UNSATISFIED;
426        }
427
428        if (QORIQ_IRQ_IS_MSI(vector)) {
429                return RTEMS_UNSATISFIED;
430        }
431
432        src_cfg = get_src_cfg(vector);
433        _Processor_mask_From_uint32_t(affinity, src_cfg->dr, 0);
434        return RTEMS_SUCCESSFUL;
435}
436
437static rtems_status_code pic_vector_set_mask(
438        rtems_vector_number vector,
439        uint32_t msk
440)
441{
442        volatile qoriq_pic_src_cfg *src_cfg;
443        rtems_interrupt_lock_context lock_context;
444
445        bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
446
447        if (QORIQ_IRQ_IS_MSI(vector)) {
448                return RTEMS_UNSATISFIED;
449        }
450
451        src_cfg = get_src_cfg(vector);
452        rtems_interrupt_lock_acquire(&lock, &lock_context);
453        src_cfg->vpr = (src_cfg->vpr & ~VPR_MSK) | msk;
454        rtems_interrupt_lock_release(&lock, &lock_context);
455        return RTEMS_SUCCESSFUL;
456}
457
458rtems_status_code bsp_interrupt_get_attributes(
459        rtems_vector_number vector,
460        rtems_interrupt_attributes *attributes
461)
462{
463        bool is_ipi = pic_is_ipi(vector);
464        bool is_msi = QORIQ_IRQ_IS_MSI(vector);
465
466        attributes->is_maskable = true;
467        attributes->can_enable = !is_msi;
468        attributes->maybe_enable = !is_msi;
469        attributes->can_disable = !is_msi;
470        attributes->maybe_disable = !is_msi;
471        attributes->cleared_by_acknowledge = true;
472        attributes->can_get_affinity = !(is_ipi || is_msi);
473        attributes->can_set_affinity = !(is_ipi || is_msi);
474        attributes->can_raise = is_ipi;
475        attributes->can_raise_on = is_ipi;
476
477        if (is_msi) {
478                attributes->can_be_triggered_by_message = true;
479                attributes->trigger_signal = RTEMS_INTERRUPT_NO_SIGNAL;
480        }
481
482        return RTEMS_SUCCESSFUL;
483}
484
485rtems_status_code bsp_interrupt_is_pending(
486        rtems_vector_number vector,
487        bool *pending
488)
489{
490        volatile qoriq_pic_src_cfg *src_cfg;
491
492        bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
493        bsp_interrupt_assert(pending != NULL);
494
495        if (QORIQ_IRQ_IS_MSI(vector)) {
496                *pending = false;
497                return RTEMS_SUCCESSFUL;
498        }
499
500        src_cfg = get_src_cfg(vector);
501        *pending = (src_cfg->vpr & VPR_A) != 0;
502        return RTEMS_SUCCESSFUL;
503}
504
505static void raise_on(rtems_vector_number vector, uint32_t cpu_index)
506{
507        rtems_vector_number ipi_index = vector - QORIQ_IRQ_IPI_BASE;
508        qoriq.pic.ipidr[ipi_index].reg = 1U << cpu_index;
509}
510
511rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
512{
513        bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
514
515        if (pic_is_ipi(vector)) {
516                raise_on(vector, rtems_scheduler_get_processor());
517                return RTEMS_SUCCESSFUL;
518        }
519
520        return RTEMS_UNSATISFIED;
521}
522
523#if defined(RTEMS_SMP)
524rtems_status_code bsp_interrupt_raise_on(
525        rtems_vector_number vector,
526        uint32_t cpu_index
527)
528{
529        bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
530
531        if (pic_is_ipi(vector)) {
532                raise_on(vector, cpu_index);
533                return RTEMS_SUCCESSFUL;
534        }
535
536        return RTEMS_UNSATISFIED;
537}
538#endif
539
540rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
541{
542  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
543  return RTEMS_UNSATISFIED;
544}
545
546rtems_status_code bsp_interrupt_vector_is_enabled(
547        rtems_vector_number vector,
548        bool *enabled
549)
550{
551        volatile qoriq_pic_src_cfg *src_cfg;
552
553        bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
554        bsp_interrupt_assert(enabled != NULL);
555
556        if (QORIQ_IRQ_IS_MSI(vector)) {
557                vector = QORIQ_IRQ_MSI_0 + QORIQ_IRQ_MSI_INDEX(vector) / 32;
558        }
559
560        src_cfg = get_src_cfg(vector);
561        *enabled = (src_cfg->vpr & VPR_MSK) == 0;
562        return RTEMS_SUCCESSFUL;
563}
564
565rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
566{
567        return pic_vector_set_mask(vector, 0);
568}
569
570rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
571{
572        return pic_vector_set_mask(vector, VPR_MSK);
573}
574
575void bsp_interrupt_dispatch(uintptr_t exception_number)
576{
577        rtems_vector_number vector = qoriq.pic.iack;
578
579        if (vector != SPURIOUS) {
580                uint32_t msr = ppc_external_exceptions_enable();
581
582                bsp_interrupt_handler_dispatch(vector);
583
584                ppc_external_exceptions_disable(msr);
585
586                qoriq.pic.eoi = 0;
587                qoriq.pic.whoami;
588        } else {
589                bsp_interrupt_handler_default(vector);
590        }
591}
592
593static void pic_reset(void)
594{
595        qoriq.pic.gcr = GCR_RST;
596        while ((qoriq.pic.gcr & GCR_RST) != 0) {
597                /* Wait */
598        }
599}
600
601static void pic_global_timer_init(void)
602{
603        int i = 0;
604
605        qoriq.pic.tcra = 0;
606        qoriq.pic.tcrb = 0;
607
608        for (i = 0; i < 4; ++i) {
609                qoriq.pic.gta [0].bcr = GTBCR_CI;
610                qoriq.pic.gtb [0].bcr = GTBCR_CI;
611        }
612}
613
614void bsp_interrupt_facility_initialize(void)
615{
616        rtems_vector_number i = 0;
617        uint32_t processor_id = ppc_processor_id();
618
619        if (processor_id == 0) {
620                /* Core 0 must do the basic initialization */
621
622                pic_reset();
623
624                for (i = 0; i < QORIQ_INTERRUPT_SOURCE_COUNT; ++i) {
625                        volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(i);
626
627                        src_cfg->vpr = VPR_MSK | VPR_P
628                                | VPR_PRIORITY(QORIQ_PIC_PRIORITY_DEFAULT) | VPR_VECTOR(i);
629
630                        if (!pic_is_ipi(i)) {
631                                src_cfg->dr = 0x1;
632                        }
633                }
634
635                qoriq.pic.mer03 = 0xf;
636                qoriq.pic.mer47 = 0xf;
637                qoriq.pic.svr = SPURIOUS;
638                qoriq.pic.gcr = GCR_M;
639
640                /* Clear shared message signaled interrupts */
641                for (i = 0; i < RTEMS_ARRAY_SIZE(qoriq.pic.msir); ++i) {
642                        (void) qoriq.pic.msir[i].reg;
643                }
644
645                pic_global_timer_init();
646        }
647
648        qoriq.pic.ctpr = 0;
649
650        for (i = 0; i < QORIQ_INTERRUPT_SOURCE_COUNT; ++i) {
651                qoriq.pic.iack;
652                qoriq.pic.eoi = 0;
653                qoriq.pic.whoami;
654        }
655}
656
657typedef __BITSET_DEFINE(pic_msi_bitset, QORIQ_IRQ_MSI_COUNT) pic_msi_bitset;
658
659static pic_msi_bitset pic_msi_available =
660  __BITSET_T_INITIALIZER(__BITSET_FSET(__bitset_words(QORIQ_IRQ_MSI_COUNT)));
661
662
663static uint32_t pic_msi_bitset_to_uint32_t(
664        const pic_msi_bitset *bitset,
665        uint32_t              index
666)
667{
668        long bits = bitset->__bits[index / _BITSET_BITS];
669
670        return (uint32_t) (bits >> (32 * ((index % _BITSET_BITS) / 32)));
671}
672
673static void pic_msi_dispatch(void *arg)
674{
675        uintptr_t reg = (uintptr_t) arg;
676        uint32_t msir = qoriq.pic.msir[reg].reg;
677
678        while (msir != 0) {
679                uint32_t index = 31 - __builtin_clz(msir);
680                const rtems_interrupt_entry *entry;
681
682                msir &= ~(UINT32_C(1) << index);
683                entry = bsp_interrupt_entry_load_first(
684                        QORIQ_IRQ_MSI_VECTOR(32 * reg + index)
685                );
686
687                if (entry != NULL) {
688                        bsp_interrupt_dispatch_entries(entry);
689                }
690        }
691}
692
693static rtems_status_code pic_msi_allocate(rtems_vector_number *vector)
694{
695        pic_msi_bitset *available = &pic_msi_available;
696        long found = __BIT_FFS(QORIQ_IRQ_MSI_COUNT, available);
697        rtems_vector_number index;
698        uint32_t subset;
699
700        if (found == 0) {
701                return RTEMS_UNSATISFIED;
702        }
703
704        index = (rtems_vector_number) found - 1;
705        subset = pic_msi_bitset_to_uint32_t(available, index);
706
707        if (subset == 0xffffffff) {
708                uintptr_t reg = index / 32;
709                rtems_status_code sc;
710
711                sc = rtems_interrupt_handler_install(
712                        QORIQ_IRQ_MSI_0 + reg,
713                        "MSI",
714                        RTEMS_INTERRUPT_UNIQUE,
715                        pic_msi_dispatch,
716                        (void *) reg
717                );
718
719                if (sc != RTEMS_SUCCESSFUL) {
720                        return sc;
721                }
722        }
723
724        __BIT_CLR(QORIQ_IRQ_MSI_COUNT, index, available);
725        *vector = QORIQ_IRQ_MSI_VECTOR(index);
726        return RTEMS_SUCCESSFUL;
727}
728
729static rtems_status_code pic_msi_free(rtems_vector_number vector)
730{
731        pic_msi_bitset *available = &pic_msi_available;
732        rtems_vector_number index = QORIQ_IRQ_MSI_INDEX(vector);
733        uint32_t subset;
734
735        if (__BIT_ISSET(QORIQ_IRQ_MSI_COUNT, index, available)) {
736                return RTEMS_NOT_DEFINED;
737        }
738
739        __BIT_SET(QORIQ_IRQ_MSI_COUNT, index, available);
740        subset = pic_msi_bitset_to_uint32_t(available, index);
741
742        if (subset == 0xffffffff) {
743                uintptr_t reg = index / 32;
744
745                return rtems_interrupt_handler_remove(
746                        QORIQ_IRQ_MSI_0 + reg,
747                        pic_msi_dispatch,
748                        (void *) reg
749                );
750        }
751
752        return RTEMS_SUCCESSFUL;
753}
754
755rtems_status_code qoriq_pic_msi_allocate(rtems_vector_number *vector)
756{
757        rtems_status_code sc;
758
759        if (!bsp_interrupt_is_initialized()) {
760                return RTEMS_INCORRECT_STATE;
761        }
762
763        if (vector == NULL) {
764                return RTEMS_INVALID_ADDRESS;
765        }
766
767        if (rtems_interrupt_is_in_progress()) {
768                return RTEMS_CALLED_FROM_ISR;
769        }
770
771        bsp_interrupt_lock();
772        sc = pic_msi_allocate(vector);
773        bsp_interrupt_unlock();
774        return sc;
775}
776
777rtems_status_code qoriq_pic_msi_free(rtems_vector_number vector)
778{
779        rtems_status_code sc;
780
781        if (!bsp_interrupt_is_initialized()) {
782                return RTEMS_INCORRECT_STATE;
783        }
784
785        if (!QORIQ_IRQ_IS_MSI(vector) ) {
786                return RTEMS_INVALID_ID;
787        }
788
789        if (rtems_interrupt_is_in_progress()) {
790                return RTEMS_CALLED_FROM_ISR;
791        }
792
793        bsp_interrupt_lock();
794        sc = pic_msi_free(vector);
795        bsp_interrupt_unlock();
796        return sc;
797}
798
799rtems_status_code qoriq_pic_msi_map(
800        rtems_vector_number vector,
801        uint64_t *addr,
802        uint32_t *data
803)
804{
805        if (addr == NULL) {
806                return RTEMS_INVALID_ADDRESS;
807        }
808
809        if (data == NULL) {
810                return RTEMS_INVALID_ADDRESS;
811        }
812
813        if (!QORIQ_IRQ_IS_MSI(vector) ) {
814                return RTEMS_INVALID_ID;
815        }
816
817        *addr = (uint64_t)(uintptr_t) &qoriq.pic.msiir;
818        *data = QORIQ_IRQ_MSI_INDEX(vector) << 24;
819        return RTEMS_SUCCESSFUL;
820}
821
822#endif /* QORIQ_IS_HYPERVISOR_GUEST */
Note: See TracBrowser for help on using the repository browser.