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

4.115
Last change on this file since e67b2b8d was e67b2b8d, checked in by Daniel Hellstrom <daniel@…>, on 12/20/11 at 14:58:05

LEON: updated and added PCI peripherals for LEON BSPs

The CCHIP driver is replaced with the GR_701 driver. The
RASTA driver is replaced by the GR-RASTA-IO driver.

All drivers are now compatible with both LEON2 and LEON3,
drivers were initialized directly by the PCI-board drivers
are now initialized by the driver manager and therefore
does not require the double code created by including for
example grcan.c into grcan_rasta.c. The other drivers needs
to be updated to the driver manager framework however.

Added support for:

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