source: rtems/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.c @ c499856

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 8.9 KB
Line 
1/*
2 *
3 *  This file contains the implementation of the function described in irq.h
4 *
5 *  Copyright (c) 2009 embedded brains GmbH.
6 *
7 *  Copyright (C) 1998, 1999 valette@crf.canon.fr
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#include <rtems/system.h>
15#include <bsp.h>
16#include <bsp/irq.h>
17#include <bsp/irq-generic.h>
18#include <bsp/vectors.h>
19#include <bsp/8xx_immap.h>
20#include <bsp/mbx.h>
21#include <bsp/commproc.h>
22
23volatile unsigned int ppc_cached_irq_mask;
24
25/*
26 * Check if symbolic IRQ name is an SIU IRQ
27 */
28static inline int is_siu_irq(const rtems_irq_number irqLine)
29{
30  return (((int) irqLine <= BSP_SIU_IRQ_MAX_OFFSET) &
31    ((int) irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET)
32   );
33}
34
35/*
36 * Check if symbolic IRQ name is an CPM IRQ
37 */
38static inline int is_cpm_irq(const rtems_irq_number irqLine)
39{
40  return (((int) irqLine <= BSP_CPM_IRQ_MAX_OFFSET) &
41    ((int) irqLine >= BSP_CPM_IRQ_LOWEST_OFFSET)
42   );
43}
44
45/*
46 * masks used to mask off the interrupts. For exmaple, for ILVL2, the
47 * mask is used to mask off interrupts ILVL2, IRQ3, ILVL3, ... IRQ7
48 * and ILVL7.
49 *
50 */
51const static unsigned int SIU_IvectMask[BSP_SIU_IRQ_NUMBER] =
52{
53     /* IRQ0      ILVL0       IRQ1        ILVL1  */
54     0x00000000, 0x80000000, 0xC0000000, 0xE0000000,
55
56     /* IRQ2      ILVL2       IRQ3        ILVL3  */
57     0xF0000000, 0xF8000000, 0xFC000000, 0xFE000000,
58
59     /* IRQ4      ILVL4       IRQ5        ILVL5  */
60     0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
61
62     /* IRQ6      ILVL6       IRQ7        ILVL7  */
63     0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000
64};
65
66int BSP_irq_enable_at_cpm(const rtems_irq_number irqLine)
67{
68  int cpm_irq_index;
69
70  if (!is_cpm_irq(irqLine))
71    return 1;
72
73  cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
74  ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << cpm_irq_index);
75
76  return 0;
77}
78
79int BSP_irq_disable_at_cpm(const rtems_irq_number irqLine)
80{
81  int cpm_irq_index;
82
83  if (!is_cpm_irq(irqLine))
84    return 1;
85
86  cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
87  ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << cpm_irq_index);
88
89  return 0;
90}
91
92int BSP_irq_enabled_at_cpm(const rtems_irq_number irqLine)
93{
94  int cpm_irq_index;
95
96  if (!is_cpm_irq(irqLine))
97    return 0;
98
99  cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
100  return (((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr & (1 << cpm_irq_index));
101}
102
103int BSP_irq_enable_at_siu(const rtems_irq_number irqLine)
104{
105  int siu_irq_index;
106
107  if (!is_siu_irq(irqLine))
108    return 1;
109
110  siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET);
111  ppc_cached_irq_mask |= (1 << (31-siu_irq_index));
112  ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
113
114  return 0;
115}
116
117int BSP_irq_disable_at_siu(const rtems_irq_number irqLine)
118{
119  int siu_irq_index;
120
121  if (!is_siu_irq(irqLine))
122    return 1;
123
124  siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET);
125  ppc_cached_irq_mask &= ~(1 << (31-siu_irq_index));
126  ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
127
128  return 0;
129}
130
131int BSP_irq_enabled_at_siu       (const rtems_irq_number irqLine)
132{
133  int siu_irq_index;
134
135  if (!is_siu_irq(irqLine))
136    return 0;
137
138  siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET);
139  return ppc_cached_irq_mask & (1 << (31-siu_irq_index));
140}
141
142#ifdef DISPATCH_HANDLER_STAT
143volatile unsigned int maxLoop = 0;
144#endif
145
146/*
147 * High level IRQ handler called from shared_raw_irq_code_entry
148 */
149int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
150{
151  register unsigned int irq;
152  register unsigned cpmIntr;                  /* boolean */
153  register unsigned oldMask;          /* old siu pic masks */
154  register unsigned msr;
155  register unsigned new_msr;
156#ifdef DISPATCH_HANDLER_STAT
157  unsigned loopCounter;
158#endif
159  /*
160   * Handle decrementer interrupt
161   */
162  if (excNum == ASM_DEC_VECTOR) {
163    _CPU_MSR_GET(msr);
164    new_msr = msr | MSR_EE;
165    _CPU_MSR_SET(new_msr);
166
167    bsp_interrupt_handler_dispatch(BSP_DECREMENTER);
168
169    _CPU_MSR_SET(msr);
170    return 0;
171  }
172  /*
173   * Handle external interrupt generated by SIU on PPC core
174   */
175#ifdef DISPATCH_HANDLER_STAT
176  loopCounter = 0;
177#endif
178  while (1) {
179    if ((ppc_cached_irq_mask & ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend) == 0) {
180#ifdef DISPATCH_HANDLER_STAT
181      if (loopCounter >  maxLoop) maxLoop = loopCounter;
182#endif
183      break;
184    }
185    irq = (((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec >> 26);
186    cpmIntr = (irq == BSP_CPM_INTERRUPT);
187    /*
188     * Disable the interrupt of the same and lower priority.
189     */
190    oldMask = ppc_cached_irq_mask;
191    ppc_cached_irq_mask = oldMask & SIU_IvectMask[irq];
192    ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
193    /*
194     * Acknowledge current interrupt. This has no effect on internal level interrupt.
195     */
196    ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = (1 << (31 - irq));
197
198    if (cpmIntr)  {
199      /*
200       * We will reenable the SIU CPM interrupt to allow nesting of CPM interrupt.
201       * We must before acknowledege the current irq at CPM level to avoid trigerring
202       * the interrupt again.
203       */
204      /*
205       * Acknowledge and get the vector.
206       */
207      ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;
208      irq = (((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr >> 11);
209      /*
210       * transform IRQ to normalized irq table index.
211       */
212      irq += BSP_CPM_IRQ_LOWEST_OFFSET;
213      /*
214       * Unmask CPM interrupt at SIU level
215       */
216      ppc_cached_irq_mask |= (1 << (31 - BSP_CPM_INTERRUPT));
217      ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
218    }
219    /*
220     * make sure, that the masking operations in
221     * ICTL and MSR are executed in order
222     */
223    __asm__ volatile("sync":::"memory");
224
225    _CPU_MSR_GET(msr);
226    new_msr = msr | MSR_EE;
227    _CPU_MSR_SET(new_msr);
228
229    bsp_interrupt_handler_dispatch(irq);
230
231    _CPU_MSR_SET(msr);
232
233    /*
234     * make sure, that the masking operations in
235     * ICTL and MSR are executed in order
236     */
237    __asm__ volatile("sync":::"memory");
238
239    if (cpmIntr)  {
240      irq -= BSP_CPM_IRQ_LOWEST_OFFSET;
241      ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr = (1 << irq);
242    }
243    ppc_cached_irq_mask = oldMask;
244    ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
245#ifdef DISPATCH_HANDLER_STAT
246    ++ loopCounter;
247#endif
248  }
249  return 0;
250}
251
252void BSP_SIU_irq_init(void)
253{
254  /*
255   * In theory we should initialize two registers at least :
256   * SIMASK, SIEL. SIMASK is reset at 0 value meaning no interrupt. But
257   * we should take care that a monitor may have restoreed to another value.
258   * If someone find a reasonnable value for SIEL, AND THE NEED TO CHANGE IT
259   * please feel free to add it here.
260   */
261  ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = 0;
262  ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 0xffff0000;
263  ppc_cached_irq_mask = 0;
264  ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel = ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel;
265}
266
267/*
268 * Initialize CPM interrupt management
269 */
270void
271BSP_CPM_irq_init(void)
272{
273  /*
274   * Initialize the CPM interrupt controller.
275   */
276  ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr =
277#ifdef mpc860
278    (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
279#else
280    (CICR_SCB_SCC2 | CICR_SCA_SCC1) |
281#endif
282    ((BSP_CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
283  ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
284
285  ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
286}
287
288rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number irqnum)
289{
290  if (is_cpm_irq(irqnum)) {
291    /*
292     * Enable interrupt at PIC level
293     */
294    BSP_irq_enable_at_cpm (irqnum);
295  }
296
297  if (is_siu_irq(irqnum)) {
298    /*
299     * Enable interrupt at SIU level
300     */
301    BSP_irq_enable_at_siu (irqnum);
302  }
303
304  return RTEMS_SUCCESSFUL;
305}
306
307rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number irqnum)
308{
309  if (is_cpm_irq(irqnum)) {
310    /*
311     * disable interrupt at PIC level
312     */
313    BSP_irq_disable_at_cpm (irqnum);
314  }
315  if (is_siu_irq(irqnum)) {
316    /*
317     * disable interrupt at OPENPIC level
318     */
319    BSP_irq_disable_at_siu (irqnum);
320  }
321
322  return RTEMS_SUCCESSFUL;
323}
324
325rtems_status_code bsp_interrupt_facility_initialize()
326{
327  /* Install exception handler */
328  if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) {
329    return RTEMS_IO_ERROR;
330  }
331  if (ppc_exc_set_handler( ASM_DEC_VECTOR, C_dispatch_irq_handler)) {
332    return RTEMS_IO_ERROR;
333  }
334
335  /* Initialize the interrupt controller */
336  BSP_SIU_irq_init();
337  BSP_CPM_irq_init();
338
339  /*
340   * Must enable CPM interrupt on SIU. CPM on SIU Interrupt level has already been
341   * set up in BSP_CPM_irq_init.
342   */
343  ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
344  BSP_irq_enable_at_siu (BSP_CPM_INTERRUPT);
345
346  return RTEMS_SUCCESSFUL;
347}
Note: See TracBrowser for help on using the repository browser.