source: rtems/c/src/lib/libbsp/powerpc/ep1a/console/rsPMCQ1.c @ e160e41

4.115
Last change on this file since e160e41 was e160e41, checked in by Joel Sherrill <joel.sherrill@…>, on 10/09/14 at 20:15:55

powerpc/ep1a: Remove if 0 sections

There may be useful nuggets for debug and alternate configurations
in this code. There may be methods directly called by the application
which are beyond normal APIs. We have no way of knowing this based
on the comments in these files. There were no public prototypes
so the routines and code in question should have be unused private
methods.

These will always be in the source code control system as a deletion.
If some of the code is needed, justify it and provide a patch to restore
it along with a prototype in a public place if needed and a better name.

  • Property mode set to 100644
File size: 11.1 KB
Line 
1/* rsPMCQ1.c - Radstone PMCQ1 Common Initialisation Code
2 *
3 * Copyright 2000 Radstone Technology
4 *
5 * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
6 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
7 * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
8 * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
9 *
10 * You are hereby granted permission to use, copy, modify, and distribute
11 * this file, provided that this notice, plus the above copyright notice
12 * and disclaimer, appears in all copies. Radstone Technology will provide
13 * no support for this code.
14 *
15 *  COPYRIGHT (c) 2005.
16 *  On-Line Applications Research Corporation (OAR).
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
24/*
25DESCRIPTION
26These functions are responsible for scanning for PMCQ1's and setting up
27the Motorola MC68360's if present.
28
29USAGE
30call rsPMCQ1Init() to perform ba  sic initialisation of the PMCQ1's.
31*/
32
33/* includes */
34#include <libcpu/io.h>
35#include <bsp/irq.h>
36#include <stdlib.h>
37#include <rtems/bspIo.h>
38#include <bsp/pci.h>
39#include <bsp.h>
40#include "rsPMCQ1.h"
41#include "m68360.h"
42
43/* defines */
44#if 1
45#define DEBUG_360
46#endif
47
48/* Local data */
49PPMCQ1BoardData         pmcq1BoardData = NULL;
50
51static unsigned char rsPMCQ1Initialized = FALSE;
52
53/* forward declarations */
54
55static void MsDelay(void)
56{
57  printk(".");
58}
59
60static void write8( int addr, int data ){
61  out_8((void *)addr, (unsigned char)data);
62}
63
64static void write16( int addr, int data ) {
65  out_be16((void *)addr, (short)data );
66}
67
68static void write32( int addr, int data ) {
69  out_be32((unsigned int *)addr, data );
70}
71
72static void rsPMCQ1_scc_nullFunc(void) {}
73
74/*******************************************************************************
75* rsPMCQ1Int - handle a PMCQ1 interrupt
76*
77* This routine gets called when the QUICC or MA causes
78* an interrupt.
79*
80* RETURNS: NONE.
81*/
82
83static void rsPMCQ1Int( void *ptr )
84{
85  unsigned long   status;
86  unsigned long   status1;
87  unsigned long   mask;
88  uint32_t        data;
89  PPMCQ1BoardData boardData = ptr;
90
91  status = PMCQ1_Read_EPLD(boardData->baseaddr, PMCQ1_INT_STATUS );
92  mask   = PMCQ1_Read_EPLD(boardData->baseaddr, PMCQ1_INT_MASK );
93
94  if (((mask & PMCQ1_INT_MASK_QUICC) == 0) && (status & PMCQ1_INT_STATUS_QUICC))
95  {
96    /* If there is a handler call it otherwise mask the interrupt */
97    if (boardData->quiccInt) {
98      boardData->quiccInt(boardData->quiccArg);
99    } else {
100      *(volatile unsigned long *)(boardData->baseaddr + PMCQ1_INT_MASK) |= PMCQ1_INT_MASK_QUICC;
101    }
102  }
103
104  if (((mask & PMCQ1_INT_MASK_MA) == 0) && (status & PMCQ1_INT_STATUS_MA))
105  {
106    /* If there is a handler call it otherwise mask the interrupt */
107    if (boardData->maInt) {
108      boardData->maInt(boardData->maArg);
109
110      data = PMCQ1_Read_EPLD(boardData->baseaddr, PMCQ1_INT_STATUS );
111      data &= (~PMCQ1_INT_STATUS_MA);
112      PMCQ1_Write_EPLD(boardData->baseaddr, PMCQ1_INT_STATUS, data );
113
114    } else {
115     *(volatile unsigned long *)(boardData->baseaddr + PMCQ1_INT_MASK) |= PMCQ1_INT_MASK_MA;
116    }
117  }
118
119  RTEMS_COMPILER_MEMORY_BARRIER();
120
121  /* Clear Interrupt on QSPAN */
122  *(volatile unsigned long *)(boardData->bridgeaddr + 0x600) = 0x00001000;
123
124  /* read back the status register to ensure that the pci write has completed */
125  status1 = *(volatile unsigned long *)(boardData->bridgeaddr + 0x600);
126  (void) status1;  /* avoid set but not used warning */
127  RTEMS_COMPILER_MEMORY_BARRIER();
128
129}
130
131
132/*******************************************************************************
133*
134* rsPMCQ1MaIntConnect - connect a MiniAce interrupt routine
135*
136* This routine is called to connect a MiniAce interrupt handler
137* upto a PMCQ1.
138*
139* RETURNS: OK if PMCQ1 found, ERROR if not.
140*/
141
142unsigned int rsPMCQ1MaIntConnect (
143    unsigned long       busNo,  /* Pci Bus number of PMCQ1 */
144    unsigned long       slotNo, /* Pci Slot number of PMCQ1 */
145    unsigned long       funcNo, /* Pci Function number of PMCQ1 */
146    FUNCTION_PTR        routine,/* interrupt routine */
147    uintptr_t           arg     /* argument to pass to interrupt routine */
148)
149{
150  PPMCQ1BoardData boardData;
151  uint32_t        data;
152  unsigned int    status = RTEMS_IO_ERROR;
153
154  for (boardData = pmcq1BoardData; boardData; boardData = boardData->pNext)
155  {
156    if ((boardData->busNo == busNo) && (boardData->slotNo == slotNo) &&
157        (boardData->funcNo == funcNo))
158    {
159      boardData->maInt = routine;
160      boardData->maArg = arg;
161
162      data  = PMCQ1_Read_EPLD(boardData->baseaddr, PMCQ1_INT_MASK );
163      data &= (~PMCQ1_INT_MASK_MA);
164      PMCQ1_Write_EPLD(boardData->baseaddr, PMCQ1_INT_MASK, data );
165
166      data = PMCQ1_Read_EPLD(boardData->baseaddr, PMCQ1_INT_STATUS );
167      data &= (~PMCQ1_INT_STATUS_MA);
168      PMCQ1_Write_EPLD(boardData->baseaddr, PMCQ1_INT_STATUS, data );
169
170      status = RTEMS_SUCCESSFUL;
171      break;
172    }
173  }
174
175  return (status);
176}
177
178/*******************************************************************************
179*
180* rsPMCQ1QuiccIntConnect - connect a Quicc interrupt routine
181*
182* This routine is called to connect a Quicc interrupt handler
183* upto a PMCQ1.
184*
185* RETURNS: OK if PMCQ1 found, ERROR if not.
186*/
187unsigned int rsPMCQ1QuiccIntConnect(
188    unsigned long       busNo,  /* Pci Bus number of PMCQ1 */
189    unsigned long       slotNo, /* Pci Slot number of PMCQ1 */
190    unsigned long       funcNo, /* Pci Function number of PMCQ1 */
191    FUNCTION_PTR        routine,/* interrupt routine */
192    uintptr_t           arg     /* argument to pass to interrupt routine */
193)
194{
195  PPMCQ1BoardData boardData;
196  unsigned int status = RTEMS_IO_ERROR;
197
198  for (boardData = pmcq1BoardData; boardData; boardData = boardData->pNext)
199  {
200    if ((boardData->busNo == busNo) && (boardData->slotNo == slotNo) &&
201        (boardData->funcNo == funcNo))
202    {
203      boardData->quiccInt = routine;
204      boardData->quiccArg = arg;
205      status = RTEMS_SUCCESSFUL;
206      break;
207    }
208  }
209  return (status);
210}
211
212/*******************************************************************************
213*
214* rsPMCQ1Init - initialize the PMCQ1's
215*
216* This routine is called to initialize the PCI card to a quiescent state.
217*
218* RETURNS: OK if PMCQ1 found, ERROR if not.
219*/
220
221unsigned int rsPMCQ1Init(void)
222{
223  int busNo;
224  int slotNo;
225  uint32_t baseaddr = 0;
226  uint32_t bridgeaddr = 0;
227  unsigned long pbti0_ctl;
228  int i;
229  unsigned char int_vector;
230  int fun;
231  uint32_t temp;
232  PPMCQ1BoardData       boardData;
233  rtems_irq_connect_data IrqData = {
234    .name   = 0,
235    .hdl    = rsPMCQ1Int,
236    .handle = NULL,
237    .on     = (rtems_irq_enable) rsPMCQ1_scc_nullFunc,
238    .off    = (rtems_irq_disable) rsPMCQ1_scc_nullFunc,
239    .isOn   = (rtems_irq_is_enabled) rsPMCQ1_scc_nullFunc,
240  };
241
242  if (rsPMCQ1Initialized)
243  {
244    return RTEMS_SUCCESSFUL;
245  }
246  for (i=0;;i++){
247    if ( pci_find_device(PCI_VEN_ID_RADSTONE, PCI_DEV_ID_PMCQ1, i, &busNo, &slotNo, &fun) != 0 )
248      break;
249
250    pci_read_config_dword(busNo, slotNo, 0, PCI_BASE_ADDRESS_2, &baseaddr);
251    pci_read_config_dword(busNo, slotNo, 0, PCI_BASE_ADDRESS_0, &bridgeaddr);
252#ifdef DEBUG_360
253  printk("PMCQ1 baseaddr 0x%08x bridgeaddr 0x%08x\n", baseaddr, bridgeaddr );
254#endif
255
256    /* Set function code to normal mode and enable window */
257    pbti0_ctl = *(unsigned long *)(bridgeaddr + 0x100) & 0xff0fffff;
258    eieio();
259    *(unsigned long *)(bridgeaddr + 0x100) = pbti0_ctl | 0x00500080;
260    eieio();
261
262    /* Assert QBUS reset */
263    *(unsigned long *)(bridgeaddr + 0x800) |= 0x00000080;
264    eieio();
265
266    /*
267     * Hold QBus in reset for 1ms
268     */
269    MsDelay();
270
271    /* Take QBUS out of reset */
272    *(unsigned long *)(bridgeaddr + 0x800) &= ~0x00000080;
273    eieio();
274
275    MsDelay();
276
277    /* If a QUICC is fitted initialise it */
278    if (PMCQ1_Read_EPLD(baseaddr, PMCQ1_BUILD_OPTION) & PMCQ1_QUICC_FITTED)
279    {
280#ifdef DEBUG_360
281  printk(" Found QUICC busNo %d slotNo %d\n", busNo, slotNo);
282#endif
283
284      /* Initialise MBAR (must use function code of 7) */
285      *(unsigned long *)(bridgeaddr + 0x100) = pbti0_ctl | 0x00700080;
286      eieio();
287
288      /* place internal 8K SRAM and registers at address 0x0 */
289      *(unsigned long *)(baseaddr + Q1_360_MBAR) = 0x1;
290      eieio();
291
292      /* Set function code to normal mode */
293      *(unsigned long *)(bridgeaddr + 0x100) = pbti0_ctl | 0x00500080;
294      eieio();
295
296      /* Disable the SWT and perform basic initialisation */
297      write8(baseaddr+Q1_360_SIM_SYPCR,0);
298      eieio();
299
300      write32(baseaddr+Q1_360_SIM_MCR,0xa0001029);
301      write16(baseaddr+Q1_360_SIM_PICR,0);
302      write16(baseaddr+Q1_360_SIM_PITR,0);
303
304      write16(baseaddr+Q1_360_CPM_ICCR,0x770);
305      write16(baseaddr+Q1_360_CPM_SDCR,0x770);
306      write32(baseaddr+Q1_360_CPM_CICR,0x00e49f00);
307      write16(baseaddr+Q1_360_SIM_PEPAR,0x2080);
308      eieio();
309
310      /* Enable SRAM */
311      write32(baseaddr+Q1_360_SIM_GMR,0x00001000);  /* external master wait state */
312      eieio();
313      write32(baseaddr+Q1_360_SIM_OR0,0x1ff00000);  /*| MEMC_OR_FC*/
314      eieio();
315      write32(baseaddr+Q1_360_SIM_BR0,0);
316      eieio();
317      write32(baseaddr+Q1_360_SIM_OR1,(0x5ff00000 | 0x00000780));  /*| MEMC_OR_FC*/
318      eieio();
319      write32(baseaddr+Q1_360_SIM_BR1,(0x00000040 | 0x00000001 | 0x00200280) );
320      eieio();
321    }
322
323    /*
324     * If a second PCI window is present then make it opposite
325     * endian to simplify 1553 integration.
326     */
327    pci_read_config_dword(busNo, slotNo, 0, PCI_BASE_ADDRESS_3, &temp);
328    if (temp) {
329      *(unsigned long *)(bridgeaddr + 0x110) |= 0x00500880;
330    }
331
332    /*
333     * Create descriptor structure for this card
334     */
335    if ((boardData = malloc(sizeof(struct _PMCQ1BoardData))) == NULL)
336    {
337      printk("Error Unable to allocate memory for _PMCQ1BoardData\n");
338      return(RTEMS_IO_ERROR);
339    }
340
341    boardData->pNext = pmcq1BoardData;
342    boardData->busNo = busNo;
343    boardData->slotNo = slotNo;
344    boardData->funcNo = 0;
345    boardData->baseaddr = baseaddr;
346    boardData->bridgeaddr = bridgeaddr;
347    boardData->quiccInt = NULL;
348    boardData->maInt = NULL;
349    pmcq1BoardData = boardData;
350    mc68360_scc_create_chip( boardData, int_vector );
351
352    /*
353     * Connect PMCQ1 interrupt handler.
354     */
355    pci_read_config_byte(busNo, slotNo, 0, 0x3c, &int_vector);
356#ifdef DEBUG_360
357    printk("PMCQ1 int_vector %d\n", int_vector);
358#endif
359    IrqData.name  = ((unsigned int)BSP_PCI_IRQ0 + int_vector);
360    IrqData.handle = boardData;
361    if (!BSP_install_rtems_shared_irq_handler (&IrqData)) {
362        printk("Error installing interrupt handler!\n");
363        rtems_fatal_error_occurred(1);
364    }
365
366    /*
367     * Enable PMCQ1 Interrupts from QSPAN-II
368     */
369
370    *(unsigned long *)(bridgeaddr + 0x600) = 0x00001000;
371    eieio();
372    *(unsigned long *)(bridgeaddr + 0x604) |= 0x00001000;
373
374    eieio();
375  }
376
377  if (i > 0)
378  {
379    rsPMCQ1Initialized = TRUE;
380  }
381  return((i > 0) ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR);
382}
383
384uint32_t PMCQ1_Read_EPLD( uint32_t base, uint32_t reg )
385{
386  uint32_t data;
387
388  data = ( *((unsigned long *) (base + reg)) );
389#ifdef DEBUG_360
390  printk("EPLD Read 0x%x: 0x%08x\n", reg + base, data );
391#endif
392  return data;
393}
394
395void PMCQ1_Write_EPLD( uint32_t base, uint32_t reg, uint32_t data )
396{
397  *((unsigned long *) (base + reg)) = data;
398#ifdef DEBUG_360
399  printk("EPLD Write 0x%x: 0x%08x\n", reg+base, data );
400#endif
401}
402
Note: See TracBrowser for help on using the repository browser.