source: rtems/bsps/sparc/leon2/pci/at697_pci.c @ 67e472c

5
Last change on this file since 67e472c was 67e472c, checked in by Sebastian Huber <sebastian.huber@…>, on 04/20/18 at 11:45:16

bsps/leon2: Move PCI driver to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 18.0 KB
Line 
1/*  LEON2 AT697 PCI Host Driver.
2 *
3 *  COPYRIGHT (c) 2008.
4 *  Cobham Gaisler AB.
5 *
6 *  Configures the AT697 PCI core and initialize,
7 *   - the PCI Library (pci.c)
8 *   - the general part of the PCI Bus driver (pci_bus.c)
9 * 
10 *  System interrupt assigned to PCI interrupt (INTA#..INTD#) is by
11 *  default taken from Plug and Play, but may be overridden by the
12 *  driver resources INTA#..INTD#.
13 *
14 *  The license and distribution terms for this file may be
15 *  found in found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19/* Configurable parameters
20 * =======================
21 *  INT[A..D]#         Select system IRQ (can be tranlated into I/O interrupt)
22 *  INT[A..D]#_PIO     Select PIO used to generate I/O interrupt
23 *
24 * Notes
25 * =====
26 *  IRQ must not be enabled before all PCI boards have been enabled, the
27 *  IRQ is therefore enabled first in init2. The init2() for this driver
28 *  is assumed to be executed earlier that all boards and their devices
29 *  driver's init2() function.
30 *
31 */
32
33#include <rtems/bspIo.h>
34#include <stdlib.h>
35#include <string.h>
36#include <stdio.h>
37#include <libcpu/byteorder.h>
38#include <libcpu/access.h>
39#include <pci.h>
40#include <pci/cfg.h>
41
42#include <drvmgr/drvmgr.h>
43#include <drvmgr/pci_bus.h>
44#include <drvmgr/leon2_amba_bus.h>
45
46#include <bsp/at697_pci.h>
47#include <leon.h>
48
49/* Configuration options */
50
51#define SYSTEM_MAINMEM_START    0x40000000
52#define SYSTEM_MAINMEM_START2   0x60000000
53
54/* Interrupt assignment. Set to other value than 0xff in order to
55 * override defaults and plug&play information
56 */
57#ifndef AT697_INTA_SYSIRQ
58 #define AT697_INTA_SYSIRQ 0xff
59#endif
60#ifndef AT697_INTB_SYSIRQ
61 #define AT697_INTB_SYSIRQ 0xff
62#endif
63#ifndef AT697_INTC_SYSIRQ
64 #define AT697_INTC_SYSIRQ 0xff
65#endif
66#ifndef AT697_INTD_SYSIRQ
67 #define AT697_INTD_SYSIRQ 0xff
68#endif
69
70#ifndef AT697_INTA_PIO
71 #define AT697_INTA_PIO 0xff
72#endif
73#ifndef AT697_INTB_PIO
74 #define AT697_INTB_PIO 0xff
75#endif
76#ifndef AT697_INTC_PIO
77 #define AT697_INTC_PIO 0xff
78#endif
79#ifndef AT697_INTD_PIO
80 #define AT697_INTD_PIO 0xff
81#endif
82
83
84/* AT697 PCI */
85#define AT697_PCI_REG_ADR 0x80000100
86
87/* PCI Window used */
88#define PCI_MEM_START 0xa0000000
89#define PCI_MEM_END   0xf0000000
90#define PCI_MEM_SIZE  (PCI_MEM_END - PCI_MEM_START)
91
92/* #define DEBUG 1 */
93
94#ifdef DEBUG
95#define DBG(x...) printf(x)
96#else
97#define DBG(x...)
98#endif
99
100struct at697pci_regs {
101    volatile unsigned int pciid1;        /* 0x80000100 - PCI Device identification register 1         */
102    volatile unsigned int pcisc;         /* 0x80000104 - PCI Status & Command                         */
103    volatile unsigned int pciid2;        /* 0x80000108 - PCI Device identification register 2         */
104    volatile unsigned int pcibhlc;       /* 0x8000010c - BIST, Header type, Cache line size register  */
105    volatile unsigned int mbar1;         /* 0x80000110 - Memory Base Address Register 1               */
106    volatile unsigned int mbar2;         /* 0x80000114 - Memory Base Address Register 2               */
107    volatile unsigned int iobar3;        /* 0x80000118 - IO Base Address Register 3                   */
108    volatile unsigned int dummy1[4];     /* 0x8000011c - 0x80000128                                   */
109    volatile unsigned int pcisid;        /* 0x8000012c - Subsystem identification register            */
110    volatile unsigned int dummy2;        /* 0x80000130                                                */
111    volatile unsigned int pcicp;         /* 0x80000134 - PCI capabilities pointer register            */
112    volatile unsigned int dummy3;        /* 0x80000138                                                */
113    volatile unsigned int pcili;         /* 0x8000013c - PCI latency interrupt register               */
114    volatile unsigned int pcirt;         /* 0x80000140 - PCI retry, trdy config                       */
115    volatile unsigned int pcicw;         /* 0x80000144 - PCI configuration write register             */
116    volatile unsigned int pcisa;         /* 0x80000148 - PCI Initiator Start Address                  */
117    volatile unsigned int pciiw;         /* 0x8000014c - PCI Initiator Write Register                 */
118    volatile unsigned int pcidma;        /* 0x80000150 - PCI DMA configuration register               */
119    volatile unsigned int pciis;         /* 0x80000154 - PCI Initiator Status Register                */
120    volatile unsigned int pciic;         /* 0x80000158 - PCI Initiator Configuration                  */
121    volatile unsigned int pcitpa;        /* 0x8000015c - PCI Target Page Address Register             */   
122    volatile unsigned int pcitsc;        /* 0x80000160 - PCI Target Status-Command Register           */
123    volatile unsigned int pciite;        /* 0x80000164 - PCI Interrupt Enable Register                */
124    volatile unsigned int pciitp;        /* 0x80000168 - PCI Interrupt Pending Register               */
125    volatile unsigned int pciitf;        /* 0x8000016c - PCI Interrupt Force Register                 */
126    volatile unsigned int pcid;          /* 0x80000170 - PCI Data Register                            */   
127    volatile unsigned int pcibe;         /* 0x80000174 - PCI Burst End Register                       */
128    volatile unsigned int pcidmaa;       /* 0x80000178 - PCI DMA Address Register                     */
129};
130
131/* PCI Interrupt assignment. Connects an PCI interrupt pin (INTA#..INTD#)
132 * to a system interrupt number.
133 */
134unsigned char at697_pci_irq_table[4] =
135{
136        /* INTA# */     AT697_INTA_SYSIRQ,
137        /* INTB# */     AT697_INTB_SYSIRQ,
138        /* INTC# */     AT697_INTC_SYSIRQ,
139        /* INTD# */     AT697_INTD_SYSIRQ
140};
141
142/* PCI Interrupt PIO assignment. Selects which GPIO pin will be used to
143 * generate the system IRQ.
144 *
145 * PCI IRQ -> GPIO -> 4 x I/O select -> System IRQ
146 *              ^- pio_table              ^- irq_select
147 */
148unsigned char at697_pci_irq_pio_table[4] =
149{
150        /* INTA# */     AT697_INTA_PIO,
151        /* INTB# */     AT697_INTB_PIO,
152        /* INTC# */     AT697_INTC_PIO,
153        /* INTD# */     AT697_INTD_PIO
154};
155
156/* Driver private data struture */
157struct at697pci_priv {
158        struct drvmgr_dev       *dev;
159        struct at697pci_regs    *regs;
160        int                     minor;
161
162        uint32_t                bar1_pci_adr;
163        uint32_t                bar2_pci_adr;
164
165        struct drvmgr_map_entry maps_up[3];
166        struct drvmgr_map_entry maps_down[2];
167        struct pcibus_config    config;
168};
169
170struct at697pci_priv *at697pcipriv = NULL;
171static int at697pci_minor = 0;
172
173int at697pci_init1(struct drvmgr_dev *dev);
174int at697pci_init2(struct drvmgr_dev *dev);
175
176/* AT697 PCI DRIVER */
177
178struct drvmgr_drv_ops at697pci_ops =
179{
180        .init = {at697pci_init1, at697pci_init2, NULL, NULL},
181        .remove = NULL,
182        .info = NULL
183};
184
185struct leon2_amba_dev_id at697pci_ids[] =
186{
187        {LEON2_AMBA_AT697PCI_ID},
188        {0}             /* Mark end of table */
189};
190
191struct leon2_amba_drv_info at697pci_info =
192{
193        {
194                DRVMGR_OBJ_DRV,                 /* Driver */
195                NULL,                           /* Next driver */
196                NULL,                           /* Device list */
197                DRIVER_LEON2_AMBA_AT697PCI,     /* Driver ID */
198                "AT697PCI_DRV",                 /* Driver Name */
199                DRVMGR_BUS_TYPE_LEON2_AMBA,     /* Bus Type */
200                &at697pci_ops,
201                NULL,                           /* Funcs */
202                0,                              /* No devices yet */
203                sizeof(struct at697pci_priv),   /* let drvmgr alloc private */
204        },
205        &at697pci_ids[0]
206};
207
208void at697pci_register_drv(void)
209{
210        DBG("Registering AT697 PCI driver\n");
211        drvmgr_drv_register(&at697pci_info.general);
212}
213
214/*  The configuration access functions uses the DMA functionality of the
215 *  AT697 pci controller to be able access all slots
216 */
217
218static int at697pci_cfg_r32(pci_dev_t dev, int offset, uint32_t *val)
219{
220        struct at697pci_regs *regs;
221        volatile unsigned int data = 0;
222        unsigned int address;
223        int bus = PCI_DEV_BUS(dev);
224        int slot = PCI_DEV_SLOT(dev);
225        int func = PCI_DEV_FUNC(dev);
226        int retval;
227
228        if (slot > 15 || (offset & ~0xfc)) {
229                *val = 0xffffffff;
230                return PCISTS_EINVAL;
231        }
232
233        regs = at697pcipriv->regs;
234
235        regs->pciitp = 0xff; /* clear interrupts */
236
237        if ( bus == 0 ) {
238                /* PCI Access - TYPE 0 */
239                address = (1<<(16+slot)) | (func << 8) | offset;
240        } else {
241                /* PCI access - TYPE 1 */
242                address = ((bus & 0xff) << 16) | ((slot & 0x1f) << 11) |
243                                (func << 8) | offset | 1;
244        }
245        regs->pcisa = address;
246        regs->pcidma = 0xa01;
247        regs->pcidmaa = (unsigned int) &data;
248
249        while (regs->pciitp == 0)
250                ;
251
252        regs->pciitp = 0xff; /* clear interrupts */
253
254        if (regs->pcisc & 0x20000000)  { /* Master Abort */
255                regs->pcisc |= 0x20000000;
256                *val = 0xffffffff;
257                retval = PCISTS_MSTABRT;
258        } else {
259                *val = data;
260                retval = PCISTS_OK;
261        }
262
263        DBG("pci_read - bus: %d, dev: %d, fn: %d, off: %d => addr: %x, val: %x\n",
264                bus, slot, func, offset,  address, *val);
265
266        return retval;
267}
268
269static int at697pci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *val)
270{
271        uint32_t v;
272        int retval;
273
274        if (ofs & 1)
275                return PCISTS_EINVAL;
276
277        retval = at697pci_cfg_r32(dev, ofs & ~0x3, &v);
278        *val = 0xffff & (v >> (8*(ofs & 0x3)));
279
280        return retval;
281}
282
283static int at697pci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *val)
284{
285        uint32_t v;
286        int retval;
287
288        retval = at697pci_cfg_r32(dev, ofs & ~0x3, &v);
289
290        *val = 0xff & (v >> (8*(ofs & 3)));
291
292        return retval;
293}
294
295static int at697pci_cfg_w32(pci_dev_t dev, int offset, uint32_t val)
296{
297        struct at697pci_regs *regs;
298        volatile unsigned int tmp_val = val;
299        unsigned int address;
300        int bus = PCI_DEV_BUS(dev);
301        int slot = PCI_DEV_SLOT(dev);
302        int func = PCI_DEV_FUNC(dev);
303        int retval;
304
305        if (slot > 15 || (offset & ~0xfc))
306                return PCISTS_EINVAL;
307
308        regs = at697pcipriv->regs;
309
310        regs->pciitp = 0xff; /* clear interrupts */
311
312        if ( bus == 0 ) {
313                /* PCI Access - TYPE 0 */
314                address = (1<<(16+slot)) | (func << 8) | offset;
315        } else {
316                /* PCI access - TYPE 1 */
317                address = ((bus & 0xff) << 16) | ((slot & 0x1f) << 11) |
318                                (func << 8) | offset | 1;
319        }
320        regs->pcisa = address;
321        regs->pcidma = 0xb01;
322        regs->pcidmaa = (unsigned int) &tmp_val;
323
324        while (regs->pciitp == 0)
325                ;
326
327        if (regs->pcisc & 0x20000000)  { /* Master Abort */
328                regs->pcisc |= 0x20000000;
329                retval = PCISTS_MSTABRT;
330        } else
331                retval = PCISTS_OK;
332
333        regs->pciitp = 0xff; /* clear interrupts */
334
335        DBG("pci_write - bus: %d, dev: %d, fn: %d, off: %d => addr: %x, val: %x\n",
336                bus, slot, func, offset, address, val);
337
338        return retval;
339}
340
341static int at697pci_cfg_w16(pci_dev_t dev, int ofs, uint16_t val)
342{
343        uint32_t v;
344        int retval;
345
346        if (ofs & 1)
347                return PCISTS_EINVAL;
348
349        retval = at697pci_cfg_r32(dev, ofs & ~0x3, &v);
350        if (retval != PCISTS_OK)
351                return retval;
352
353        v = (v & ~(0xffff << (8*(ofs&3)))) | ((0xffff&val) << (8*(ofs&3)));
354
355        return at697pci_cfg_w32(dev, ofs & ~0x3, v);
356}
357
358static int at697pci_cfg_w8(pci_dev_t dev, int ofs, uint8_t val)
359{
360        uint32_t v;
361
362        at697pci_cfg_r32(dev, ofs & ~0x3, &v);
363
364        v = (v & ~(0xff << (8*(ofs&3)))) | ((0xff&val) << (8*(ofs&3)));
365
366        return at697pci_cfg_w32(dev, ofs & ~0x3, v);
367}
368
369/* Return the assigned system IRQ number that corresponds to the PCI
370 * "Interrupt Pin" information from configuration space.
371 *
372 * The IRQ information is stored in the at697_pci_irq_table configurable
373 * by the user.
374 *
375 * Returns the "system IRQ" for the PCI INTA#..INTD# pin in irq_pin. Returns
376 * 0xff if not assigned.
377 */
378static uint8_t at697pci_bus0_irq_map(pci_dev_t dev, int irq_pin)
379{
380        uint8_t sysIrqNr = 0; /* not assigned */
381        int irq_group;
382
383        if ( (irq_pin >= 1) && (irq_pin <= 4) ) {
384                /* Use default IRQ decoding on PCI BUS0 according slot numbering */
385                irq_group = PCI_DEV_SLOT(dev) & 0x3;
386                irq_pin = ((irq_pin - 1) + irq_group) & 0x3;
387                /* Valid PCI "Interrupt Pin" number */
388                sysIrqNr = at697_pci_irq_table[irq_pin];
389        }
390        return sysIrqNr;
391}
392
393static int at697pci_translate(uint32_t *address, int type, int dir)
394{
395        /* No address translation implmented at this point */
396        return 0;
397}
398
399extern struct pci_memreg_ops pci_memreg_sparc_be_ops;
400
401/* AT697 Big-Endian PCI access routines */
402static struct pci_access_drv at697pci_access_drv = {
403        .cfg =
404        {
405                at697pci_cfg_r8,
406                at697pci_cfg_r16,
407                at697pci_cfg_r32,
408                at697pci_cfg_w8,
409                at697pci_cfg_w16,
410                at697pci_cfg_w32,
411        },
412        .io =
413        {       /* AT697 only supports non-standard Big-Endian PCI Bus */
414                _ld8,
415                _ld_be16,
416                _ld_be32,
417                _st8,
418                _st_be16,
419                _st_be32,
420
421        },
422        .memreg = &pci_memreg_sparc_be_ops,
423        .translate = at697pci_translate,
424};
425
426/* Initializes the AT697PCI core hardware
427 *
428 */
429static int at697pci_hw_init(struct at697pci_priv *priv)
430{
431        struct at697pci_regs *regs = priv->regs;
432        unsigned short vendor = regs->pciid1 >> 16;
433
434        /* Must match ATMEL or ESA ID */
435        if ( !((vendor == 0x1202) || (vendor == 0x1E0F)) ) {
436                /* No AT697 PCI, quit */
437                return -1;
438        }
439
440        /* If not in system slot we are not host and we must abort.
441         * This is a host only driver.
442         */
443        if ((regs->pciis & 0x1000) != 0) {
444                return -1;
445        }
446
447        /* Reset PCI Core */
448        regs->pciic = 0xffffffff;
449
450        /* Mask PCI interrupts */
451        regs->pciite = 0;
452
453        /* Map parts of AT697 main memory into PCI (for DMA) */
454        regs->mbar1  = priv->bar1_pci_adr;
455        regs->mbar2  = priv->bar2_pci_adr;
456        regs->pcitpa = (priv->bar1_pci_adr & 0xff000000) |
457                       ((priv->bar2_pci_adr>>16) & 0xff00);
458
459        /* Enable PCI master and target memory command response  */
460        regs->pcisc |= 0x40 | 0x6;
461
462        /* Set latency timer to 64 */
463        regs->pcibhlc = 0x00004000;
464
465        /* Set Inititator configuration so that AHB slave accesses generate memory read/write commands */
466        regs->pciic = 0x41;
467
468        return 0;
469}
470
471/* Initializes the AT697PCI core and driver, must be called before calling init_pci()
472 *
473 * Return values
474 *  0             Successful initalization
475 *  -1            Error during initialization.
476 */
477static int at697pci_init(struct at697pci_priv *priv)
478{
479        int pin;
480        union drvmgr_key_value *value;
481        char keyname_sysirq[6];
482        char keyname_pio[10];
483
484        /* PCI core, init private structure */
485        priv->regs = (struct at697pci_regs *) AT697_PCI_REG_ADR;
486
487        /* Init PCI interrupt assignment table to all use the interrupt routed
488         * through the GPIO core.
489         *
490         * INT[A..D]# selects system IRQ (and I/O interrupt)
491         * INT[A..D]#_PIO selects PIO used to generate I/O interrupt
492         */
493        strcpy(keyname_sysirq, "INTX#");
494        strcpy(keyname_pio, "INTX#_PIO");
495        for (pin=1; pin<5; pin++) {
496                if ( at697_pci_irq_table[pin-1] == 0xff ) {
497                        /* User may override hardcoded IRQ setup */
498                        keyname_sysirq[3] = 'A' + (pin-1);
499                        value = drvmgr_dev_key_get(priv->dev,
500                                        keyname_sysirq, DRVMGR_KT_INT);
501                        if ( value )
502                                at697_pci_irq_table[pin-1] = value->i;
503                }
504                if ( at697_pci_irq_pio_table[pin-1] == 0xff ) {
505                        /* User may override hardcoded IRQ setup */
506                        keyname_pio[3] = 'A' + (pin-1);
507                        value = drvmgr_dev_key_get(priv->dev,
508                                                keyname_pio, DRVMGR_KT_INT);
509                        if ( value )
510                                at697_pci_irq_pio_table[pin-1] = value->i;
511                }
512        }
513
514        /* Use GRPCI target BAR1 and BAR2 to map CPU RAM to PCI, this is to
515         * make it possible for PCI peripherals to do DMA directly to CPU memory
516         *
517         * Defualt is to map system RAM at pci address 0x40000000 and system
518         * SDRAM to pci address 0x60000000
519         */
520        value = drvmgr_dev_key_get(priv->dev, "tgtbar1", DRVMGR_KT_INT);
521        if (value)
522                priv->bar1_pci_adr = value->i;
523        else
524                priv->bar1_pci_adr = SYSTEM_MAINMEM_START; /* default */
525
526        value = drvmgr_dev_key_get(priv->dev, "tgtbar2", DRVMGR_KT_INT);
527        if (value)
528                priv->bar2_pci_adr = value->i;
529        else
530                priv->bar2_pci_adr = SYSTEM_MAINMEM_START2; /* default */
531
532        /* Init the PCI Core */
533        if ( at697pci_hw_init(priv) ) {
534                return -3;
535        }
536
537        /* Down streams translation table */
538        priv->maps_down[0].name = "AMBA -> PCI MEM Window";
539        priv->maps_down[0].size = 0xF0000000 - 0xA0000000;
540        priv->maps_down[0].from_adr = (void *)0xA0000000;
541        priv->maps_down[0].to_adr = (void *)0xA0000000;
542        /* End table */
543        priv->maps_down[1].size = 0;
544
545        /* Up streams translation table, 2x16Mb mapped 1:1  */
546        priv->maps_up[0].name = "Target BAR0 -> AMBA";
547        priv->maps_up[0].size = 0x01000000; /* 16Mb BAR1 */
548        priv->maps_up[0].from_adr = (void *)priv->bar1_pci_adr;
549        priv->maps_up[0].to_adr = (void *)priv->bar1_pci_adr;
550        priv->maps_up[1].name = "Target BAR1 -> AMBA";
551        priv->maps_up[1].size = 0x01000000; /* 16Mb BAR2 */
552        priv->maps_up[1].from_adr = (void *)priv->bar2_pci_adr;
553        priv->maps_up[1].to_adr = (void *)priv->bar2_pci_adr;
554        /* End table */
555        priv->maps_up[2].size = 0;
556
557        return 0;
558}
559
560/* Called when a core is found with the AMBA device and vendor ID
561 * given in at697pci_ids[].
562 */
563int at697pci_init1(struct drvmgr_dev *dev)
564{
565        struct at697pci_priv *priv;
566        struct pci_auto_setup at697pci_auto_cfg;
567
568        DBG("AT697PCI[%d] on bus %s\n", dev->minor_drv,
569                dev->parent->dev->name);
570
571        if ( at697pci_minor != 0 ) {
572                DBG("Driver only supports one PCI core\n");
573                return DRVMGR_FAIL;
574        }
575
576        at697pcipriv = priv = dev->priv;
577        if ( !priv )
578                return DRVMGR_NOMEM;
579
580        priv->dev = dev;
581        priv->minor = at697pci_minor++;
582
583        if (at697pci_init(priv)) {
584                DBG("Failed to initialize at697pci driver\n");
585                return DRVMGR_EIO;
586        }
587
588        /* Host is always Big-Endian */
589        pci_endian = PCI_BIG_ENDIAN;
590
591        if (pci_access_drv_register(&at697pci_access_drv)) {
592                /* Access routines registration failed */
593                return DRVMGR_FAIL;
594        }
595
596        /* Prepare memory MAP */
597        at697pci_auto_cfg.options = 0;
598        at697pci_auto_cfg.mem_start = 0;
599        at697pci_auto_cfg.mem_size = 0;
600        at697pci_auto_cfg.memio_start = PCI_MEM_START;
601        at697pci_auto_cfg.memio_size = PCI_MEM_SIZE;
602        at697pci_auto_cfg.io_start = 0;
603        at697pci_auto_cfg.io_size = 0;
604        at697pci_auto_cfg.irq_map = at697pci_bus0_irq_map;
605        at697pci_auto_cfg.irq_route = NULL; /* use standard routing */
606        pci_config_register(&at697pci_auto_cfg);
607
608        if (pci_config_init()) {
609                /* PCI configuration failed */
610                return DRVMGR_FAIL;
611        }
612
613        priv->config.maps_down = &priv->maps_down[0];
614        priv->config.maps_up = &priv->maps_up[0];
615        return pcibus_register(dev, &priv->config);
616}
617
618int at697pci_init2(struct drvmgr_dev *dev)
619{
620#if 0
621        struct at697pci_priv *priv = dev->priv;
622#endif
623        int pin, irq, pio, ioport;
624        LEON_Register_Map *regs = (LEON_Register_Map *)0x80000000;
625
626        /* Enable interrupts now that init1 has been reached for all devices
627         * on the bus.
628         */
629
630        for (pin=1; pin<5; pin++) {
631                irq = at697_pci_irq_table[pin-1];
632                pio = at697_pci_irq_pio_table[pin-1];
633                if ( (pio < 16) && (irq >= 4) && (irq <= 7) ) {
634                        /* AT697 I/O IRQ, we know how to set up this
635                         *
636                         * IRQ 4 -> I/O 0
637                         * IRQ 5 -> I/O 1
638                         * IRQ 6 -> I/O 2
639                         * IRQ 7 -> I/O 3
640                         */
641                        ioport = irq - 4;
642
643                        /* First disable interrupts */
644                        regs->PIO_Interrupt &= ~(0xff << (ioport * 8));
645                        /* Set PIO as input pin */
646                        regs->PIO_Direction &= ~(1 << pio);
647                        /* Set Low Level sensitivity */
648                        regs->PIO_Interrupt |= ((0x80 | pio) << (ioport * 8));
649                }
650        }
651
652        /* Unmask Interrupt */
653        /*priv->regs->pciite = 0xff;*/
654
655        return DRVMGR_OK;
656}
Note: See TracBrowser for help on using the repository browser.