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

5
Last change on this file since 90d8567 was 90d8567, checked in by Sebastian Huber <sebastian.huber@…>, on 02/18/16 at 07:36:16

score: Distribute clock tick to all online CPUs

Update #2554.

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup QorIQ
5 *
6 * @brief Interrupt implementation.
7 */
8
9/*
10 * Copyright (c) 2010-2015 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 <bsp.h>
30#include <bsp/irq.h>
31#include <bsp/irq-generic.h>
32#include <bsp/vectors.h>
33#include <bsp/utility.h>
34#include <bsp/qoriq.h>
35
36#define VPR_MSK BSP_BBIT32(0)
37#define VPR_A BSP_BBIT32(1)
38#define VPR_P BSP_BBIT32(8)
39#define VPR_S BSP_BBIT32(9)
40#define VPR_PRIORITY(val) BSP_BFLD32(val, 12, 15)
41#define VPR_PRIORITY_GET(reg) BSP_BFLD32GET(reg, 12, 15)
42#define VPR_PRIORITY_SET(reg, val) BSP_BFLD32SET(reg, val, 12, 15)
43#define VPR_VECTOR(val) BSP_BFLD32(val, 16, 31)
44#define VPR_VECTOR_GET(reg) BSP_BFLD32GET(reg, 16, 31)
45#define VPR_VECTOR_SET(reg, val) BSP_BFLD32SET(reg, val, 16, 31)
46
47#define GCR_RST BSP_BBIT32(0)
48#define GCR_M BSP_BBIT32(2)
49
50#define SPURIOUS 0xffff
51
52RTEMS_INTERRUPT_LOCK_DEFINE(static, lock, "QorIQ IRQ")
53
54#define SRC_CFG_IDX(i) ((i) - QORIQ_IRQ_EXT_BASE)
55
56static const uint16_t src_cfg_offsets [] = {
57        [SRC_CFG_IDX(QORIQ_IRQ_EXT_0)] = 0x10000 >> 4,
58        [SRC_CFG_IDX(QORIQ_IRQ_EXT_1)] = 0x10020 >> 4,
59        [SRC_CFG_IDX(QORIQ_IRQ_EXT_2)] = 0x10040 >> 4,
60        [SRC_CFG_IDX(QORIQ_IRQ_EXT_3)] = 0x10060 >> 4,
61        [SRC_CFG_IDX(QORIQ_IRQ_EXT_4)] = 0x10080 >> 4,
62        [SRC_CFG_IDX(QORIQ_IRQ_EXT_5)] = 0x100a0 >> 4,
63        [SRC_CFG_IDX(QORIQ_IRQ_EXT_6)] = 0x100c0 >> 4,
64        [SRC_CFG_IDX(QORIQ_IRQ_EXT_7)] = 0x100e0 >> 4,
65        [SRC_CFG_IDX(QORIQ_IRQ_EXT_8)] = 0x10100 >> 4,
66        [SRC_CFG_IDX(QORIQ_IRQ_EXT_9)] = 0x10120 >> 4,
67        [SRC_CFG_IDX(QORIQ_IRQ_EXT_10)] = 0x10140 >> 4,
68        [SRC_CFG_IDX(QORIQ_IRQ_EXT_11)] = 0x10160 >> 4,
69        [SRC_CFG_IDX(QORIQ_IRQ_IPI_0)] = 0x010a0 >> 4,
70        [SRC_CFG_IDX(QORIQ_IRQ_IPI_1)] = 0x010b0 >> 4,
71        [SRC_CFG_IDX(QORIQ_IRQ_IPI_2)] = 0x010c0 >> 4,
72        [SRC_CFG_IDX(QORIQ_IRQ_IPI_3)] = 0x010d0 >> 4,
73        [SRC_CFG_IDX(QORIQ_IRQ_MI_0)] = 0x11600 >> 4,
74        [SRC_CFG_IDX(QORIQ_IRQ_MI_1)] = 0x11620 >> 4,
75        [SRC_CFG_IDX(QORIQ_IRQ_MI_2)] = 0x11640 >> 4,
76        [SRC_CFG_IDX(QORIQ_IRQ_MI_3)] = 0x11660 >> 4,
77        [SRC_CFG_IDX(QORIQ_IRQ_MI_4)] = 0x11680 >> 4,
78        [SRC_CFG_IDX(QORIQ_IRQ_MI_5)] = 0x116a0 >> 4,
79        [SRC_CFG_IDX(QORIQ_IRQ_MI_6)] = 0x116c0 >> 4,
80        [SRC_CFG_IDX(QORIQ_IRQ_MI_7)] = 0x116e0 >> 4,
81        [SRC_CFG_IDX(QORIQ_IRQ_MSI_0)] = 0x11c00 >> 4,
82        [SRC_CFG_IDX(QORIQ_IRQ_MSI_1)] = 0x11c20 >> 4,
83        [SRC_CFG_IDX(QORIQ_IRQ_MSI_2)] = 0x11c40 >> 4,
84        [SRC_CFG_IDX(QORIQ_IRQ_MSI_3)] = 0x11c60 >> 4,
85        [SRC_CFG_IDX(QORIQ_IRQ_MSI_4)] = 0x11c80 >> 4,
86        [SRC_CFG_IDX(QORIQ_IRQ_MSI_5)] = 0x11ca0 >> 4,
87        [SRC_CFG_IDX(QORIQ_IRQ_MSI_6)] = 0x11cc0 >> 4,
88        [SRC_CFG_IDX(QORIQ_IRQ_MSI_7)] = 0x11ce0 >> 4,
89        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_0)] = 0x01120 >> 4,
90        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_1)] = 0x01160 >> 4,
91        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_2)] = 0x011a0 >> 4,
92        [SRC_CFG_IDX(QORIQ_IRQ_GT_A_3)] = 0x011e0 >> 4,
93        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_0)] = 0x02120 >> 4,
94        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_1)] = 0x02160 >> 4,
95        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_2)] = 0x021a0 >> 4,
96        [SRC_CFG_IDX(QORIQ_IRQ_GT_B_3)] = 0x021e0 >> 4
97};
98
99static volatile qoriq_pic_src_cfg *get_src_cfg(rtems_vector_number vector)
100{
101        uint32_t n = MIN(RTEMS_ARRAY_SIZE(qoriq.pic.ii_0), QORIQ_IRQ_EXT_BASE);
102
103        if (vector < n) {
104                return &qoriq.pic.ii_0 [vector];
105        } else if (vector < QORIQ_IRQ_EXT_BASE) {
106                return &qoriq.pic.ii_1 [vector - n];
107        } else {
108                uint32_t offs = ((uint32_t)
109                        src_cfg_offsets [vector - QORIQ_IRQ_EXT_BASE]) << 4;
110
111                return (volatile qoriq_pic_src_cfg *) ((uint32_t) &qoriq.pic + offs);
112        }
113}
114
115rtems_status_code qoriq_pic_set_priority(
116        rtems_vector_number vector,
117        int new_priority,
118        int *old_priority
119)
120{
121        rtems_status_code sc = RTEMS_SUCCESSFUL;
122        uint32_t old_vpr = 0;
123
124        if (bsp_interrupt_is_valid_vector(vector)) {
125                volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
126
127                if (QORIQ_PIC_PRIORITY_IS_VALID(new_priority)) {
128                        rtems_interrupt_lock_context lock_context;
129
130                        rtems_interrupt_lock_acquire(&lock, &lock_context);
131                        old_vpr = src_cfg->vpr;
132                        src_cfg->vpr = VPR_PRIORITY_SET(old_vpr, (uint32_t) new_priority);
133                        rtems_interrupt_lock_release(&lock, &lock_context);
134                } else if (new_priority < 0) {
135                        old_vpr = src_cfg->vpr;
136                } else {
137                        sc = RTEMS_INVALID_PRIORITY;
138                }
139        } else {
140                sc = RTEMS_INVALID_ID;
141        }
142
143        if (old_priority != NULL) {
144                *old_priority = (int) VPR_PRIORITY_GET(old_vpr);
145        }
146
147        return sc;
148}
149
150rtems_status_code qoriq_pic_set_affinities(
151        rtems_vector_number vector,
152        uint32_t processor_affinities
153)
154{
155        rtems_status_code sc = RTEMS_SUCCESSFUL;
156
157        if (bsp_interrupt_is_valid_vector(vector)) {
158                volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
159
160                src_cfg->dr = processor_affinities;
161        } else {
162                sc = RTEMS_INVALID_ID;
163        }
164
165        return sc;
166}
167
168rtems_status_code qoriq_pic_set_affinity(
169        rtems_vector_number vector,
170        uint32_t processor_index
171)
172{
173        return qoriq_pic_set_affinities(vector, BSP_BIT32(processor_index));
174}
175
176static rtems_status_code pic_vector_enable(rtems_vector_number vector, uint32_t msk)
177{
178        rtems_status_code sc = RTEMS_SUCCESSFUL;
179
180        if (bsp_interrupt_is_valid_vector(vector)) {
181                volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
182                rtems_interrupt_lock_context lock_context;
183
184                rtems_interrupt_lock_acquire(&lock, &lock_context);
185                src_cfg->vpr = (src_cfg->vpr & ~VPR_MSK) | msk;
186                rtems_interrupt_lock_release(&lock, &lock_context);
187        }
188
189        return sc;
190}
191
192rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
193{
194        return pic_vector_enable(vector, 0);
195}
196
197rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
198{
199        return pic_vector_enable(vector, VPR_MSK);
200}
201
202static void qoriq_interrupt_dispatch(void)
203{
204        rtems_vector_number vector = qoriq.pic.iack;
205
206        if (vector != SPURIOUS) {
207                uint32_t msr = ppc_external_exceptions_enable();
208
209                bsp_interrupt_handler_dispatch(vector);
210
211                ppc_external_exceptions_disable(msr);
212
213                qoriq.pic.eoi = 0;
214                qoriq.pic.whoami;
215        } else {
216                bsp_interrupt_handler_default(vector);
217        }
218}
219
220#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
221static int qoriq_external_exception_handler(BSP_Exception_frame *frame, unsigned exception_number)
222{
223        qoriq_interrupt_dispatch();
224
225        return 0;
226}
227#else
228void bsp_interrupt_dispatch(void)
229{
230        qoriq_interrupt_dispatch();
231}
232#endif
233
234static bool pic_is_ipi(rtems_vector_number vector)
235{
236        return QORIQ_IRQ_IPI_0 <= vector && vector <= QORIQ_IRQ_IPI_3;
237}
238
239static void pic_reset(void)
240{
241        qoriq.pic.gcr = GCR_RST;
242        while ((qoriq.pic.gcr & GCR_RST) != 0) {
243                /* Wait */
244        }
245}
246
247static void pic_global_timer_init(void)
248{
249        int i = 0;
250
251        qoriq.pic.tcra = 0;
252        qoriq.pic.tcrb = 0;
253
254        for (i = 0; i < 4; ++i) {
255                qoriq.pic.gta [0].bcr = GTBCR_CI;
256                qoriq.pic.gtb [0].bcr = GTBCR_CI;
257        }
258}
259
260rtems_status_code bsp_interrupt_facility_initialize(void)
261{
262        rtems_vector_number i = 0;
263        uint32_t processor_id = ppc_processor_id();
264
265#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
266        if (ppc_exc_set_handler(ASM_EXT_VECTOR, qoriq_external_exception_handler)) {
267                return RTEMS_IO_ERROR;
268        }
269#endif
270
271        if (processor_id == 0) {
272                /* Core 0 must do the basic initialization */
273
274                pic_reset();
275
276                for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) {
277                        volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(i);
278
279                        src_cfg->vpr = VPR_MSK | VPR_P | VPR_PRIORITY(1) | VPR_VECTOR(i);
280
281                        if (!pic_is_ipi(i)) {
282                                src_cfg->dr = 0x1;
283                        }
284                }
285
286                qoriq.pic.mer03 = 0xf;
287                qoriq.pic.mer47 = 0xf;
288                qoriq.pic.svr = SPURIOUS;
289                qoriq.pic.gcr = GCR_M;
290
291                pic_global_timer_init();
292        }
293
294        qoriq.pic.ctpr = 0;
295
296        for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) {
297                qoriq.pic.iack;
298                qoriq.pic.eoi = 0;
299                qoriq.pic.whoami;
300        }
301
302        return RTEMS_SUCCESSFUL;
303}
Note: See TracBrowser for help on using the repository browser.