OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [powerpc/] [mpc5xx/] [v2_0/] [src/] [var_intr.c] - Blame information for rev 541

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      var_intr.c
4
//
5
//      PowerPC variant interrupt handlers
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    Bob Koninckx
44
// Contributors: Bob Koninckx
45
// Date:         2001-12-16
46
// Purpose:      PowerPC variant interrupt handlers
47
// Description:  This file contains code to handle interrupt related issues
48
//               on the PowerPC variant.
49
//
50
//####DESCRIPTIONEND####
51
//
52
//==========================================================================
53
 
54
#include <pkgconf/hal.h>
55
#include <cyg/hal/ppc_regs.h>
56
#include <cyg/hal/hal_arbiter.h>
57
 
58
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
59
// Since the interrupt sources do not have fixed vectors on the 5XX
60
// SIU, some arbitration is required.
61
 
62
// More than one interrupt source can be programmed to use the same
63
// vector, so all sources on the same vector have to be queried to
64
// find the one raising the interrupt. This functionality has not been
65
// implemented, but the arbiter functions for each of the SIU
66
// interrupt sources can be called in sequence without change.
67
 
68
 
69
 
70
// Timebase interrupt can be caused by match on either reference A
71
// or B.  
72
// Note: If only one interrupt source is assigned per vector, and only
73
// reference interrupt A or B is used, this ISR is not
74
// necessary. Attach the timerbase reference A or B ISR directly to
75
// the LVLx vector instead.
76
externC cyg_uint32
77
hal_arbitration_isr_tb (CYG_ADDRWORD vector, CYG_ADDRWORD data)
78
{
79
    cyg_uint32 isr_ret;
80
    cyg_uint16 tbscr;
81
 
82
    HAL_READ_UINT16 (CYGARC_REG_IMM_TBSCR, tbscr);
83
    if (tbscr & CYGARC_REG_IMM_TBSCR_REFA) {
84
        isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_TB_A);
85
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN
86
        if (isr_ret & CYG_ISR_HANDLED)
87
#endif
88
            return isr_ret;
89
    }
90
 
91
    if (tbscr & CYGARC_REG_IMM_TBSCR_REFB) {
92
        isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_TB_B);
93
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN
94
        if (isr_ret & CYG_ISR_HANDLED)
95
#endif
96
            return isr_ret;
97
    }
98
 
99
    return 0;
100
}
101
 
102
// Periodic interrupt.
103
// Note: If only one interrupt source is assigned per vector, this ISR
104
// is not necessary. Attach the periodic interrupt ISR directly to the
105
// LVLx vector instead.
106
externC cyg_uint32
107
hal_arbitration_isr_pit (CYG_ADDRWORD vector, CYG_ADDRWORD data)
108
{
109
    cyg_uint32 isr_ret;
110
    cyg_uint16 piscr;
111
 
112
    HAL_READ_UINT16 (CYGARC_REG_IMM_PISCR, piscr);
113
    if (piscr & CYGARC_REG_IMM_PISCR_PS) {
114
        isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_PIT);
115
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN
116
        if (isr_ret & CYG_ISR_HANDLED)
117
#endif
118
            return isr_ret;
119
    }
120
 
121
    return 0;
122
}
123
 
124
// Real time clock interrupts can be caused by the alarm or
125
// once-per-second.
126
// Note: If only one interrupt source is assigned per vector, and only
127
// the alarm or once-per-second interrupt is used, this ISR is not
128
// necessary. Attach the alarm or once-per-second ISR directly to the
129
// LVLx vector instead.
130
externC cyg_uint32
131
hal_arbitration_isr_rtc (CYG_ADDRWORD vector, CYG_ADDRWORD data)
132
{
133
    cyg_uint32 isr_ret;
134
    cyg_uint16 rtcsc;
135
 
136
    HAL_READ_UINT16 (CYGARC_REG_IMM_RTCSC, rtcsc);
137
    if (rtcsc & CYGARC_REG_IMM_RTCSC_SEC) {
138
        isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_RTC_SEC);
139
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN
140
        if (isr_ret & CYG_ISR_HANDLED)
141
#endif
142
            return isr_ret;
143
    }
144
 
145
    if (rtcsc & CYGARC_REG_IMM_RTCSC_ALR) {
146
        isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SIU_RTC_ALR);
147
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN
148
        if (isr_ret & CYG_ISR_HANDLED)
149
#endif
150
            return isr_ret;
151
    }
152
 
153
    return 0;
154
}
155
 
156
// -------------------------------------------------------------------------
157
// IMB3 interrupt decoding
158
//
159
// All interrupt priorities higher than 7 are mapped to SIU level 7. As much
160
// as 15 interrupting devices can be behind this. If more than one IMB3 
161
// device is to be used with priorites in the range 7-31, a special kind of
162
// arbitration isr needs to be set up on SIU level 7. As this is not allways
163
// necessary, it is provided as a configuration option.
164
#ifdef CYGSEM_HAL_POWERPC_MPC5XX_IMB3_ARBITER
165
static hal_mpc5xx_arbitration_data * imb3_data_head = 0;
166
 
167
static cyg_uint32
168
hal_arbitration_imb3(CYG_ADDRWORD vector, CYG_ADDRWORD data)
169
{
170
  hal_mpc5xx_arbitration_data * p =
171
    *(hal_mpc5xx_arbitration_data **)data;
172
 
173
  // Try them all, highest priorities come first. An ISR should return
174
  // CYG_ISR_HANDLED or CYG_ISR_CALL_DSR. An arbitration ISR will 
175
  // strip the CYG_DSR_HANDLED from the ISR result, or returns 0 if
176
  // no ISR could be called. This means that CYG_ISR_HANDLED implies
177
  // that an ISR was called, 0 means that nothing was called.
178
  // Notice that our approach tries to be efficient. We return as soon
179
  // as the first interrupting source is found. This prevents from scanning 
180
  // the complete table for every interrupt. If more than one module 
181
  // requested at the same time, we will re-enter this procedure immediately
182
  // anyway.
183
  while(p)
184
  {
185
    if((p->arbiter(CYGNUM_HAL_INTERRUPT_SIU_LVL7, p->data))&CYG_ISR_HANDLED)
186
      break;
187
    else
188
      p = (hal_mpc5xx_arbitration_data *)(p->reserved);
189
  }
190
 
191
  return 0;
192
}
193
 
194
static hal_mpc5xx_arbitration_data *
195
mpc5xx_insert(hal_mpc5xx_arbitration_data * list,
196
              hal_mpc5xx_arbitration_data * data)
197
{
198
  hal_mpc5xx_arbitration_data    tmp;
199
  hal_mpc5xx_arbitration_data * ptmp = &tmp;
200
  tmp.reserved = list;
201
 
202
  while(ptmp->reserved)
203
  {
204
    if(((hal_mpc5xx_arbitration_data *)(ptmp->reserved))->priority > data->priority)
205
      break;
206
    ptmp = (hal_mpc5xx_arbitration_data *)(ptmp->reserved);
207
  }
208
 
209
  data->reserved = ptmp->reserved;
210
  ptmp->reserved = data;
211
 
212
  return (hal_mpc5xx_arbitration_data *)(tmp.reserved);
213
}
214
 
215
static hal_mpc5xx_arbitration_data *
216
mpc5xx_remove(hal_mpc5xx_arbitration_data * list,
217
              hal_mpc5xx_arbitration_data * data)
218
{
219
  hal_mpc5xx_arbitration_data    tmp;
220
  hal_mpc5xx_arbitration_data * ptmp = &tmp;
221
  tmp.reserved = list;
222
 
223
  while(ptmp->reserved)
224
  {
225
    if(ptmp->reserved == data)
226
      break;
227
 
228
    ptmp = (hal_mpc5xx_arbitration_data *)(ptmp->reserved);
229
  }
230
 
231
  if(ptmp->reserved)
232
    ptmp->reserved = ((hal_mpc5xx_arbitration_data *)(ptmp->reserved))->reserved;
233
 
234
  return (hal_mpc5xx_arbitration_data *)(tmp.reserved);
235
}
236
#endif
237
 
238
externC void
239
hal_mpc5xx_install_arbitration_isr(hal_mpc5xx_arbitration_data * adata)
240
{
241
  CYG_ADDRWORD vector = 2*(1 + adata->priority);
242
  if(vector < CYGNUM_HAL_INTERRUPT_SIU_LVL7)
243
  {
244
    HAL_INTERRUPT_ATTACH(vector, adata->arbiter, adata->data, 0);
245
    HAL_INTERRUPT_UNMASK(vector);
246
  }
247
  else
248
  {
249
#ifdef CYGSEM_HAL_POWERPC_MPC5XX_IMB3_ARBITER  
250
    // Prevent anything from coming through while manipulating
251
    // the list
252
    HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_LVL7);
253
    imb3_data_head = mpc5xx_insert(imb3_data_head, adata);
254
    HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_SIU_LVL7);
255
#else
256
    HAL_INTERRUPT_ATTACH(CYGNUM_HAL_INTERRUPT_SIU_LVL7, adata->arbiter, adata->data, 0);
257
    HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_SIU_LVL7);
258
#endif
259
  }
260
}
261
 
262
externC void
263
hal_mpc5xx_remove_arbitration_isr(hal_mpc5xx_arbitration_data * adata)
264
{
265
#ifdef CYGSEM_HAL_POWERPC_MPC5XX_IMB3_ARBITER  
266
  // Prevent anything from coming through while manipulating the list
267
  HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_SIU_LVL7);
268
  imb3_data_head = mpc5xx_remove(imb3_data_head, adata);
269
  HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_SIU_LVL7);
270
#endif
271
}
272
 
273
// -------------------------------------------------------------------------
274
// Variant specific interrupt setup
275
externC void
276
hal_variant_IRQ_init(void)
277
{
278
#ifdef CYGSEM_HAL_POWERPC_MPC5XX_IMB3_ARBITER  
279
  HAL_INTERRUPT_ATTACH(CYGNUM_HAL_INTERRUPT_SIU_LVL7, hal_arbitration_imb3, &imb3_data_head, 0);
280
  HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_SIU_LVL7);
281
#endif
282
}
283
 
284
// -------------------------------------------------------------------------
285
// EOF var_intr.c

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.