source: rtems/bsps/sparc/shared/pci/gr_701.c @ c05d7a9d

5
Last change on this file since c05d7a9d was c05d7a9d, checked in by Sebastian Huber <sebastian.huber@…>, on 12/21/18 at 20:43:27

bsps/sparc: Fix warnings

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