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

Last change on this file since c05d7a9d was c05d7a9d, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 21, 2018 at 8:43:27 PM

bsps/sparc: Fix warnings

  • Property mode set to 100644
File size: 15.1 KB
Line 
1/*  GR-TMTC-1553 PCI Target driver.
2 *
3 *  COPYRIGHT (c) 2008.
4 *  Cobham Gaisler AB.
5 *
6 *  Configures the GR-TMTC-1553 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 *  gr_tmtc_1553_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#include <grlib.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_tmtc_1553.h>
39
40#include <grlib_impl.h>
41
42/*#define DEBUG 1 */
43
44#ifdef DEBUG
45#define DBG(x...) printk(x)
46#else
47#define DBG(x...)
48#endif
49
50/* PCI ID */
51#define PCIID_VENDOR_GAISLER            0x1AC8
52
53int gr_tmtc_1553_init1(struct drvmgr_dev *dev);
54int gr_tmtc_1553_init2(struct drvmgr_dev *dev);
55void gr_tmtc_1553_isr (void *arg);
56
57struct gr_tmtc_1553_ver {
58        const unsigned int      amba_freq_hz;   /* The frequency */
59        const unsigned int      amba_ioarea;    /* The address where the PnP IOAREA starts at */
60};
61
62/* Private data structure for driver */
63struct gr_tmtc_1553_priv {
64        /* Driver management */
65        struct drvmgr_dev               *dev;
66        char                            prefix[32];
67        SPIN_DECLARE(devlock);
68
69        /* PCI */
70        pci_dev_t                       pcidev;
71        struct pci_dev_info             *devinfo;
72
73        /* IRQ */
74        genirq_t                        genirq;
75
76        struct gr_tmtc_1553_ver         *version;
77        struct irqmp_regs               *irq;
78        struct drvmgr_map_entry         bus_maps_down[2];
79
80        struct ambapp_bus               abus;
81        struct ambapp_mmap              amba_maps[4];
82        struct ambapp_config            config;
83};
84
85struct gr_tmtc_1553_ver gr_tmtc_1553_ver0 = {
86        .amba_freq_hz           = 33333333,
87        .amba_ioarea            = 0xfff00000,
88};
89
90
91int ambapp_tmtc_1553_int_register(
92        struct drvmgr_dev *dev,
93        int irq,
94        const char *info,
95        drvmgr_isr handler,
96        void *arg);
97int ambapp_tmtc_1553_int_unregister(
98        struct drvmgr_dev *dev,
99        int irq,
100        drvmgr_isr handler,
101        void *arg);
102int ambapp_tmtc_1553_int_unmask(
103        struct drvmgr_dev *dev,
104        int irq);
105int ambapp_tmtc_1553_int_mask(
106        struct drvmgr_dev *dev,
107        int irq);
108int ambapp_tmtc_1553_int_clear(
109        struct drvmgr_dev *dev,
110        int irq);
111int ambapp_tmtc_1553_get_params(
112        struct drvmgr_dev *dev,
113        struct drvmgr_bus_params *params);
114
115struct ambapp_ops ambapp_tmtc_1553_ops = {
116        .int_register = ambapp_tmtc_1553_int_register,
117        .int_unregister = ambapp_tmtc_1553_int_unregister,
118        .int_unmask = ambapp_tmtc_1553_int_unmask,
119        .int_mask = ambapp_tmtc_1553_int_mask,
120        .int_clear = ambapp_tmtc_1553_int_clear,
121        .get_params = ambapp_tmtc_1553_get_params
122};
123
124struct drvmgr_drv_ops gr_tmtc_1553_ops = 
125{
126        {gr_tmtc_1553_init1, gr_tmtc_1553_init2, NULL, NULL},
127        NULL,
128        NULL
129};
130
131struct pci_dev_id_match gr_tmtc_1553_ids[] = 
132{
133        PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_TMTC_1553),
134        PCIID_END_TABLE /* Mark end of table */
135};
136
137struct pci_drv_info gr_tmtc_1553_info =
138{
139        {
140                DRVMGR_OBJ_DRV,                 /* Driver */
141                NULL,                           /* Next driver */
142                NULL,                           /* Device list */
143                DRIVER_PCI_GAISLER_TMTC_1553_ID, /* Driver ID */
144                "GR-TMTC-1553_DRV",             /* Driver Name */
145                DRVMGR_BUS_TYPE_PCI,            /* Bus Type */
146                &gr_tmtc_1553_ops,
147                NULL,                           /* Funcs */
148                0,                              /* No devices yet */
149                0,
150        },
151        &gr_tmtc_1553_ids[0]
152};
153
154/* Driver resources configuration for the AMBA bus on the GR-RASTA-IO board.
155 * It is declared weak so that the user may override it from the project file,
156 * if the default settings are not enough.
157 *
158 * The configuration consists of an array of configuration pointers, each
159 * pointer determine the configuration of one GR-RASTA-IO board. Pointer
160 * zero is for board0, pointer 1 for board1 and so on.
161 *
162 * The array must end with a NULL pointer.
163 */
164struct drvmgr_bus_res *gr_tmtc_1553_resources[] __attribute__((weak)) =
165{
166        NULL
167};
168
169void gr_tmtc_1553_register_drv(void)
170{
171        DBG("Registering GR-TMTC-1553 PCI driver\n");
172        drvmgr_drv_register(&gr_tmtc_1553_info.general);
173}
174
175void gr_tmtc_1553_isr (void *arg)
176{
177        struct gr_tmtc_1553_priv *priv = arg;
178        unsigned int status, tmp;
179        int irq;
180        SPIN_ISR_IRQFLAGS(irqflags);
181
182        tmp = status = priv->irq->ipend;
183
184        /* DBG("GR-RASTA-IO: IRQ 0x%x\n",status); */
185
186        SPIN_LOCK(&priv->devlock, irqflags);
187        for(irq=0; irq<16; irq++) {
188                if ( status & (1<<irq) ) {
189                        genirq_doirq(priv->genirq, irq);
190                        priv->irq->iclear = (1<<irq);
191                        status &= ~(1<<irq);
192                        if ( status == 0 )
193                                break;
194                }
195        }
196        SPIN_UNLOCK(&priv->devlock, irqflags);
197
198        /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */
199        if ( tmp ) 
200                drvmgr_interrupt_clear(priv->dev, 0);
201
202        DBG("GR-TMTC-1553-IRQ: 0x%x\n", tmp);
203}
204
205static int gr_tmtc_1553_hw_init(struct gr_tmtc_1553_priv *priv)
206{
207        unsigned int *page0 = NULL;
208        struct ambapp_dev *tmp;
209        unsigned int pci_freq_hz;
210        struct pci_dev_info *devinfo = priv->devinfo;
211        uint32_t bar0, bar0_size;
212
213        /* Select version of GR-TMTC-1553 board */
214        switch (devinfo->rev) {
215                case 0:
216                        priv->version = &gr_tmtc_1553_ver0;
217                        break;
218                default:
219                        return -2;
220        }
221
222        bar0 = devinfo->resources[0].address;
223        bar0_size = devinfo->resources[0].size;
224        page0 = (unsigned int *)(bar0 + bar0_size/2); 
225
226        /* Point PAGE0 to start of board address map. RAM at 0xff000000, APB at 0xffc00000, IOAREA at 0xfff000000 */
227        /* XXX We assume little endian host with byte twisting enabled here */
228        *page0 = 0x010000ff;    /* Set little endian mode on peripheral. */
229
230        /* Scan AMBA Plug&Play */
231
232        /* AMBA MAP bar0 (in CPU) ==> 0x80000000(remote amba address) */
233        priv->amba_maps[0].size = 0x1000000;
234        priv->amba_maps[0].local_adr = bar0;
235        priv->amba_maps[0].remote_adr = 0xff000000;
236       
237        /* Addresses not matching with map be untouched */
238        priv->amba_maps[2].size = 0xfffffff0;
239        priv->amba_maps[2].local_adr = 0;
240        priv->amba_maps[2].remote_adr = 0;
241
242        /* Mark end of table */
243        priv->amba_maps[3].size=0;
244        priv->amba_maps[3].local_adr = 0;
245        priv->amba_maps[3].remote_adr = 0;
246
247        /* Start AMBA PnP scan at first AHB bus */
248        ambapp_scan(&priv->abus,
249                bar0 + (priv->version->amba_ioarea & ~0xff000000),
250                NULL, &priv->amba_maps[0]);
251
252        /* Frequency is the hsame as the PCI bus frequency */
253        drvmgr_freq_get(priv->dev, 0, &pci_freq_hz);
254
255        ambapp_freq_init(&priv->abus, NULL, pci_freq_hz);
256
257        /* Find IRQ controller */
258        tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
259                                        (OPTIONS_ALL|OPTIONS_APB_SLVS),
260                                        VENDOR_GAISLER, GAISLER_IRQMP,
261                                        ambapp_find_by_idx, NULL);
262        if ( !tmp ) {
263                return -4;
264        }
265        priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start;
266        /* Set up irq controller */
267        priv->irq->mask[0] = 0;
268        priv->irq->iclear = 0xffff;
269        priv->irq->ilevel = 0;
270
271        /* DOWN streams translation table */
272        priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA";
273        priv->bus_maps_down[0].size = priv->amba_maps[0].size;
274        priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr;
275        priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr;
276        /* Mark end of translation table */
277        priv->bus_maps_down[1].size = 0;
278
279        /* Successfully registered the board */
280        return 0;
281}
282
283
284/* Called when a PCI target is found with the PCI device and vendor ID
285 * given in gr_tmtc_1553_ids[].
286 */
287int gr_tmtc_1553_init1(struct drvmgr_dev *dev)
288{
289        struct gr_tmtc_1553_priv *priv;
290        struct pci_dev_info *devinfo;
291        int status;
292        uint32_t bar0, bar0_size;
293        int resources_cnt;
294
295        /* PCI device does not have the IRQ line register, when PCI autoconf configures it the configuration
296         * is forgotten. We take the IRQ number from the PCI Host device (AMBA device), this works as long
297         * as PCI-IRQs are ored together on the bus.
298         *
299         * Note that this only works on LEON.
300         */
301        ((struct pci_dev_info *)dev->businfo)->irq = ((struct amba_dev_info *)dev->parent->dev->businfo)->info.irq; 
302
303        priv = grlib_calloc(1, sizeof(*priv));
304        if ( !priv )
305                return DRVMGR_NOMEM;
306
307        dev->priv = priv;
308        priv->dev = dev;
309
310        /* Determine number of configurations */
311        resources_cnt = get_resarray_count(gr_tmtc_1553_resources);
312
313        /* Generate Device prefix */
314
315        strcpy(priv->prefix, "/dev/tmtc1553_0");
316        priv->prefix[14] += dev->minor_drv;
317        mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO);
318        priv->prefix[15] = '/';
319        priv->prefix[16] = '\0';
320
321        priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo;
322        priv->pcidev = devinfo->pcidev;
323        bar0 = devinfo->resources[0].address;
324        bar0_size = devinfo->resources[0].size;
325        printk("\n\n--- GR-TMTC-1553[%d] ---\n", dev->minor_drv);
326        printk(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n",
327                PCI_DEV_EXPAND(priv->pcidev));
328        printk(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n",
329                devinfo->id.vendor, devinfo->id.device);
330        printk(" PCI BAR[0]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
331                bar0, bar0 + bar0_size - 1);
332        printk(" IRQ: %d\n\n\n", devinfo->irq);
333
334        /* all neccessary space assigned to GR-TMTC-1553 target? */
335        if (bar0_size == 0)
336                return DRVMGR_ENORES;
337
338        /* Initialize spin-lock for this PCI peripheral device. This is to
339         * protect the Interrupt Controller Registers. The genirq layer is
340         * protecting its own internals and ISR dispatching.
341         */
342        SPIN_INIT(&priv->devlock, priv->prefix);
343
344        priv->genirq = genirq_init(16);
345        if ( priv->genirq == NULL ) {
346                free(priv);
347                dev->priv = NULL;
348                return DRVMGR_FAIL;
349        }
350
351        status = gr_tmtc_1553_hw_init(priv);
352        if ( status != 0 ) {
353                genirq_destroy(priv->genirq);
354                free(priv);
355                dev->priv = NULL;
356                printk(" Failed to initialize GR-TMTC-1553 HW: %d\n", status);
357                return DRVMGR_FAIL;
358        }
359
360        /* Init amba bus */
361        priv->config.abus = &priv->abus;
362        priv->config.ops = &ambapp_tmtc_1553_ops;
363        priv->config.maps_down = &priv->bus_maps_down[0];
364        /* This PCI device has only target interface so DMA is not supported,
365         * which means that translation from AMBA->PCI should fail if attempted.
366         */
367        priv->config.maps_up = DRVMGR_TRANSLATE_NO_BRIDGE;
368        if ( priv->dev->minor_drv < resources_cnt ) {
369                priv->config.resources = gr_tmtc_1553_resources[priv->dev->minor_drv];
370        } else {
371                priv->config.resources = NULL;
372        }
373
374        /* Create And Register AMBA PnP Bus */
375        return ambapp_bus_register(dev, &priv->config);
376}
377
378int gr_tmtc_1553_init2(struct drvmgr_dev *dev)
379{
380        struct gr_tmtc_1553_priv *priv = dev->priv;
381
382        /* Clear any old interrupt requests */
383        drvmgr_interrupt_clear(dev, 0);
384
385        /* Enable System IRQ so that GR-TMTC-1553 PCI target interrupt goes through.
386         *
387         * It is important to enable it in stage init2. If interrupts were enabled in init1
388         * this might hang the system when more than one PCI target is connected, this is
389         * because PCI interrupts might be shared and PCI target 2 have not initialized and
390         * might therefore drive interrupt already when entering init1().
391         */
392        drvmgr_interrupt_register(
393                dev,
394                0,
395                "gr_tmtc_1553",
396                gr_tmtc_1553_isr,
397                (void *)priv);
398
399        return DRVMGR_OK;
400}
401
402int ambapp_tmtc_1553_int_register(
403        struct drvmgr_dev *dev,
404        int irq,
405        const char *info,
406        drvmgr_isr handler,
407        void *arg)
408{
409        struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
410        SPIN_IRQFLAGS(irqflags);
411        int status;
412        void *h;
413
414        h = genirq_alloc_handler(handler, arg);
415        if ( h == NULL )
416                return DRVMGR_FAIL;
417
418        SPIN_LOCK_IRQ(&priv->devlock, irqflags);
419
420        status = genirq_register(priv->genirq, irq, h);
421        if ( status == 0 ) {
422                /* Disable and clear IRQ for first registered handler */
423                priv->irq->iclear = (1<<irq);
424                priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
425        } else if ( status == 1 )
426                status = 0;
427
428        if (status != 0) {
429                SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
430                genirq_free_handler(h);
431                return DRVMGR_FAIL;
432        }
433
434        status = genirq_enable(priv->genirq, irq, handler, arg);
435        if ( status == 0 ) {
436                /* Enable IRQ for first enabled handler only */
437                priv->irq->mask[0] |= (1<<irq); /* unmask interrupt source */
438        } else if ( status == 1 )
439                status = 0;
440
441        SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
442
443        return status;
444}
445
446int ambapp_tmtc_1553_int_unregister(
447        struct drvmgr_dev *dev,
448        int irq,
449        drvmgr_isr isr,
450        void *arg)
451{
452        struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
453        SPIN_IRQFLAGS(irqflags);
454        int status;
455        void *handler;
456
457        SPIN_LOCK_IRQ(&priv->devlock, irqflags);
458
459        status = genirq_disable(priv->genirq, irq, isr, arg);
460        if ( status == 0 ) {
461                /* Disable IRQ only when no enabled handler exists */
462                priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
463        } else if ( status == 1 )
464                status = 0;
465
466        handler = genirq_unregister(priv->genirq, irq, isr, arg);
467        if ( handler == NULL )
468                status = DRVMGR_FAIL;
469        else
470                status = DRVMGR_OK;
471
472        SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
473
474        if (handler)
475                genirq_free_handler(handler);
476
477        return status;
478}
479
480int ambapp_tmtc_1553_int_unmask(
481        struct drvmgr_dev *dev,
482        int irq)
483{
484        struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
485        SPIN_IRQFLAGS(irqflags);
486
487        DBG("TMTC-1553 IRQ %d: enable\n", irq);
488       
489        if ( genirq_check(priv->genirq, irq) )
490                return DRVMGR_FAIL;
491
492        SPIN_LOCK_IRQ(&priv->devlock, irqflags);
493
494        /* Enable IRQ */
495        priv->irq->mask[0] |= (1<<irq); /* unmask interrupt source */
496
497        SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
498
499        return DRVMGR_OK;
500}
501
502int ambapp_tmtc_1553_int_mask(
503        struct drvmgr_dev *dev,
504        int irq)
505{
506        struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
507        SPIN_IRQFLAGS(irqflags);
508
509        DBG("TMTC-1553 IRQ %d: disable\n", irq);
510
511        if ( genirq_check(priv->genirq, irq) )
512                return DRVMGR_FAIL;
513
514        SPIN_LOCK_IRQ(&priv->devlock, irqflags);
515
516        /* Disable IRQ */
517        priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
518
519        SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
520
521        return DRVMGR_OK;
522}
523
524int ambapp_tmtc_1553_int_clear(
525        struct drvmgr_dev *dev,
526        int irq)
527{
528        struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
529
530        if ( genirq_check(priv->genirq, irq) )
531                return DRVMGR_FAIL;
532
533        priv->irq->iclear = (1<<irq);
534
535        return DRVMGR_OK;
536}
537
538int ambapp_tmtc_1553_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
539{
540        struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv;
541
542        /* Device name prefix pointer, skip /dev */
543        params->dev_prefix = &priv->prefix[5];
544
545        return 0;
546}
547
548void gr_tmtc_1553_print_dev(struct drvmgr_dev *dev, int options)
549{
550        struct gr_tmtc_1553_priv *priv = dev->priv;
551        struct pci_dev_info *devinfo = priv->devinfo;
552        uint32_t bar0, bar0_size;
553
554        /* Print */
555        printf("--- GR-TMTC-1553 [bus 0x%x, dev 0x%x, fun 0x%x] ---\n",
556                PCI_DEV_EXPAND(priv->pcidev));
557
558        bar0 = devinfo->resources[0].address;
559        bar0_size = devinfo->resources[0].size;
560
561        printf(" PCI BAR[0]: 0x%" PRIx32 " - 0x%" PRIx32 "\n",
562                bar0, bar0 + bar0_size - 1);
563        printf(" IRQ REGS:        0x%" PRIxPTR "\n", (uintptr_t)priv->irq);
564        printf(" IRQ:             %d\n", devinfo->irq);
565        printf(" FREQ:            %d Hz\n", priv->version->amba_freq_hz);
566        printf(" IMASK:           0x%08x\n", priv->irq->mask[0]);
567        printf(" IPEND:           0x%08x\n", priv->irq->ipend);
568
569        /* Print amba config */
570        if ( options & TMTC_1553_OPTIONS_AMBA ) {
571                ambapp_print(&priv->abus, 10);
572        }
573#if 0
574        /* Print IRQ handlers and their arguments */
575        if ( options & TMTC_1553_OPTIONS_IRQ ) {
576                int i;
577                for(i=0; i<16; i++) {
578                        printf(" IRQ[%02d]:         0x%x, arg: 0x%x\n",
579                                i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg);
580                }
581        }
582#endif
583}
584
585void gr_tmtc_1553_print(int options)
586{
587        struct pci_drv_info *drv = &gr_tmtc_1553_info;
588        struct drvmgr_dev *dev;
589
590        dev = drv->general.dev;
591        while(dev) {
592                gr_tmtc_1553_print_dev(dev, options);
593                dev = dev->next_in_drv;
594        }
595}
Note: See TracBrowser for help on using the repository browser.