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

Last change on this file since 11f3b9a was 11f3b9a, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 26, 2018 at 2:55:38 PM

bsps/sparc: Add grlib_malloc(), grlib_calloc()

This avoids a dependency to errno in device driver code.

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