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

4.115
Last change on this file since 8b29637c was 8b29637c, checked in by Daniel Hellstrom <daniel@…>, on 04/07/15 at 12:31:07

LEON: converted PCI peripherals to BSD header

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