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

5
Last change on this file since 11f3b9a was 11f3b9a, checked in by Sebastian Huber <sebastian.huber@…>, on 11/26/18 at 14:55:38

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