source: rtems/bsps/sparc/shared/pci/gr_rasta_adcdac.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: 18.6 KB
RevLine 
[e67b2b8d]1/*  GR-RASTA-ADCDAC PCI Target driver.
2 *
3 *  COPYRIGHT (c) 2008.
4 *  Cobham Gaisler AB.
5 *
6 *  Configures the GR-RASTA-ADCDAC 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_rasta_adcdac_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
[4a7d1026]15 *  http://www.rtems.org/license/LICENSE.
[e67b2b8d]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
28#include <ambapp.h>
29#include <grlib.h>
30#include <drvmgr/drvmgr.h>
31#include <drvmgr/ambapp_bus.h>
32#include <drvmgr/pci_bus.h>
[03037b4]33#include <drvmgr/bspcommon.h>
[5823bae8]34#include <bsp/genirq.h>
[e67b2b8d]35
[5823bae8]36#include <bsp/gr_rasta_adcdac.h>
[e67b2b8d]37
[a7267241]38#include <grlib_impl.h>
[ce76b9d2]39
[e67b2b8d]40/*#define DEBUG 1*/
41
42#ifdef DEBUG
43#define DBG(x...) printk(x)
44#else
45#define DBG(x...)
46#endif
47
48/* Determines which PCI address the AHB masters will access, it should be
49 * set so that the masters can access the CPU RAM. Default is base of CPU RAM,
50 * CPU RAM is mapped 1:1 to PCI space.
51 */
52extern unsigned int _RAM_START;
53#define AHBMST2PCIADR (((unsigned int)&_RAM_START) & 0xf0000000)
54
55/* PCI ID */
56#define PCIID_VENDOR_GAISLER            0x1AC8
57#define PCIID_DEVICE_GR_RASTA_ADCDAC    0x0014
58
59int gr_rasta_adcdac_init1(struct drvmgr_dev *dev);
60int gr_rasta_adcdac_init2(struct drvmgr_dev *dev);
[03037b4]61void gr_rasta_adcdac_isr (void *arg);
[e67b2b8d]62
63struct grpci_regs {
64        volatile unsigned int cfg_stat;
65        volatile unsigned int bar0;
66        volatile unsigned int page0;
67        volatile unsigned int bar1;
68        volatile unsigned int page1;
69        volatile unsigned int iomap;
70        volatile unsigned int stat_cmd;
71};
72
73struct gr_rasta_adcdac_ver {
74        const unsigned int      amba_freq_hz;   /* The frequency */
75        const unsigned int      amba_ioarea;    /* The address where the PnP IOAREA starts at */
76};
77
78/* Private data structure for driver */
79struct gr_rasta_adcdac_priv {
80        /* Driver management */
[ce76b9d2]81        struct drvmgr_dev               *dev;
[e67b2b8d]82        char                            prefix[20];
[ce76b9d2]83        SPIN_DECLARE(devlock);
[e67b2b8d]84
85        /* PCI */
86        pci_dev_t                       pcidev;
87        struct pci_dev_info             *devinfo;
88        uint32_t                        ahbmst2pci_map;
89
90        /* IRQ */
91        genirq_t                        genirq;
92
93        /* GR-RASTA-ADCDAC */
94        struct gr_rasta_adcdac_ver      *version;
95        struct irqmp_regs               *irq;
96        struct grpci_regs               *grpci;
97        struct drvmgr_map_entry         bus_maps_down[3];
98        struct drvmgr_map_entry         bus_maps_up[2];
99
100        /* AMBA Plug&Play information on GR-RASTA-ADCDAC */
101        struct ambapp_bus               abus;
102        struct ambapp_mmap              amba_maps[4];
103        struct ambapp_config            config;
104};
105
106struct gr_rasta_adcdac_ver gr_rasta_adcdac_ver0 = {
107        .amba_freq_hz           = 50000000,
108        .amba_ioarea            = 0x80100000,
109};
110
111int ambapp_rasta_adcdac_int_register(
112        struct drvmgr_dev *dev,
113        int irq,
114        const char *info,
115        drvmgr_isr handler,
116        void *arg);
117int ambapp_rasta_adcdac_int_unregister(
118        struct drvmgr_dev *dev,
119        int irq,
120        drvmgr_isr isr,
121        void *arg);
122int ambapp_rasta_adcdac_int_unmask(
123        struct drvmgr_dev *dev,
124        int irq);
125int ambapp_rasta_adcdac_int_mask(
126        struct drvmgr_dev *dev,
127        int irq);
128int ambapp_rasta_adcdac_int_clear(
129        struct drvmgr_dev *dev,
130        int irq);
131int ambapp_rasta_adcdac_get_params(
132        struct drvmgr_dev *dev,
133        struct drvmgr_bus_params *params);
134
135struct ambapp_ops ambapp_rasta_adcdac_ops = {
136        .int_register = ambapp_rasta_adcdac_int_register,
137        .int_unregister = ambapp_rasta_adcdac_int_unregister,
138        .int_unmask = ambapp_rasta_adcdac_int_unmask,
139        .int_mask = ambapp_rasta_adcdac_int_mask,
140        .int_clear = ambapp_rasta_adcdac_int_clear,
141        .get_params = ambapp_rasta_adcdac_get_params
142};
143
144struct drvmgr_drv_ops gr_rasta_adcdac_ops =
145{       .init = {gr_rasta_adcdac_init1, gr_rasta_adcdac_init2, NULL, NULL},
146        .remove = NULL,
147        .info = NULL
148};
149
150struct pci_dev_id_match gr_rasta_adcdac_ids[] =
151{
152        PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_ADCDAC),
153        PCIID_END_TABLE /* Mark end of table */
154};
155
156struct pci_drv_info gr_rasta_adcdac_info =
157{
158        {
159                DRVMGR_OBJ_DRV,                 /* Driver */
160                NULL,                           /* Next driver */
161                NULL,                           /* Device list */
162                DRIVER_PCI_GAISLER_RASTAADCDAC_ID,/* Driver ID */
163                "GR-RASTA-ADCDAC_DRV",          /* Driver Name */
164                DRVMGR_BUS_TYPE_PCI,            /* Bus Type */
165                &gr_rasta_adcdac_ops,
166                NULL,                           /* Funcs */
167                0,                              /* No devices yet */
168                0,
169        },
170        &gr_rasta_adcdac_ids[0]
171};
172
173/* Driver resources configuration for the AMBA bus on the GR-RASTA-ADCDAC board.
174 * It is declared weak so that the user may override it from the project file,
175 * if the default settings are not enough.
176 *
177 * The configuration consists of an array of configuration pointers, each
178 * pointer determine the configuration of one GR-RASTA-ADCDAC board. Pointer
179 * zero is for board0, pointer 1 for board1 and so on.
180 *
181 * The array must end with a NULL pointer.
182 */
183struct drvmgr_bus_res *gr_rasta_adcdac_resources[] __attribute__((weak)) =
184{
185        NULL
186};
187
188void gr_rasta_adcdac_register_drv(void)
189{
190        DBG("Registering GR-RASTA-ADCDAC PCI driver\n");
191        drvmgr_drv_register(&gr_rasta_adcdac_info.general);
192}
193
194void gr_rasta_adcdac_isr (void *arg)
195{
196        struct gr_rasta_adcdac_priv *priv = arg;
197        unsigned int status, tmp;
198        int irq;
[ce76b9d2]199        SPIN_ISR_IRQFLAGS(irqflags);
200
[e67b2b8d]201        tmp = status = priv->irq->ipend;
202
203        /* DBG("GR-RASTA-ADCDAC: IRQ 0x%x\n",status); */
204
[ce76b9d2]205        SPIN_LOCK(&priv->devlock, irqflags);
[e67b2b8d]206        for(irq=0; irq<16; irq++) {
207                if ( status & (1<<irq) ) {
208                        genirq_doirq(priv->genirq, irq);
209                        priv->irq->iclear = (1<<irq);
210                        status &= ~(1<<irq);
211                        if ( status == 0 )
212                                break;
213                }
214        }
[ce76b9d2]215        SPIN_UNLOCK(&priv->devlock, irqflags);
[e67b2b8d]216
217        /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */
218        if ( tmp )
219                drvmgr_interrupt_clear(priv->dev, 0);
220
221        DBG("RASTA-ADCDAC-IRQ: 0x%x\n", tmp);
222}
223
[03037b4]224static int gr_rasta_adcdac_hw_init1(struct gr_rasta_adcdac_priv *priv)
[e67b2b8d]225{
226        uint32_t data;
227        unsigned int *page0 = NULL;
228        struct ambapp_dev *tmp;
229        struct ambapp_ahb_info *ahb;
230        struct pci_dev_info *devinfo = priv->devinfo;
231        uint32_t bar0, bar0_size;
232
233        /* Select version of GR-RASTA-ADCDAC board */
234        switch (devinfo->rev) {
235                case 0:
236                        priv->version = &gr_rasta_adcdac_ver0;
237                        break;
238                default:
239                        return -2;
240        }
241
242        bar0 = devinfo->resources[0].address;
243        bar0_size = devinfo->resources[0].size;
244        page0 = (unsigned int *)(bar0 + bar0_size/2);
245
246        /* Point PAGE0 to start of Plug and Play information */
247        *page0 = priv->version->amba_ioarea & 0xf0000000;
248
249        /* set parity error response */
[8b29637c]250        pci_cfg_r32(priv->pcidev, PCIR_COMMAND, &data);
251        pci_cfg_w32(priv->pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN));
[e67b2b8d]252
[819de55b]253        /* Setup cache line size. Default cache line size will result in
254         * poor performance (256 word fetches), 0xff will set it according
255         * to the max size of the PCI FIFO.
256         */
[8b29637c]257        pci_cfg_w8(priv->pcidev, PCIR_CACHELNSZ, 0xff);
[819de55b]258
[e67b2b8d]259        /* Scan AMBA Plug&Play */
260
261        /* AMBA MAP bar0 (in CPU) ==> 0x80000000(remote amba address) */
262        priv->amba_maps[0].size = bar0_size/2;
263        priv->amba_maps[0].local_adr = bar0;
264        priv->amba_maps[0].remote_adr = 0x80000000;
265
266        /* AMBA MAP bar1 (in CPU) ==> 0x40000000(remote amba address) */
267        priv->amba_maps[1].size = devinfo->resources[1].size;
268        priv->amba_maps[1].local_adr = devinfo->resources[1].address;
269        priv->amba_maps[1].remote_adr = 0x40000000;
270
271        /* Addresses not matching with map be untouched */
272        priv->amba_maps[2].size = 0xfffffff0;
273        priv->amba_maps[2].local_adr = 0;
274        priv->amba_maps[2].remote_adr = 0;
275
276        /* Mark end of table */
277        priv->amba_maps[3].size=0;
278        priv->amba_maps[3].local_adr = 0;
279        priv->amba_maps[3].remote_adr = 0;
280
281        /* Start AMBA PnP scan at first AHB bus */
282        /*ambapp_scan(priv->bar0 + (priv->version->amba_ioarea & ~0xf0000000),
283                NULL, &priv->amba_maps[0], NULL, &priv->abus.root, NULL);*/
284        ambapp_scan(&priv->abus,
285                bar0 + (priv->version->amba_ioarea & ~0xf0000000),
286                NULL, &priv->amba_maps[0]);
287
288        /* Initialize Frequency of AMBA bus */
289        ambapp_freq_init(&priv->abus, NULL, priv->version->amba_freq_hz);
290
291        /* Point PAGE0 to start of APB area */
292        *page0 = 0x80000000;   
293
294        /* Find GRPCI controller */
[03037b4]295        tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
[e67b2b8d]296                                        (OPTIONS_ALL|OPTIONS_APB_SLVS),
297                                        VENDOR_GAISLER, GAISLER_PCIFBRG,
298                                        ambapp_find_by_idx, NULL);
299        if ( !tmp ) {
300                return -3;
301        }
302        priv->grpci = (struct grpci_regs *)((struct ambapp_apb_info *)tmp->devinfo)->start;
303
304        /* Set GRPCI mmap so that AMBA masters can access CPU-RAM over
305         * the PCI window.
306         */
307        priv->grpci->cfg_stat = (priv->grpci->cfg_stat & 0x0fffffff) |
308                                (priv->ahbmst2pci_map & 0xf0000000);
309        priv->grpci->page1 = 0x40000000;
310
311        /* Find IRQ controller */
[03037b4]312        tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
[e67b2b8d]313                                        (OPTIONS_ALL|OPTIONS_APB_SLVS),
314                                        VENDOR_GAISLER, GAISLER_IRQMP,
315                                        ambapp_find_by_idx, NULL);
316        if ( !tmp ) {
317                return -4;
318        }
319        priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start;
320        /* Set up GR-RASTA-ADCDAC irq controller */
321        priv->irq->iclear = 0xffff;
322        priv->irq->ilevel = 0;
323        priv->irq->mask[0] = 0;
324
325        /* DOWN streams translation table */
326        priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA";
327        priv->bus_maps_down[0].size = priv->amba_maps[0].size;
328        priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr;
329        priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr;
330
331        priv->bus_maps_down[1].name = "PCI BAR1 -> AMBA";
332        priv->bus_maps_down[1].size = priv->amba_maps[1].size;
333        priv->bus_maps_down[1].from_adr = (void *)priv->amba_maps[1].local_adr;
334        priv->bus_maps_down[1].to_adr = (void *)priv->amba_maps[1].remote_adr;
335
336        /* Mark end of translation table */
337        priv->bus_maps_down[2].size = 0;
338
339        /* Find GRPCI controller AHB Slave interface */
[03037b4]340        tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus,
[e67b2b8d]341                                        (OPTIONS_ALL|OPTIONS_AHB_SLVS),
342                                        VENDOR_GAISLER, GAISLER_PCIFBRG,
343                                        ambapp_find_by_idx, NULL);
344        if ( !tmp ) {
345                return -5;
346        }
347        ahb = (struct ambapp_ahb_info *)tmp->devinfo;
348
349        /* UP streams translation table */
350        priv->bus_maps_up[0].name = "AMBA GRPCI Window";
351        priv->bus_maps_up[0].size = ahb->mask[0]; /* AMBA->PCI Window on GR-RASTA-ADCDAC board */
352        priv->bus_maps_up[0].from_adr = (void *)ahb->start[0];
353        priv->bus_maps_up[0].to_adr = (void *)
354                                        (priv->ahbmst2pci_map & 0xf0000000);
355
356        /* Mark end of translation table */
357        priv->bus_maps_up[1].size = 0;
358
359        /* Successfully registered the RASTA board */
360        return 0;
361}
362
[03037b4]363static int gr_rasta_adcdac_hw_init2(struct gr_rasta_adcdac_priv *priv)
[e67b2b8d]364{
365        /* Enable DMA by enabling PCI target as master */
366        pci_master_enable(priv->pcidev);
367
368        return DRVMGR_OK;
369}
370
371/* Called when a PCI target is found with the PCI device and vendor ID
372 * given in gr_rasta_adcdac_ids[].
373 */
374int gr_rasta_adcdac_init1(struct drvmgr_dev *dev)
375{
376        struct gr_rasta_adcdac_priv *priv;
377        struct pci_dev_info *devinfo;
378        int status;
379        uint32_t bar0, bar1, bar0_size, bar1_size;
380        union drvmgr_key_value *value;
[03037b4]381        int resources_cnt;
[e67b2b8d]382
[11f3b9a]383        priv = grlib_calloc(1, sizeof(*priv));
[e67b2b8d]384        if ( !priv )
385                return DRVMGR_NOMEM;
386
387        dev->priv = priv;
388        priv->dev = dev;
389
390        /* Determine number of configurations */
[03037b4]391        resources_cnt = get_resarray_count(gr_rasta_adcdac_resources);
[e67b2b8d]392
393        /* Generate Device prefix */
394
395        strcpy(priv->prefix, "/dev/rastaadcdac0");
396        priv->prefix[16] += dev->minor_drv;
397        mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO);
398        priv->prefix[17] = '/';
399        priv->prefix[18] = '\0';
400
401        priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo;
402        priv->pcidev = devinfo->pcidev;
403        bar0 = devinfo->resources[0].address;
404        bar0_size = devinfo->resources[0].size;
405        bar1 = devinfo->resources[1].address;
406        bar1_size = devinfo->resources[1].size;
[56a7540]407        printk("\n\n--- GR-RASTA-ADCDAC[%d] ---\n", dev->minor_drv);
408        printk(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n",
[e67b2b8d]409                PCI_DEV_EXPAND(priv->pcidev));
[56a7540]410        printk(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n",
[e67b2b8d]411                devinfo->id.vendor, devinfo->id.device);
[56a7540]412        printk(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1);
413        printk(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1);
414        printk(" IRQ: %d\n\n\n", devinfo->irq);
[e67b2b8d]415
416        /* all neccessary space assigned to GR-RASTA-ADCDAC target? */
417        if ((bar0_size == 0) || (bar1_size == 0))
418                return DRVMGR_ENORES;
419
[ce76b9d2]420        /* Initialize spin-lock for this PCI perihperal device. This is to
421         * protect the Interrupt Controller Registers. The genirq layer is
422         * protecting its own internals and ISR dispatching.
423         */
424        SPIN_INIT(&priv->devlock, priv->prefix);
425
[e67b2b8d]426        /* Let user override which PCI address the AHB masters of the
427         * RASTA-ADCDAC board access when doing DMA to CPU RAM. The AHB masters
428         * access the PCI Window of the AMBA bus, the MSB 4-bits of that address
429         * is translated according this config option before the address
430         * goes out on the PCI bus.
431         * Only the 4 MSB bits have an effect;
432         */
[4d3e70f4]433        value = drvmgr_dev_key_get(priv->dev, "ahbmst2pci", DRVMGR_KT_INT);
[e67b2b8d]434        if (value)
435                priv->ahbmst2pci_map = value->i;
436        else
437                priv->ahbmst2pci_map = AHBMST2PCIADR; /* default */
438
439        priv->genirq = genirq_init(16);
440        if ( priv->genirq == NULL ) {
441                free(priv);
442                dev->priv = NULL;
443                return DRVMGR_FAIL;
444        }
445
446        if ( (status = gr_rasta_adcdac_hw_init1(priv)) != 0 ) {
447                genirq_destroy(priv->genirq);
448                free(priv);
449                dev->priv = NULL;
[56a7540]450                printk(" Failed to initialize GR-RASTA-ADCDAC HW: %d\n", status);
[e67b2b8d]451                return DRVMGR_FAIL;
452        }
453
454        /* Init amba bus */
455        priv->config.abus = &priv->abus;
456        priv->config.ops = &ambapp_rasta_adcdac_ops;
457        priv->config.maps_up = &priv->bus_maps_up[0];
458        priv->config.maps_down = &priv->bus_maps_down[0];
[03037b4]459        if ( priv->dev->minor_drv < resources_cnt ) {
[e67b2b8d]460                priv->config.resources = gr_rasta_adcdac_resources[priv->dev->minor_drv];
461        } else {
462                priv->config.resources = NULL;
463        }
464
465        /* Create and register AMBA PnP bus. */
466        return ambapp_bus_register(dev, &priv->config);
467}
468
469int gr_rasta_adcdac_init2(struct drvmgr_dev *dev)
470{
471        struct gr_rasta_adcdac_priv *priv = dev->priv;
472
473        /* Clear any old interrupt requests */
474        drvmgr_interrupt_clear(dev, 0);
475
476        /* Enable System IRQ so that GR-RASTA-ADCDAC PCI target interrupt
477         * goes through.
478         *
479         * It is important to enable it in stage init2. If interrupts were
480         * enabled in init1 this might hang the system when more than one
481         * PCI board is connected, this is because PCI interrupts might
482         * be shared and PCI board 2 have not initialized and might
483         * therefore drive interrupt already when entering init1().
484         */
485        drvmgr_interrupt_register(
486                dev,
487                0,
488                "gr_rasta_adcdac",
489                gr_rasta_adcdac_isr,
490                (void *)priv);
491
492        return gr_rasta_adcdac_hw_init2(priv);
493}
494
495int ambapp_rasta_adcdac_int_register(
496        struct drvmgr_dev *dev,
497        int irq,
498        const char *info,
499        drvmgr_isr handler,
500        void *arg)
501{
502        struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
[ce76b9d2]503        SPIN_IRQFLAGS(irqflags);
[e67b2b8d]504        int status;
[ce76b9d2]505        void *h;
[e67b2b8d]506
[ce76b9d2]507        h = genirq_alloc_handler(handler, arg);
508        if ( h == NULL )
509                return DRVMGR_FAIL;
[e67b2b8d]510
[ce76b9d2]511        SPIN_LOCK_IRQ(&priv->devlock, irqflags);
512
513        status = genirq_register(priv->genirq, irq, h);
[e67b2b8d]514        if ( status == 0 ) {
515                /* Clear IRQ for first registered handler */
516                priv->irq->iclear = (1<<irq);
517        } else if ( status == 1 )
518                status = 0;
519
520        if (status != 0) {
[ce76b9d2]521                SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
522                genirq_free_handler(h);
[e67b2b8d]523                return DRVMGR_FAIL;
524        }
525
526        status = genirq_enable(priv->genirq, irq, handler, arg);
527        if ( status == 0 ) {
528                /* Enable IRQ for first enabled handler only */
529                priv->irq->mask[0] |= (1<<irq); /* unmask interrupt source */
530        } else if ( status == 1 )
531                status = 0;
532
[ce76b9d2]533        SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
[e67b2b8d]534
535        return status;
536}
537
538int ambapp_rasta_adcdac_int_unregister(
539        struct drvmgr_dev *dev,
540        int irq,
541        drvmgr_isr isr,
542        void *arg)
543{
544        struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
[ce76b9d2]545        SPIN_IRQFLAGS(irqflags);
[e67b2b8d]546        int status;
[ce76b9d2]547        void *handler;
[e67b2b8d]548
[ce76b9d2]549        SPIN_LOCK_IRQ(&priv->devlock, irqflags);
[e67b2b8d]550
551        status = genirq_disable(priv->genirq, irq, isr, arg);
552        if ( status == 0 ) {
553                /* Disable IRQ only when no enabled handler exists */
554                priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
555        }
556
[ce76b9d2]557        handler = genirq_unregister(priv->genirq, irq, isr, arg);
558        if ( handler == NULL )
[e67b2b8d]559                status = DRVMGR_FAIL;
[ce76b9d2]560        else
561                status = DRVMGR_OK;
562
563        SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
[e67b2b8d]564
[ce76b9d2]565        if (handler)
566                genirq_free_handler(handler);
[e67b2b8d]567
568        return status;
569}
570
571int ambapp_rasta_adcdac_int_unmask(
572        struct drvmgr_dev *dev,
573        int irq)
574{
575        struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
[ce76b9d2]576        SPIN_IRQFLAGS(irqflags);
[e67b2b8d]577
578        DBG("RASTA-ADCDAC IRQ %d: unmask\n", irq);
579
580        if ( genirq_check(priv->genirq, irq) )
581                return DRVMGR_EINVAL;
582
[ce76b9d2]583        SPIN_LOCK_IRQ(&priv->devlock, irqflags);
[e67b2b8d]584
585        /* Enable IRQ for first enabled handler only */
586        priv->irq->mask[0] |= (1<<irq); /* unmask interrupt source */
587
[ce76b9d2]588        SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
[e67b2b8d]589
590        return DRVMGR_OK;
591}
592
593int ambapp_rasta_adcdac_int_mask(
594        struct drvmgr_dev *dev,
595        int irq)
596{
597        struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
[ce76b9d2]598        SPIN_IRQFLAGS(irqflags);
[e67b2b8d]599
600        DBG("RASTA-ADCDAC IRQ %d: mask\n", irq);
601
602        if ( genirq_check(priv->genirq, irq) )
603                return DRVMGR_EINVAL;
604
[ce76b9d2]605        SPIN_LOCK_IRQ(&priv->devlock, irqflags);
[e67b2b8d]606
607        /* Disable/mask IRQ */
608        priv->irq->mask[0] &= ~(1<<irq); /* mask interrupt source */
609
[ce76b9d2]610        SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
[e67b2b8d]611
612        return DRVMGR_OK;
613}
614
615int ambapp_rasta_adcdac_int_clear(
616        struct drvmgr_dev *dev,
617        int irq)
618{
619        struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
620
621        if ( genirq_check(priv->genirq, irq) )
622                return DRVMGR_FAIL;
623
624        priv->irq->iclear = (1<<irq);
625
626        return DRVMGR_OK;
627}
628
629int ambapp_rasta_adcdac_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
630{
631        struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv;
632
633        /* Device name prefix pointer, skip /dev */
634        params->dev_prefix = &priv->prefix[5];
635
636        return 0;
637}
638
639void gr_rasta_adcdac_print_dev(struct drvmgr_dev *dev, int options)
640{
641        struct gr_rasta_adcdac_priv *priv = dev->priv;
642        struct pci_dev_info *devinfo = priv->devinfo;
643        uint32_t bar0, bar1, bar0_size, bar1_size;
644
645        /* Print */
646        printf("--- GR-RASTA-ADCDAC [bus 0x%x, dev 0x%x, fun 0x%x] ---\n",
647                PCI_DEV_EXPAND(priv->pcidev));
648
649        bar0 = devinfo->resources[0].address;
650        bar0_size = devinfo->resources[0].size;
651        bar1 = devinfo->resources[1].address;
652        bar1_size = devinfo->resources[1].size;
653
654        printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1);
655        printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1);
656        printf(" IRQ REGS:        0x%x\n", (unsigned int)priv->irq);
657        printf(" IRQ:             %d\n", devinfo->irq);
658        printf(" PCI REVISION:    %d\n", devinfo->rev);
659        printf(" FREQ:            %d Hz\n", priv->version->amba_freq_hz);
660        printf(" IMASK:           0x%08x\n", priv->irq->mask[0]);
661        printf(" IPEND:           0x%08x\n", priv->irq->ipend);
662
663        /* Print amba config */
664        if ( options & RASTA_ADCDAC_OPTIONS_AMBA ) {
665                ambapp_print(&priv->abus, 10);
666        }
667#if 0
668        /* Print IRQ handlers and their arguments */
669        if ( options & RASTA_ADCDAC_OPTIONS_IRQ ) {
670                int i;
671                for(i=0; i<16; i++) {
672                        printf(" IRQ[%02d]:         0x%x, arg: 0x%x\n",
673                                i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg);
674                }
675        }
676#endif
677}
678
679void gr_rasta_adcdac_print(int options)
680{
681        struct pci_drv_info *drv = &gr_rasta_adcdac_info;
682        struct drvmgr_dev *dev;
683
684        dev = drv->general.dev;
685        while(dev) {
686                gr_rasta_adcdac_print_dev(dev, options);
687                dev = dev->next_in_drv;
688        }
689}
Note: See TracBrowser for help on using the repository browser.