source: rtems/bsps/sparc/leon3/start/eirq.c @ c7b4eca7

Last change on this file since c7b4eca7 was c7b4eca7, checked in by Sebastian Huber <sebastian.huber@…>, on 07/27/21 at 07:58:43

bsps/irq: bsp_interrupt_facility_initialize()

Do not return a status code in bsp_interrupt_facility_initialize() since this
leads to unreachable code in bsp_interrupt_initialize(). Use RTEMS_DEBUG
assertions in bsp_interrupt_facility_initialize() if necessary.

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 *  GRLIB/LEON3 extended interrupt controller
3 *
4 *  Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
5 *
6 *  COPYRIGHT (c) 2011
7 *  Aeroflex Gaisler
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.rtems.org/license/LICENSE.
12 *
13 */
14
15#include <leon.h>
16#include <bsp/irq.h>
17#include <bsp/irq-generic.h>
18
19/* GRLIB extended IRQ controller IRQ number */
20int LEON3_IrqCtrl_EIrq = -1;
21
22/* Initialize Extended Interrupt controller */
23void leon3_ext_irq_init(void)
24{
25  if ( (LEON3_IrqCtrl_Regs->mpstat >> 16) & 0xf ) {
26    /* Extended IRQ controller available */
27    LEON3_IrqCtrl_EIrq = (LEON3_IrqCtrl_Regs->mpstat >> 16) & 0xf;
28  }
29}
30
31bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
32{
33  if (vector == 0) {
34    return false;
35  }
36
37  if (LEON3_IrqCtrl_EIrq > 0) {
38    return vector <= BSP_INTERRUPT_VECTOR_MAX_EXT;
39  }
40
41  return vector <= BSP_INTERRUPT_VECTOR_MAX_STD;
42}
43
44#if defined(RTEMS_SMP)
45Processor_mask leon3_interrupt_affinities[BSP_INTERRUPT_VECTOR_MAX_STD + 1];
46#endif
47
48void bsp_interrupt_facility_initialize(void)
49{
50#if defined(RTEMS_SMP)
51  Processor_mask affinity;
52  size_t i;
53
54  _Processor_mask_From_index(&affinity, rtems_scheduler_get_processor());
55
56  for (i = 0; i < RTEMS_ARRAY_SIZE(leon3_interrupt_affinities); ++i) {
57    leon3_interrupt_affinities[i] = affinity;
58  }
59#endif
60}
61
62rtems_status_code bsp_interrupt_get_attributes(
63  rtems_vector_number         vector,
64  rtems_interrupt_attributes *attributes
65)
66{
67  bool is_standard_interrupt;
68
69  is_standard_interrupt = (vector <= BSP_INTERRUPT_VECTOR_MAX_STD);
70  attributes->is_maskable = (vector != 15);
71  attributes->can_enable = true;
72  attributes->maybe_enable = true;
73  attributes->can_disable = true;
74  attributes->maybe_disable = true;
75  attributes->can_raise = true;
76  attributes->can_raise_on = is_standard_interrupt;
77  attributes->can_clear = true;
78  attributes->cleared_by_acknowledge = true;
79  attributes->can_get_affinity = is_standard_interrupt;
80  attributes->can_set_affinity = is_standard_interrupt;
81  return RTEMS_SUCCESSFUL;
82}
83
84rtems_status_code bsp_interrupt_is_pending(
85  rtems_vector_number vector,
86  bool               *pending
87)
88{
89#if defined(RTEMS_SMP)
90  rtems_interrupt_level level;
91  uint32_t bit;
92
93  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
94  bsp_interrupt_assert(pending != NULL);
95  bit = 1U << vector;
96
97  rtems_interrupt_local_disable(level);
98  *pending = (LEON3_IrqCtrl_Regs->ipend & bit) != 0 ||
99    (LEON3_IrqCtrl_Regs->force[rtems_scheduler_get_processor()] & bit) != 0;
100  rtems_interrupt_local_enable(level);
101  return RTEMS_SUCCESSFUL;
102#else
103  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
104  *pending = !BSP_Is_interrupt_pending(vector);
105  return RTEMS_SUCCESSFUL;
106#endif
107}
108
109rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
110{
111  uint32_t bit;
112
113  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
114  bit = 1U << vector;
115
116  if ( vector <= BSP_INTERRUPT_VECTOR_MAX_STD ) {
117    uint32_t cpu_count;
118    uint32_t cpu_index;
119
120    cpu_count = rtems_scheduler_get_processor_maximum();
121
122    for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
123      LEON3_IrqCtrl_Regs->force[cpu_index] = bit;
124    }
125  } else {
126    rtems_interrupt_lock_context lock_context;
127
128    /*
129     * This is a very dangerous operation and should only be used for test
130     * software.  We may accidentally clear the pending state set by
131     * peripherals with this read-modify-write operation.
132     */
133    LEON3_IRQCTRL_ACQUIRE(&lock_context);
134    LEON3_IrqCtrl_Regs->ipend |= bit;
135    LEON3_IRQCTRL_RELEASE(&lock_context);
136  }
137
138  return RTEMS_SUCCESSFUL;
139}
140
141#if defined(RTEMS_SMP)
142rtems_status_code bsp_interrupt_raise_on(
143  rtems_vector_number vector,
144  uint32_t            cpu_index
145)
146{
147  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
148  bsp_interrupt_assert(cpu_index < rtems_scheduler_get_processor_maximum());
149
150  if ( vector > BSP_INTERRUPT_VECTOR_MAX_STD ) {
151    return RTEMS_UNSATISFIED;
152  }
153
154  LEON3_IrqCtrl_Regs->force[cpu_index] = 1U << vector;
155  return RTEMS_SUCCESSFUL;
156}
157#endif
158
159rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
160{
161  uint32_t bit;
162
163  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
164  bit = 1U << vector;
165
166  LEON3_IrqCtrl_Regs->iclear = bit;
167
168  if (vector <= BSP_INTERRUPT_VECTOR_MAX_STD) {
169    LEON3_IrqCtrl_Regs->force[rtems_scheduler_get_processor()] = bit << 16;
170  }
171
172  return RTEMS_SUCCESSFUL;
173}
174
175rtems_status_code bsp_interrupt_vector_is_enabled(
176  rtems_vector_number vector,
177  bool               *enabled
178)
179{
180  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
181  *enabled =
182    !BSP_Cpu_Is_interrupt_masked(vector, _LEON3_Get_current_processor());
183  return RTEMS_SUCCESSFUL;
184}
185
186#if defined(RTEMS_SMP)
187static void leon3_interrupt_vector_enable(rtems_vector_number vector)
188{
189  uint32_t cpu_index;
190  uint32_t cpu_count;
191  Processor_mask affinity;
192  uint32_t bit;
193  uint32_t unmasked;
194
195  if (vector <= BSP_INTERRUPT_VECTOR_MAX_STD) {
196    affinity = leon3_interrupt_affinities[vector];
197  } else {
198    affinity = leon3_interrupt_affinities[LEON3_IrqCtrl_EIrq];
199  }
200
201  cpu_count = rtems_scheduler_get_processor_maximum();
202  bit = 1U << vector;
203  unmasked = 0;
204
205  for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
206    uint32_t mask;
207
208    mask = LEON3_IrqCtrl_Regs->mask[cpu_index];
209
210    if (_Processor_mask_Is_set(&affinity, cpu_index)) {
211      ++unmasked;
212      mask |= bit;
213    } else {
214      mask &= ~bit;
215    }
216
217    LEON3_IrqCtrl_Regs->mask[cpu_index] = mask;
218  }
219
220  if (unmasked > 1) {
221    LEON3_IrqCtrl_Regs->bcast |= bit;
222  } else {
223    LEON3_IrqCtrl_Regs->bcast &= ~bit;
224  }
225}
226#endif
227
228rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
229{
230#if defined(RTEMS_SMP)
231  rtems_interrupt_lock_context lock_context;
232
233  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
234  LEON3_IRQCTRL_ACQUIRE(&lock_context);
235  leon3_interrupt_vector_enable(vector);
236  LEON3_IRQCTRL_RELEASE(&lock_context);
237#else
238  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
239  BSP_Cpu_Unmask_interrupt(vector, _LEON3_Get_current_processor());
240#endif
241  return RTEMS_SUCCESSFUL;
242}
243
244rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
245{
246#if defined(RTEMS_SMP)
247  rtems_interrupt_lock_context lock_context;
248  uint32_t bit;
249  uint32_t cpu_index;
250  uint32_t cpu_count;
251
252  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
253  bit = 1U << vector;
254  cpu_count = rtems_scheduler_get_processor_maximum();
255
256  LEON3_IRQCTRL_ACQUIRE(&lock_context);
257
258  for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
259    LEON3_IrqCtrl_Regs->mask[cpu_index] &= ~bit;
260  }
261
262  LEON3_IrqCtrl_Regs->bcast &= ~bit;
263
264  LEON3_IRQCTRL_RELEASE(&lock_context);
265#else
266  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
267  BSP_Cpu_Mask_interrupt(vector, _LEON3_Get_current_processor());
268#endif
269  return RTEMS_SUCCESSFUL;
270}
271
272#if defined(RTEMS_SMP)
273rtems_status_code bsp_interrupt_set_affinity(
274  rtems_vector_number vector,
275  const Processor_mask *affinity
276)
277{
278  rtems_interrupt_lock_context lock_context;
279  uint32_t cpu_count;
280  uint32_t cpu_index;
281  uint32_t bit;
282
283  if (vector >= RTEMS_ARRAY_SIZE(leon3_interrupt_affinities)) {
284    return RTEMS_UNSATISFIED;
285  }
286
287  cpu_count = rtems_scheduler_get_processor_maximum();
288  bit = 1U << vector;
289
290  LEON3_IRQCTRL_ACQUIRE(&lock_context);
291  leon3_interrupt_affinities[vector] = *affinity;
292
293  /*
294   * If the interrupt is enabled on at least one processor, then re-enable it
295   * using the new affinity.
296   */
297  for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
298    if ((LEON3_IrqCtrl_Regs->mask[cpu_index] & bit) != 0) {
299      leon3_interrupt_vector_enable(vector);
300      break;
301    }
302  }
303
304  LEON3_IRQCTRL_RELEASE(&lock_context);
305  return RTEMS_SUCCESSFUL;
306}
307
308rtems_status_code bsp_interrupt_get_affinity(
309  rtems_vector_number vector,
310  Processor_mask *affinity
311)
312{
313  if (vector >= RTEMS_ARRAY_SIZE(leon3_interrupt_affinities)) {
314    return RTEMS_UNSATISFIED;
315  }
316
317  *affinity = leon3_interrupt_affinities[vector];
318  return RTEMS_SUCCESSFUL;
319}
320#endif
Note: See TracBrowser for help on using the repository browser.