source: rtems/c/src/lib/libbsp/sparc/shared/pci/gr_701.c @ e67b2b8d

4.115
Last change on this file since e67b2b8d was e67b2b8d, checked in by Daniel Hellstrom <daniel@…>, on 12/20/11 at 14:58:05

LEON: updated and added PCI peripherals for LEON BSPs

The CCHIP driver is replaced with the GR_701 driver. The
RASTA driver is replaced by the GR-RASTA-IO driver.

All drivers are now compatible with both LEON2 and LEON3,
drivers were initialized directly by the PCI-board drivers
are now initialized by the driver manager and therefore
does not require the double code created by including for
example grcan.c into grcan_rasta.c. The other drivers needs
to be updated to the driver manager framework however.

Added support for:

  • GR-701 (only LEON2 before)
  • GR-RASTA-IO (only LEON2 before)
  • GR-RASTA-ADCDAC
  • GR-RASTA-TMTC
  • GR-RASTA-SPW-ROUTER
  • GR-TMTC-1553
  • Property mode set to 100644
File size: 14.5 KB
Line 
1/*  GR-701 PCI Target driver.
2 *
3 *  COPYRIGHT (c) 2008.
4 *  Cobham Gaisler AB.
5 *
6 *  Configures the GR-701 interface PCI board.
7 *  This driver provides a AMBA PnP bus by using the general part
8 *  of the AMBA PnP bus driver (ambapp_bus.c).
9 *
10 *  Driver resources for the AMBA PnP bus provided can be set using
11 *  gr701_set_resources().
12 *
13 *  The license and distribution terms for this file may be
14 *  found in found in the file LICENSE in this distribution or at
15 *  http://www.rtems.com/license/LICENSE.
16 */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23
24#include <bsp.h>
25#include <rtems/bspIo.h>
26#include <pci.h>
27#include <pci/access.h>
28
29#include <ambapp.h>
30
31#include <ambapp.h>
32#include <drvmgr/drvmgr.h>
33#include <drvmgr/ambapp_bus.h>
34#include <drvmgr/pci_bus.h>
35#include <genirq.h>
36
37#include <gr_701.h>
38
39/* Offset from 0x80000000 (dual bus version) */
40#define AHB1_BASE_ADDR 0x80000000
41#define AHB1_IOAREA_BASE_ADDR 0x80100000
42
43/* #define DEBUG 1 */
44
45#ifdef DEBUG
46#define DBG(x...) printk(x)
47#else
48#define DBG(x...)
49#endif
50
51int gr701_init1(struct drvmgr_dev *dev);
52int gr701_init2(struct drvmgr_dev *dev);
53
54#define READ_REG(address) (*(volatile unsigned int *)address)
55
56/* PCI bride reg layout on AMBA side */
57struct amba_bridge_regs {
58        volatile unsigned int bar0;
59        volatile unsigned int bar1;
60        volatile unsigned int bar2;
61        volatile unsigned int bar3;
62        volatile unsigned int bar4;/* 0x10 */
63       
64        volatile unsigned int unused[4*3-1];
65       
66        volatile unsigned int ambabars[1]; /* 0x40 */
67};
68
69/* PCI bride reg layout on PCI side */
70struct pci_bridge_regs {
71        volatile unsigned int bar0;
72        volatile unsigned int bar1;
73        volatile unsigned int bar2;
74        volatile unsigned int bar3;
75        volatile unsigned int bar4; /* 0x10 */
76
77        volatile unsigned int ilevel;
78        volatile unsigned int ipend;
79        volatile unsigned int iforce;
80        volatile unsigned int istatus;
81        volatile unsigned int iclear;
82        volatile unsigned int imask;
83};
84
85/* Private data structure for driver */
86struct gr701_priv {
87        /* Driver management */
88        struct drvmgr_dev       *dev;
89        char                            prefix[16];
90
91        struct pci_bridge_regs          *pcib;
92        struct amba_bridge_regs         *ambab;
93
94        /* PCI */
95        pci_dev_t                       pcidev;
96        struct pci_dev_info             *devinfo;       
97
98        /* IRQ */
99        genirq_t                        genirq;
100        int                             interrupt_cnt;
101
102        /* GR-701 Address translation */
103        struct drvmgr_map_entry         bus_maps_up[2];
104        struct drvmgr_map_entry         bus_maps_down[2];
105
106        /* AMBA Plug&Play information on GR-701 */
107        struct ambapp_bus               abus;
108        struct ambapp_mmap              amba_maps[3];
109        struct ambapp_config            config;
110};
111
112int ambapp_gr701_int_register(
113        struct drvmgr_dev *dev,
114        int irq,
115        const char *info,
116        drvmgr_isr handler,
117        void *arg);
118int ambapp_gr701_int_unregister(
119        struct drvmgr_dev *dev,
120        int irq,
121        drvmgr_isr isr,
122        void *arg);
123int ambapp_gr701_int_unmask(
124        struct drvmgr_dev *dev,
125        int irq);
126int ambapp_gr701_int_mask(
127        struct drvmgr_dev *dev,
128        int irq);
129int ambapp_gr701_int_clear(
130        struct drvmgr_dev *dev,
131        int irq);
132int ambapp_gr701_get_params(
133        struct drvmgr_dev *dev,
134        struct drvmgr_bus_params *params);
135
136struct ambapp_ops ambapp_gr701_ops = {
137        .int_register = ambapp_gr701_int_register,
138        .int_unregister = ambapp_gr701_int_unregister,
139        .int_unmask = ambapp_gr701_int_unmask,
140        .int_mask = ambapp_gr701_int_mask,
141        .int_clear = ambapp_gr701_int_clear,
142        .get_params = ambapp_gr701_get_params
143};
144
145struct drvmgr_drv_ops gr701_ops =
146{
147        .init = {gr701_init1, gr701_init2, NULL, NULL},
148        .remove = NULL,
149        .info = NULL
150};
151
152struct pci_dev_id_match gr701_ids[] =
153{
154        PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_701),
155        PCIID_END_TABLE /* Mark end of table */
156};
157
158struct pci_drv_info gr701_info =
159{
160        {
161                DRVMGR_OBJ_DRV,                 /* Driver */
162                NULL,                           /* Next driver */
163                NULL,                           /* Device list */
164                DRIVER_PCI_GAISLER_GR701_ID,    /* Driver ID */
165                "GR-701_DRV",                   /* Driver Name */
166                DRVMGR_BUS_TYPE_PCI,            /* Bus Type */
167                &gr701_ops,
168                NULL,                           /* Funcs */
169                0,                              /* No devices yet */
170                0,
171        },
172        &gr701_ids[0]
173};
174
175/* Driver resources configuration for the AMBA bus on the GR-701 board.
176 * It is declared weak so that the user may override it from the project file,
177 * if the default settings are not enough.
178 *
179 * The configuration consists of an array of configuration pointers, each
180 * pointer determine the configuration of one GR-701 board. Pointer
181 * zero is for board0, pointer 1 for board1 and so on.
182 *
183 * The array must end with a NULL pointer.
184 */
185struct drvmgr_bus_res *gr701_resources[] __attribute__((weak)) =
186{
187        NULL
188};
189int gr701_resources_cnt = 0;
190
191void gr701_register_drv(void)
192{
193        DBG("Registering GR-701 PCI driver\n");
194        drvmgr_drv_register(&gr701_info.general);
195}
196
197void gr701_interrupt(void *arg)
198{
199        struct gr701_priv *priv = arg;
200        unsigned int status;
201        int irq = 0;
202
203        while ( (status=priv->pcib->istatus) != 0 ) {
204                priv->interrupt_cnt++;  /* An interrupt was generated */
205                irq = status;
206                genirq_doirq(priv->genirq, irq);
207                /* ACK interrupt */
208                priv->pcib->istatus = 0;
209        }
210
211        /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */
212        if ( irq )
213                drvmgr_interrupt_clear(priv->dev, 0);
214}
215
216int gr701_hw_init(struct gr701_priv *priv)
217{
218        uint32_t com1;
219        struct pci_bridge_regs *pcib;
220        struct amba_bridge_regs *ambab;
221        int mst;
222        unsigned int pci_freq_hz;
223        pci_dev_t pcidev = priv->pcidev;
224        struct pci_dev_info *devinfo = priv->devinfo;
225
226        /* Set up PCI ==> AMBA */
227        priv->pcib = pcib = (void *)devinfo->resources[0].address;
228        pcib->bar0 = 0xfc000000;
229
230        /* Set up GR701 AMBA Masters connection to PCI */
231        priv->ambab = ambab = (struct amba_bridge_regs *)(
232                devinfo->resources[1].address + 0x400);
233
234        /* Init all msters, max 16 */
235        for (mst=0; mst<16; mst++) {
236                ambab->ambabars[mst] = 0x40000000;
237                if (READ_REG(&ambab->ambabars[mst]) != 0x40000000)
238                        break;
239        }
240
241        /* Setup Address translation for AMBA bus, assume that PCI BAR
242         * are mapped 1:1 to CPU.
243         */
244
245        priv->amba_maps[0].size = 0x04000000;
246        priv->amba_maps[0].local_adr = devinfo->resources[1].address;
247        priv->amba_maps[0].remote_adr = 0xfc000000;
248
249        /* Mark end of table */
250        priv->amba_maps[1].size=0;
251        priv->amba_maps[1].local_adr = 0;
252        priv->amba_maps[1].remote_adr = 0;
253
254        /* Setup DOWN-streams address translation */
255        priv->bus_maps_down[0].name = "PCI BAR1 -> AMBA";
256        priv->bus_maps_down[0].size = priv->amba_maps[0].size;
257        priv->bus_maps_down[0].from_adr = (void *)devinfo->resources[1].address;
258        priv->bus_maps_down[0].to_adr = (void *)0xfc000000;
259
260        /* Setup UP-streams address translation */
261        priv->bus_maps_up[0].name = "AMBA PCIF Window";
262        priv->bus_maps_up[0].size = 0x10000000;
263        priv->bus_maps_up[0].from_adr = (void *)0xe0000000;
264        priv->bus_maps_up[0].to_adr = (void *)0x40000000;
265
266        /* Mark end of translation tables */
267        priv->bus_maps_down[1].size = 0;
268        priv->bus_maps_up[1].size = 0;
269
270        /* Enable I/O and Mem accesses */
271        pci_cfg_r32(pcidev, PCI_COMMAND, &com1);
272        com1 |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
273        pci_cfg_w32(pcidev, PCI_COMMAND, com1);
274
275        /* Start AMBA PnP scan at first AHB bus */
276        ambapp_scan(&priv->abus, devinfo->resources[1].address + 0x3f00000,
277                        NULL, &priv->amba_maps[0]);
278
279        /* Frequency is the same as the PCI bus frequency */
280        drvmgr_freq_get(priv->dev, NULL, &pci_freq_hz);
281
282        /* Initialize Frequency of AMBA bus */
283        ambapp_freq_init(&priv->abus, NULL, pci_freq_hz);
284
285        /* Init IRQ controller (avoid IRQ generation) */
286        pcib->imask = 0x0000;
287        pcib->ipend = 0;
288        pcib->iclear = 0xffff;
289        pcib->iforce = 0;
290        pcib->ilevel = 0x0;
291
292        /* Successfully registered the GR-701 board */
293        return 0;
294}
295
296void gr701_hw_init2(struct gr701_priv *priv)
297{
298        /* Enable PCI Master (for DMA) */
299        pci_master_enable(priv->pcidev);
300}
301
302/* Called when a PCI target is found with the PCI device and vendor ID
303 * given in gr701_ids[].
304 */
305int gr701_init1(struct drvmgr_dev *dev)
306{
307        struct gr701_priv *priv;
308        struct pci_dev_info *devinfo;
309        uint32_t bar0, bar1, bar0_size, bar1_size;
310
311        priv = malloc(sizeof(struct gr701_priv));
312        if ( !priv )
313                return DRVMGR_NOMEM;
314
315        memset(priv, 0, sizeof(*priv));
316        dev->priv = priv;
317        priv->dev = dev;
318
319        /* Determine number of configurations */
320        if ( gr701_resources_cnt == 0 ) {
321                while ( gr701_resources[gr701_resources_cnt] )
322                        gr701_resources_cnt++;
323        }
324
325        /* Generate Device prefix */
326
327        strcpy(priv->prefix, "/dev/gr701_0");
328        priv->prefix[11] += dev->minor_drv;
329        mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO);
330        priv->prefix[12] = '/';
331        priv->prefix[13] = '\0';
332
333        priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo;
334        priv->pcidev = devinfo->pcidev;
335        bar0 = devinfo->resources[0].address;
336        bar0_size = devinfo->resources[0].size;
337        bar1 = devinfo->resources[1].address;
338        bar1_size = devinfo->resources[1].size;
339        printf("\n\n--- GR-701[%d] ---\n", dev->minor_drv);
340        printf(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n",
341                PCI_DEV_EXPAND(priv->pcidev));
342        printf(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n\n\n",
343                devinfo->id.vendor, devinfo->id.device);
344        printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1);
345        printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1);
346        printf(" IRQ: %d\n\n\n", devinfo->irq);
347
348        /* all neccessary space assigned to GR-701 target? */
349        if ((bar0_size == 0) || (bar1_size == 0))
350                return DRVMGR_ENORES;
351
352        priv->genirq = genirq_init(16);
353        if ( priv->genirq == NULL ) {
354                free(priv);
355                dev->priv = NULL;
356                return DRVMGR_FAIL;
357        }
358
359        if ( gr701_hw_init(priv) ) {
360                genirq_destroy(priv->genirq);
361                free(priv);
362                dev->priv = NULL;
363                printf(" Failed to initialize GR-701 HW\n");
364                return DRVMGR_FAIL;
365        }
366
367        /* Init amba bus */
368        priv->config.abus = &priv->abus;
369        priv->config.ops = &ambapp_gr701_ops;
370        priv->config.maps_up = &priv->bus_maps_up[0];
371        priv->config.maps_down = &priv->bus_maps_down[0];
372        if ( priv->dev->minor_drv < gr701_resources_cnt ) {
373                priv->config.resources = gr701_resources[priv->dev->minor_drv];
374        } else {
375                priv->config.resources = NULL;
376        }
377
378        /* Create and register AMBA PnP bus. */
379        return ambapp_bus_register(dev, &priv->config);
380}
381
382/* Called when a PCI target is found with the PCI device and vendor ID
383 * given in gr701_ids[].
384 */
385int gr701_init2(struct drvmgr_dev *dev)
386{
387        struct gr701_priv *priv = dev->priv;
388
389        /* Clear any old interrupt requests */
390        drvmgr_interrupt_clear(dev, 0);
391
392        /* Enable System IRQ so that GR-701 PCI target interrupt goes through.
393         *
394         * It is important to enable it in stage init2. If interrupts were
395         * enabled in init1 this might hang the system when more than one PCI
396         * board is connected, this is because PCI interrupts might be shared
397         * and PCI target 2 have not initialized and might therefore drive
398         * interrupt already when entering init1().
399         */
400        drvmgr_interrupt_register(dev, 0, "gr701", gr701_interrupt, priv);
401
402        gr701_hw_init2(priv);
403
404        return DRVMGR_OK;
405}
406
407int ambapp_gr701_int_register(
408        struct drvmgr_dev *dev,
409        int irq,
410        const char *info,
411        drvmgr_isr handler,
412        void *arg)
413{
414        struct gr701_priv *priv = dev->parent->dev->priv;
415        rtems_interrupt_level level;
416        int status;
417
418        rtems_interrupt_disable(level);
419
420        status = genirq_register(priv->genirq, irq, handler, arg);
421        if ( status == 0 ) {
422                /* Clear IRQ for first registered handler */
423                priv->pcib->iclear = (1<<irq);
424        } else if ( status == 1 )
425                status = 0;
426
427        if (status != 0) {
428                rtems_interrupt_enable(level);
429                return DRVMGR_FAIL;
430        }
431
432        status = genirq_enable(priv->genirq, irq, handler, arg);
433        if ( status == 0 ) {
434                /* Enable IRQ for first enabled handler only */
435                priv->pcib->imask |= (1<<irq); /* unmask interrupt source */
436        } else if ( status == 1 )
437                status = DRVMGR_OK;
438
439        rtems_interrupt_enable(level);
440
441        return status;
442}
443
444int ambapp_gr701_int_unregister(
445        struct drvmgr_dev *dev,
446        int irq,
447        drvmgr_isr isr,
448        void *arg)
449{
450        struct gr701_priv *priv = dev->parent->dev->priv;
451        rtems_interrupt_level level;
452        int status;
453
454        rtems_interrupt_disable(level);
455
456        status = genirq_disable(priv->genirq, irq, isr, arg);
457        if ( status == 0 ) {
458                /* Disable IRQ only when no enabled handler exists */
459                priv->pcib->imask &= ~(1<<irq); /* mask interrupt source */
460        }
461
462        status = genirq_unregister(priv->genirq, irq, isr, arg);
463        if ( status != 0 )
464                status = DRVMGR_FAIL;
465
466        rtems_interrupt_enable(level);
467
468        return status;
469}
470
471int ambapp_gr701_int_unmask(
472        struct drvmgr_dev *dev,
473        int irq)
474{
475        struct gr701_priv *priv = dev->parent->dev->priv;
476        rtems_interrupt_level level;
477
478        DBG("GR-701 IRQ %d: enable\n", irq);
479
480        if ( genirq_check(priv->genirq, irq) )
481                return DRVMGR_FAIL;
482
483        rtems_interrupt_disable(level);
484
485        /* Enable IRQ */
486        priv->pcib->imask |= (1<<irq); /* unmask interrupt source */
487
488        rtems_interrupt_enable(level);
489
490        return DRVMGR_OK;
491}
492
493int ambapp_gr701_int_mask(
494        struct drvmgr_dev *dev,
495        int irq)
496{
497        struct gr701_priv *priv = dev->parent->dev->priv;
498        rtems_interrupt_level level;
499
500        DBG("GR-701 IRQ %d: disable\n", irq);
501
502        if ( genirq_check(priv->genirq, irq) )
503                return DRVMGR_FAIL;
504
505        rtems_interrupt_disable(level);
506
507        /* Disable IRQ */
508        priv->pcib->imask &= ~(1<<irq); /* mask interrupt source */
509
510        rtems_interrupt_enable(level);
511
512        return DRVMGR_OK;
513}
514
515int ambapp_gr701_int_clear(
516        struct drvmgr_dev *dev,
517        int irq)
518{
519        struct gr701_priv *priv = dev->parent->dev->priv;
520
521        if ( genirq_check(priv->genirq, irq) )
522                return DRVMGR_FAIL;
523
524        priv->pcib->iclear = (1<<irq);
525
526        return DRVMGR_OK;
527}
528
529int ambapp_gr701_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
530{
531        struct gr701_priv *priv = dev->parent->dev->priv;
532
533        /* Device name prefix pointer, skip /dev */
534        params->dev_prefix = &priv->prefix[5];
535
536        return 0;
537}
538
539void gr701_print_dev(struct drvmgr_dev *dev, int options)
540{
541        struct gr701_priv *priv = dev->priv;
542        struct pci_dev_info *devinfo = priv->devinfo;
543        unsigned int freq_hz;
544        uint32_t bar0, bar1, bar0_size, bar1_size;
545
546        /* Print */
547        printf("--- GR-701 [bus 0x%x, dev 0x%x, fun 0x%x] ---\n",
548                PCI_DEV_EXPAND(priv->pcidev));
549        bar0 = devinfo->resources[0].address;
550        bar0_size = devinfo->resources[0].size;
551        bar1 = devinfo->resources[1].address;
552        bar1_size = devinfo->resources[1].size;
553
554        printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1);
555        printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1);
556        printf(" IRQ:             %d\n", devinfo->irq);
557
558        /* Frequency is the same as the PCI bus frequency */
559        drvmgr_freq_get(dev, 0, &freq_hz);
560
561        printf(" FREQ:            %u Hz\n", freq_hz);
562        printf(" IMASK:           0x%08x\n", priv->pcib->imask);
563        printf(" IPEND:           0x%08x\n", priv->pcib->ipend);
564
565        /* Print amba config */
566        if ( options & GR701_OPTIONS_AMBA ) {
567                ambapp_print(&priv->abus, 10);
568        }
569
570#if 0
571        /* Print IRQ handlers and their arguments */
572        if ( options & GR701_OPTIONS_IRQ ) {
573                int i;
574                for(i=0; i<16; i++) {
575                        printf(" IRQ[%02d]:         0x%x, arg: 0x%x\n",
576                                i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg);
577                }
578        }
579#endif
580}
581
582void gr701_print(int options)
583{
584        struct pci_drv_info *drv = &gr701_info;
585        struct drvmgr_dev *dev;
586
587        dev = drv->general.dev;
588        while(dev) {
589                gr701_print_dev(dev, options);
590                dev = dev->next_in_drv;
591        }
592}
Note: See TracBrowser for help on using the repository browser.