source: rtems/c/src/lib/libbsp/sparc/leon2/cchip/cchip.c @ c903fc2

4.115
Last change on this file since c903fc2 was c903fc2, checked in by Daniel Cederman <cederman@…>, on 05/08/14 at 14:33:08

bsps/sparc: Add copyright and license information

  • Property mode set to 100644
File size: 8.7 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup cchip
5 *
6 * @brief GR-701 (Companion Chip) PCI board driver
7 */
8
9/*
10 *  COPYRIGHT (c) 2007.
11 *  Aeroflex Gaisler AB.
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#include <bsp.h>
19#include <rtems/bspIo.h>
20#include <rtems.h>
21#include <string.h>
22
23#include <rtems.h>
24#include <leon.h>
25#include <ambapp.h>
26#include <pci.h>
27
28#include <b1553brm_pci.h>
29#include <occan_pci.h>
30#include <grspw_pci.h>
31#include <apbuart_pci.h>
32
33#include <cchip.h>
34
35/*
36#define DEBUG
37#define DEBUG_IRQS
38*/
39#define BOARD_INFO
40/*#define PRINT_SPURIOUS*/
41
42/* AT697 Register MAP */
43static LEON_Register_Map *regs = (LEON_Register_Map *)0x80000000;
44
45/* initializes interrupt management for companionship board */
46void cchip1_irq_init(void);
47
48/* register interrupt handler (called from drivers) */
49void cchip1_set_isr(void *handler, int irqno, void *arg);
50
51#define READ_REG(address) _READ_REG((unsigned int)address)
52static __inline__ unsigned int _READ_REG(unsigned int addr) {
53        unsigned int tmp;
54        __asm__ ("lda [%1]1, %0 "
55          : "=r"(tmp)
56          : "r"(addr)
57        );
58        return tmp;
59}
60
61/* PCI bride reg layout on AMBA side */
62typedef struct {
63        unsigned int bar0;
64        unsigned int bar1;
65        unsigned int bar2;
66        unsigned int bar3;
67        unsigned int bar4;/* 0x10 */
68
69        unsigned int unused[4*3-1];
70
71        unsigned int ambabars[1]; /* 0x40 */
72} amba_bridge_regs;
73
74/* PCI bride reg layout on PCI side */
75typedef struct {
76        unsigned int bar0;
77        unsigned int bar1;
78        unsigned int bar2;
79        unsigned int bar3;
80        unsigned int bar4; /* 0x10 */
81
82        unsigned int ilevel;
83        unsigned int ipend;
84        unsigned int iforce;
85        unsigned int istatus;
86        unsigned int iclear;
87        unsigned int imask;
88} pci_bridge_regs;
89
90typedef struct {
91        pci_bridge_regs  *pcib;
92        amba_bridge_regs *ambab;
93
94        /* AT697 PCI */
95        unsigned int bars[5];
96        int bus, dev, fun;
97
98        /* AMBA bus */
99        struct ambapp_bus amba_bus;
100        struct ambapp_mmap amba_maps[2];
101
102        /* FT AHB SRAM */
103        int ftsram_size; /* kb */
104        unsigned int ftsram_start;
105        unsigned int ftsram_end;
106
107} cchip1;
108
109cchip1 cc1;
110
111int init_pcif(void){
112        unsigned int com1;
113        int i,bus,dev,fun;
114        pci_bridge_regs *pcib;
115        amba_bridge_regs *ambab;
116        struct ambapp_bus *abus;
117
118  if ( BSP_pciFindDevice(0x1AC8, 0x0701, 0, &bus, &dev, &fun) == 0 ) {
119    ;
120  }else if (BSP_pciFindDevice(0x16E3, 0x0210, 0, &bus, &dev, &fun) == 0) {
121    ;
122  } else {
123    /* didn't find any Companionship board on the PCI bus. */
124    return -1;
125  }
126
127  /* found Companionship PCI board, Set it up: */
128
129        pci_read_config_dword(bus, dev, fun, 0x10, &cc1.bars[0]);
130        pci_read_config_dword(bus, dev, fun, 0x14, &cc1.bars[1]);
131        pci_read_config_dword(bus, dev, fun, 0x18, &cc1.bars[2]);
132        pci_read_config_dword(bus, dev, fun, 0x1c, &cc1.bars[3]);
133        pci_read_config_dword(bus, dev, fun, 0x20, &cc1.bars[4]);
134
135#ifdef DEBUG
136        for(i=0; i<5; i++){
137                printk("PCI: BAR%d: 0x%x\n\r",i,cc1.bars[i]);
138        }
139#endif
140
141        /* Set up PCI ==> AMBA */
142        pcib = (void *)cc1.bars[0];
143        pcib->bar0 = 0xfc000000;
144/*      pcib->bar1 = 0xff000000;*/
145#ifdef BOARD_INFO
146        printk("Found CCHIP1 Board at 0x%lx\n\r",(unsigned int)pcib);
147#endif
148
149        /* AMBA MAP cc1.bars[1] (in CPU) ==> 0xf0000000(remote amba address) */
150        cc1.amba_maps[0].size = 0x04000000;
151        cc1.amba_maps[0].local_adr = cc1.bars[1];
152        cc1.amba_maps[0].remote_adr = 0xfc000000;
153
154        /* Mark end of table */
155        cc1.amba_maps[1].size=0;
156        cc1.amba_maps[1].local_adr = 0;
157        cc1.amba_maps[1].remote_adr = 0;
158
159        /* Enable I/O and Mem accesses */
160        pci_read_config_dword(bus, dev, fun, 0x4, &com1);
161        com1 |= 0x3;
162        pci_write_config_dword(bus, dev, fun, 0x4, com1);
163        pci_read_config_dword(bus, dev, fun, 0x4, &com1);
164
165        /* Set up AMBA Masters ==> PCI */
166        ambab = (void *)(cc1.bars[1]+0x400);
167#ifdef DEBUG
168        printk("AMBA: PCIBAR[%d]: 0x%x, 0x%x\n\r",0,ambab->bar0,pcib->bar0);
169        printk("AMBA: PCIBAR[%d]: 0x%x, 0x%x\n\r",1,ambab->bar1,pcib->bar1);
170        printk("AMBA: PCIBAR[%d]: 0x%x, 0x%x\n\r",2,ambab->bar2,pcib->bar2);
171#endif
172        /* 0xe0000000(AMBA) ==> 0x40000000(PCI) ==> 0x40000000(AT697 AMBA) */
173        ambab->ambabars[0] = 0x40000000;
174
175        /* Scan bus for AMBA devices */
176        abus = &cc1.amba_bus;
177        memset(abus,0,sizeof(*abus));
178        ambapp_scan(abus, cc1.bars[1]+0x3f00000, NULL, &cc1.amba_maps[0]);
179
180        /* Init all msters, max 16 */
181        for(i=1; i<16; i++) {
182                ambab->ambabars[i] = 0x40000000;
183                if (READ_REG(&ambab->ambabars[i]) != 0x40000000)
184                        break;
185        }
186
187        /* Enable PCI Master */
188   pci_read_config_dword(bus, dev, fun, 0x4, &com1);
189   com1 |= 0x4;
190   pci_write_config_dword(bus, dev, fun, 0x4, com1);
191   pci_read_config_dword(bus, dev, fun, 0x4, &com1);
192
193        cc1.pcib  = pcib;
194        cc1.ambab = ambab;
195        cc1.bus = bus;
196        cc1.dev = dev;
197        cc1.fun = fun;
198
199        return 0;
200}
201
202#ifndef GAISLER_FTAHBRAM
203 #define GAISLER_FTAHBRAM 0x50
204#endif
205int init_onboard_sram(void){
206        struct ambapp_ahb_info ahb;
207        struct ambapp_apb_info apb;
208        unsigned int conf, size;
209
210        /* Find SRAM controller
211         * 1. AHB slave interface
212         * 2. APB slave interface
213         */
214        if ( ambapp_find_apbslv(&cc1.amba_bus, VENDOR_GAISLER, GAISLER_FTAHBRAM,
215                                &apb) != 1 ){
216                printk("On Board FT SRAM not found (APB)\n");
217                return -1;
218        }
219
220        if ( ambapp_find_ahbslv(&cc1.amba_bus, VENDOR_GAISLER, GAISLER_FTAHBRAM,
221                                &ahb) != 1 ){
222                printk("On Board FT SRAM not found (AHB)\n");
223                return -1;
224        }
225
226        /* We have found the controller.
227         * Get it going.
228         *
229         * Get size of SRAM
230         */
231        conf = *(unsigned int *)apb.start;
232        size = (conf >>10) & 0x7;
233
234        /* 2^x kb */
235        cc1.ftsram_size = 1<<size;
236        cc1.ftsram_start = ahb.start[0];
237        cc1.ftsram_end = size*1024 + cc1.ftsram_start;
238#ifdef BOARD_INFO
239        printk("Found FT AHB SRAM %dkb at 0x%lx\n",cc1.ftsram_size,cc1.ftsram_start);
240#endif
241        return 0;
242}
243
244int cchip1_register(void){
245
246        /* Init AT697 PCI Controller */
247        init_pci();
248
249        /* Find & init CChip board .
250         * Also scan AMBA Plug&Play info for us.
251         */
252        if ( init_pcif() ){
253                printk("Failed to initialize CCHIP board\n\r");
254                return -1;
255        }
256
257        /* Set interrupt common board stuff */
258        cchip1_irq_init();
259
260        /* Find on board SRAM */
261        if ( init_onboard_sram() ){
262                printk("Failed to register On Board SRAM. It is needed by b1553BRM\n");
263                return -1;
264        }
265
266        /* Register interrupt install functions */
267        b1553brm_pci_int_reg = cchip1_set_isr;
268        occan_pci_int_reg = cchip1_set_isr;
269        grspw_pci_int_reg = cchip1_set_isr;
270        apbuart_pci_int_reg = cchip1_set_isr;
271
272        /* register the BRM PCI driver, use 16k FTSRAM... */
273        if ( b1553brm_pci_register(&cc1.amba_bus,0,0,3,cc1.ftsram_start,0xffa00000) ){
274                printk("Failed to register BRM PCI driver\n");
275                return -1;
276        }
277
278        /* register the BRM PCI driver, no DMA memory... */
279        if ( occan_pci_register(&cc1.amba_bus) ){
280                printk("Failed to register OC_CAN PCI driver\n");
281                return -1;
282        }
283
284        /* register the GRSPW PCI driver, use malloc... */
285        if ( grspw_pci_register(&cc1.amba_bus,0,0xe0000000) ){
286                printk("Failed to register GRSPW PCI driver\n");
287                return -1;
288        }
289
290        /* register the APBUART PCI driver, no DMA memory */
291        if ( apbuart_pci_register(&cc1.amba_bus) ){
292                printk("Failed to register APBUART PCI driver\n");
293                return -1;
294        }
295
296        return 0;
297}
298
299static rtems_isr cchip1_interrupt_dispatcher(rtems_vector_number v);
300static unsigned int cchip1_spurious_cnt;
301
302typedef struct {
303        unsigned int (*handler)(int irqno, void *arg);
304        void *arg;
305} int_handler;
306
307static int_handler int_handlers[16];
308
309void cchip1_irq_init(void){
310
311        /* Configure AT697 ioport bit 7 to input pci irq */
312  regs->PIO_Direction &= ~(1<<7);
313  regs->PIO_Interrupt  = 0x87;          /* level sensitive */
314
315  /* Set up irq controller (mask all IRQs) */
316        cc1.pcib->imask = 0x0000;
317        cc1.pcib->ipend = 0;
318        cc1.pcib->iclear = 0xffff;
319        cc1.pcib->iforce = 0;
320        cc1.pcib->ilevel = 0x0;
321
322        memset(int_handlers,0,sizeof(int_handlers));
323
324        /* Reset spurious counter */
325        cchip1_spurious_cnt = 0;
326
327        /* Register interrupt handler */
328        set_vector(cchip1_interrupt_dispatcher,LEON_TRAP_TYPE(CCHIP_IRQ),1);
329}
330
331void cchip1_set_isr(void *handler, int irqno, void *arg){
332        int_handlers[irqno].handler = handler;
333        int_handlers[irqno].arg = arg;
334#ifdef DEBUG
335        printk("Registering IRQ %d to 0x%lx(%d,0x%lx)\n\r",
336                        irqno,(unsigned int)handler,irqno,(unsigned int)arg);
337#endif
338        cc1.pcib->imask |= 1<<irqno; /* Enable the registered IRQ */
339}
340
341static rtems_isr cchip1_interrupt_dispatcher(rtems_vector_number v){
342        unsigned int pending = READ_REG(&cc1.pcib->ipend);
343        unsigned int (*handler)(int irqno, void *arg);
344        unsigned int clr = pending;
345        int irq=1;
346
347        if ( !pending ){
348#ifdef PRINT_SPURIOUS
349                printk("Spurious IRQ %d: %d\n",v,cchip1_spurious_cnt);
350#endif
351                cchip1_spurious_cnt++;
352                return;
353        }
354#ifdef DEBUG_IRQS
355  printk("CCIRQ: 0x%x\n",(unsigned int)pending);
356#endif
357        /* IRQ 0 doesn't exist */
358        irq=1;
359        pending = pending>>1;
360
361        while ( pending ){
362                if ( (pending & 1) && (handler=int_handlers[irq].handler) ){
363                        handler(irq,int_handlers[irq].arg);
364                }
365                irq++;
366                pending = pending>>1;
367        }
368
369        cc1.pcib->iclear = clr;
370
371        /*LEON_Clear_interrupt( brd->irq );*/
372}
Note: See TracBrowser for help on using the repository browser.