source: rtems/c/src/lib/libbsp/sparc/shared/pci/gr_tmtc_1553.c @ 4a7d1026

4.11
Last change on this file since 4a7d1026 was 4a7d1026, checked in by Daniel Hellstrom <daniel@…>, on Apr 13, 2015 at 8:25:52 AM

sparc bsps: updated license to rtems.org

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