source: rtems/c/src/lib/libbsp/sparc/shared/pci/grpci.c @ 51347053

4.11
Last change on this file since 51347053 was 51347053, checked in by Daniel Hellstrom <daniel@…>, on Jul 1, 2013 at 1:00:21 PM

LEON PCI: host bridge driver support for probing dev0=AD16

Before the LIBPCI didn't probe device0 (AD16), the host bridge
drivers used bus=dev=func=0 to internally probe the host bridge's
target interface. Now that LIBPCI uses bus=dev=func=0 to access
device0, bus=0xff is introduced internally to identify the
host bridge target configuration space.

  • Property mode set to 100644
File size: 18.0 KB
Line 
1/*  GRLIB GRPCI PCI HOST driver.
2 *
3 *  COPYRIGHT (c) 2008.
4 *  Cobham Gaisler AB.
5 *
6 *  Configures the GRPCI 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.com/license/LICENSE.
17 */
18
19#include <stdlib.h>
20#include <stdio.h>
21#include <string.h>
22#include <rtems/bspIo.h>
23#include <libcpu/byteorder.h>
24#include <libcpu/access.h>
25#include <pci.h>
26#include <pci/cfg.h>
27
28#include <drvmgr/drvmgr.h>
29#include <drvmgr/ambapp_bus.h>
30#include <ambapp.h>
31#include <drvmgr/pci_bus.h>
32
33#define DMAPCI_ADDR 0x80000500
34
35/* Configuration options */
36#define SYSTEM_MAINMEM_START 0x40000000
37
38/* If defined to 1 - byte twisting is enabled by default */
39#define DEFAULT_BT_ENABLED 0
40
41/* Interrupt assignment. Set to other value than 0xff in order to
42 * override defaults and plug&play information
43 */
44#ifndef GRPCI_INTA_SYSIRQ
45 #define GRPCI_INTA_SYSIRQ 0xff
46#endif
47#ifndef GRPCI_INTB_SYSIRQ
48 #define GRPCI_INTB_SYSIRQ 0xff
49#endif
50#ifndef GRPCI_INTC_SYSIRQ
51 #define GRPCI_INTC_SYSIRQ 0xff
52#endif
53#ifndef GRPCI_INTD_SYSIRQ
54 #define GRPCI_INTD_SYSIRQ 0xff
55#endif
56
57#define PAGE0_BTEN_BIT    0
58#define PAGE0_BTEN        (1<<PAGE0_BTEN_BIT)
59
60#define CFGSTAT_HOST_BIT  13
61#define CFGSTAT_HOST      (1<<CFGSTAT_HOST_BIT)
62
63/*#define DEBUG 1*/
64
65#ifdef DEBUG
66#define DBG(x...) printk(x)
67#else
68#define DBG(x...)
69#endif
70
71#define PCI_INVALID_VENDORDEVICEID      0xffffffff
72#define PCI_MULTI_FUNCTION              0x80
73
74/*
75 * Bit encode for PCI_CONFIG_HEADER_TYPE register
76 */
77struct grpci_regs {
78        volatile unsigned int cfg_stat;
79        volatile unsigned int bar0;
80        volatile unsigned int page0;
81        volatile unsigned int bar1;
82        volatile unsigned int page1;
83        volatile unsigned int iomap;
84        volatile unsigned int stat_cmd;
85        volatile unsigned int irq;
86};
87
88#define HOST_TGT PCI_DEV(0xff, 0, 0)
89
90struct grpci_priv *grpcipriv = NULL;
91static int grpci_minor = 0;
92static unsigned int *pcidma = (unsigned int *)DMAPCI_ADDR;
93
94/* PCI Interrupt assignment. Connects an PCI interrupt pin (INTA#..INTD#)
95 * to a system interrupt number.
96 */
97unsigned char grpci_pci_irq_table[4] =
98{
99        /* INTA# */     GRPCI_INTA_SYSIRQ,
100        /* INTB# */     GRPCI_INTB_SYSIRQ,
101        /* INTC# */     GRPCI_INTC_SYSIRQ,
102        /* INTD# */     GRPCI_INTD_SYSIRQ
103};
104
105/* Driver private data struture */
106struct grpci_priv {
107        struct drvmgr_dev       *dev;
108        struct grpci_regs               *regs;
109        int                             irq;
110        int                             minor;
111
112        uint32_t                        bar1_pci_adr;
113        uint32_t                        bar1_size;
114
115        int                             bt_enabled;
116        unsigned int                    pci_area;
117        unsigned int                    pci_area_end;
118        unsigned int                    pci_io;   
119        unsigned int                    pci_conf;
120        unsigned int                    pci_conf_end;
121
122        uint32_t                        devVend; /* Host PCI Vendor/Device ID */
123
124        struct drvmgr_map_entry maps_up[2];
125        struct drvmgr_map_entry maps_down[2];
126        struct pcibus_config    config;
127};
128
129int grpci_init1(struct drvmgr_dev *dev);
130
131/* GRPCI DRIVER */
132
133struct drvmgr_drv_ops grpci_ops = 
134{
135        .init = {grpci_init1, NULL, NULL, NULL},
136        .remove = NULL,
137        .info = NULL
138};
139
140struct amba_dev_id grpci_ids[] = 
141{
142        {VENDOR_GAISLER, GAISLER_PCIFBRG},
143        {0, 0}          /* Mark end of table */
144};
145
146struct amba_drv_info grpci_info =
147{
148        {
149                DRVMGR_OBJ_DRV,                 /* Driver */
150                NULL,                           /* Next driver */
151                NULL,                           /* Device list */
152                DRIVER_AMBAPP_GAISLER_GRPCI_ID, /* Driver ID */
153                "GRPCI_DRV",                    /* Driver Name */
154                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
155                &grpci_ops,
156                NULL,                           /* Funcs */
157                0,                              /* No devices yet */
158                sizeof(struct grpci_priv),      /* Make drvmgr alloc private */
159        },
160        &grpci_ids[0]
161};
162
163void grpci_register_drv(void)
164{
165        DBG("Registering GRPCI driver\n");
166        drvmgr_drv_register(&grpci_info.general);
167}
168
169int grpci_cfg_r32(pci_dev_t dev, int ofs, uint32_t *val)
170{
171        struct grpci_priv *priv = grpcipriv;
172        volatile uint32_t *pci_conf;
173        uint32_t devfn;
174        int retval;
175        int bus = PCI_DEV_BUS(dev);
176
177        if (ofs & 3)
178                return PCISTS_EINVAL;
179
180        if (PCI_DEV_SLOT(dev) > 15) {
181                *val = 0xffffffff;
182                return PCISTS_OK;
183        }
184
185        /* GRPCI can access "non-standard" devices on bus0 (on AD11.AD16),
186         * but we skip them.
187         */
188        if (dev == HOST_TGT)
189                bus = devfn = 0;
190        if (bus == 0)
191                devfn = PCI_DEV_DEVFUNC(dev) + PCI_DEV(0, 6, 0);
192        else
193                devfn = PCI_DEV_DEVFUNC(dev);
194
195        /* Select bus */
196        priv->regs->cfg_stat = (priv->regs->cfg_stat & ~(0xf<<23)) | (bus<<23);
197
198        pci_conf = (volatile uint32_t *)(priv->pci_conf | (devfn << 8) | ofs);
199
200        if (priv->bt_enabled) {
201                *val =  CPU_swap_u32(*pci_conf);
202        } else {
203                *val = *pci_conf;
204        }
205
206        if (priv->regs->cfg_stat & 0x100) {
207                *val = 0xffffffff;
208                retval = PCISTS_MSTABRT;
209        } else
210                retval = PCISTS_OK;
211
212        DBG("pci_read: [%x:%x:%x] reg: 0x%x => addr: 0x%x, val: 0x%x\n",
213                PCI_DEV_EXPAND(dev), ofs, pci_conf, *val);
214
215        return retval;
216}
217
218
219int grpci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *val)
220{
221        uint32_t v;
222        int retval;
223
224        if (ofs & 1)
225                return PCISTS_EINVAL;
226
227        retval = grpci_cfg_r32(dev, ofs & ~0x3, &v);
228        *val = 0xffff & (v >> (8*(ofs & 0x3)));
229
230        return retval;
231}
232
233int grpci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *val)
234{
235        uint32_t v;
236        int retval;
237
238        retval = grpci_cfg_r32(dev, ofs & ~0x3, &v);
239
240        *val = 0xff & (v >> (8*(ofs & 3)));
241
242        return retval;
243}
244
245int grpci_cfg_w32(pci_dev_t dev, int ofs, uint32_t val)
246{
247        struct grpci_priv *priv = grpcipriv;
248        volatile uint32_t *pci_conf;
249        uint32_t value, devfn = PCI_DEV_DEVFUNC(dev);
250        int bus = PCI_DEV_BUS(dev);
251
252        if (ofs & 0x3)
253                return PCISTS_EINVAL;
254
255        if (PCI_DEV_SLOT(dev) > 15)
256                return PCISTS_MSTABRT;
257
258        /* GRPCI can access "non-standard" devices on bus0 (on AD11.AD16),
259         * but we skip them.
260         */
261        if (dev == HOST_TGT)
262                bus = devfn = 0;
263        if (bus == 0)
264                devfn = PCI_DEV_DEVFUNC(dev) + PCI_DEV(0, 6, 0);
265        else
266                devfn = PCI_DEV_DEVFUNC(dev);
267
268        /* Select bus */
269        priv->regs->cfg_stat = (priv->regs->cfg_stat & ~(0xf<<23)) | (bus<<23);
270
271        pci_conf = (volatile uint32_t *)(priv->pci_conf | (devfn << 8) | ofs);
272
273        if ( priv->bt_enabled ) {
274                value = CPU_swap_u32(val);
275        } else {
276                value = val;
277        }
278
279        *pci_conf = value;
280
281        DBG("pci_write - [%x:%x:%x] reg: 0x%x => addr: 0x%x, val: 0x%x\n",
282                PCI_DEV_EXPAND(dev), ofs, pci_conf, value);
283
284        return PCISTS_OK;
285}
286
287int grpci_cfg_w16(pci_dev_t dev, int ofs, uint16_t val)
288{
289        uint32_t v;
290        int retval;
291
292        if (ofs & 1)
293                return PCISTS_EINVAL;
294
295        retval = grpci_cfg_r32(dev, ofs & ~0x3, &v);
296        if (retval != PCISTS_OK)
297                return retval;
298
299        v = (v & ~(0xffff << (8*(ofs&3)))) | ((0xffff&val) << (8*(ofs&3)));
300
301        return grpci_cfg_w32(dev, ofs & ~0x3, v);
302}
303
304int grpci_cfg_w8(pci_dev_t dev, int ofs, uint8_t val)
305{
306        uint32_t v;
307        int retval;
308
309        retval = grpci_cfg_r32(dev, ofs & ~0x3, &v);
310        if (retval != PCISTS_OK)
311                return retval;
312
313        v = (v & ~(0xff << (8*(ofs&3)))) | ((0xff&val) << (8*(ofs&3)));
314
315        return grpci_cfg_w32(dev, ofs & ~0x3, v);
316}
317
318/* Return the assigned system IRQ number that corresponds to the PCI
319 * "Interrupt Pin" information from configuration space.
320 *
321 * The IRQ information is stored in the grpci_pci_irq_table configurable
322 * by the user.
323 *
324 * Returns the "system IRQ" for the PCI INTA#..INTD# pin in irq_pin. Returns
325 * 0xff if not assigned.
326 */
327uint8_t grpci_bus0_irq_map(pci_dev_t dev, int irq_pin)
328{
329        uint8_t sysIrqNr = 0; /* not assigned */
330        int irq_group;
331
332        if ( (irq_pin >= 1) && (irq_pin <= 4) ) {
333                /* Use default IRQ decoding on PCI BUS0 according slot numbering */
334                irq_group = PCI_DEV_SLOT(dev) & 0x3;
335                irq_pin = ((irq_pin - 1) + irq_group) & 0x3;
336                /* Valid PCI "Interrupt Pin" number */
337                sysIrqNr = grpci_pci_irq_table[irq_pin];
338        }
339        return sysIrqNr;
340}
341
342int grpci_translate(uint32_t *address, int type, int dir)
343{
344        uint32_t adr;
345        struct grpci_priv *priv = grpcipriv;
346
347        if (type == 1) {
348                /* I/O */
349                if (dir != 0) {
350                        /* The PCI bus can not access the CPU bus from I/O
351                         * because GRPCI core does not support I/O BARs
352                         */
353                        return -1;
354                }
355
356                /* We have got a PCI BAR address that the CPU want to access...
357                 * Check that it is within the PCI I/O window, I/O adresses
358                 * are mapped 1:1 with GRPCI driver... no translation needed.
359                 */
360                adr = *(uint32_t *)address;
361                if (adr < priv->pci_io || adr >= priv->pci_conf)
362                        return -1;
363        } else {
364                /* MEMIO and MEM.
365                 * Memory space is mapped 1:1 so no translation is needed.
366                 * Check that address is within accessible windows.
367                 */
368                adr = *(uint32_t *)address;
369                if (dir == 0) {
370                        /* PCI BAR to AMBA-CPU address.. check that it is
371                         * located within GRPCI PCI Memory Window
372                         * adr = PCI address.
373                         */
374                        if (adr < priv->pci_area || adr >= priv->pci_area_end)
375                                return -1;
376                } else {
377                        /* We have a CPU address and want to get access to it
378                         * from PCI space, typically when doing DMA into CPU
379                         * RAM. The GRPCI core has two target BARs that PCI
380                         * masters can access, we check here that the address
381                         * is accessible from PCI.
382                         * adr = AMBA address.
383                         */
384                        if (adr < priv->bar1_pci_adr ||
385                            adr >= (priv->bar1_pci_adr + priv->bar1_size))
386                                return -1;
387                }
388        }
389
390        return 0;
391}
392
393extern struct pci_memreg_ops pci_memreg_sparc_le_ops;
394extern struct pci_memreg_ops pci_memreg_sparc_be_ops;
395
396/* GRPCI PCI access routines, default to Little-endian PCI Bus */
397struct pci_access_drv grpci_access_drv = {
398        .cfg =
399        {
400                grpci_cfg_r8,
401                grpci_cfg_r16,
402                grpci_cfg_r32,
403                grpci_cfg_w8,
404                grpci_cfg_w16,
405                grpci_cfg_w32,
406        },
407        .io =
408        {
409                _ld8,
410                _ld_le16,
411                _ld_le32,
412                _st8,
413                _st_le16,
414                _st_le32,
415        },
416        .memreg = &pci_memreg_sparc_le_ops,
417        .translate = grpci_translate,
418};
419
420struct pci_io_ops grpci_io_ops_be =
421{
422        _ld8,
423        _ld_be16,
424        _ld_be32,
425        _st8,
426        _st_be16,
427        _st_be32,
428};
429
430int grpci_hw_init(struct grpci_priv *priv)
431{
432        volatile unsigned int *mbar0, *page0;
433        uint32_t data, addr, mbar0size;
434        pci_dev_t host = HOST_TGT;
435
436        mbar0 = (volatile unsigned int *)priv->pci_area;
437
438        if ( !priv->bt_enabled && ((priv->regs->page0 & PAGE0_BTEN) == PAGE0_BTEN) ) {
439                /* Byte twisting is on, turn it off */
440                grpci_cfg_w32(host, PCI_BASE_ADDRESS_0, 0xffffffff);
441                grpci_cfg_r32(host, PCI_BASE_ADDRESS_0, &addr);
442                /* Setup bar0 to nonzero value */
443                grpci_cfg_w32(host, PCI_BASE_ADDRESS_0,
444                                CPU_swap_u32(0x80000000));
445                /* page0 is accessed through upper half of bar0 */
446                addr = (~CPU_swap_u32(addr)+1)>>1;
447                mbar0size = addr*2;
448                DBG("GRPCI: Size of MBAR0: 0x%x, MBAR0: 0x%x(lower) 0x%x(upper)\n",mbar0size,((unsigned int)mbar0),((unsigned int)mbar0)+mbar0size/2);
449                page0 = &mbar0[mbar0size/8];
450                DBG("GRPCI: PAGE0 reg address: 0x%x (0x%x)\n",((unsigned int)mbar0)+mbar0size/2,page0);
451                priv->regs->cfg_stat = (priv->regs->cfg_stat & (~0xf0000000)) | 0x80000000;    /* Setup mmap reg so we can reach bar0 */ 
452                *page0 = 0<<PAGE0_BTEN_BIT;                                         /* Disable bytetwisting ... */
453        }
454
455        /* Get the GRPCI Host PCI ID */
456        grpci_cfg_r32(host, PCI_VENDOR_ID, &priv->devVend);
457
458        /* set 1:1 mapping between AHB -> PCI memory */
459        priv->regs->cfg_stat = (priv->regs->cfg_stat & 0x0fffffff) | priv->pci_area;
460
461        /* determine size of target BAR1 */
462        grpci_cfg_w32(host, PCI_BASE_ADDRESS_1, 0xffffffff);
463        grpci_cfg_r32(host, PCI_BASE_ADDRESS_1, &addr);
464        priv->bar1_size = (~(addr & ~0xf)) + 1;
465
466        /* and map system RAM at pci address 0x40000000 */
467        priv->bar1_pci_adr &= ~(priv->bar1_size - 1); /* Fix alignment of BAR1 */
468        grpci_cfg_w32(host, PCI_BASE_ADDRESS_1, priv->bar1_pci_adr);
469        priv->regs->page1 = priv->bar1_pci_adr;
470
471        /* Translate I/O accesses 1:1 */
472        priv->regs->iomap = priv->pci_io & 0xffff0000;
473
474        /* Setup Latency Timer and cache line size. Default cache line
475         * size will result in poor performance (256 word fetches), 0xff
476         * will set it according to the max size of the PCI FIFO.
477         */
478        grpci_cfg_w8(host, PCI_CACHE_LINE_SIZE, 0xff);
479        grpci_cfg_w8(host, PCI_LATENCY_TIMER, 0x40);
480
481        /* set as bus master and enable pci memory responses */ 
482        grpci_cfg_r32(host, PCI_COMMAND, &data);
483        data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
484        grpci_cfg_w32(host, PCI_COMMAND, data);
485
486        /* unmask all PCI interrupts at PCI Core, not all GRPCI cores support
487         * this
488         */
489        priv->regs->irq = 0xf0000;
490
491        /* Successful */
492        return 0;
493}
494
495/* Initializes the GRPCI core and driver, must be called before calling init_pci()
496 *
497 * Return values
498 *  0             Successful initalization
499 *  -1            Error during initialization, for example "PCI core not found".
500 *  -2            Error PCI controller not HOST (targets not supported)
501 *  -3            Error due to GRPCI hardware initialization
502 *  -4            Error registering driver to PCI layer
503 */
504int grpci_init(struct grpci_priv *priv)
505{
506        struct ambapp_apb_info *apb;
507        struct ambapp_ahb_info *ahb;
508        int pin;
509        union drvmgr_key_value *value;
510        char keyname[6];
511        struct amba_dev_info *ainfo = priv->dev->businfo;
512
513        /* Find PCI core from Plug&Play information */
514        apb = ainfo->info.apb_slv;
515        ahb = ainfo->info.ahb_slv;
516
517        /* Found PCI core, init private structure */
518        priv->irq = apb->irq;
519        priv->regs = (struct grpci_regs *)apb->start;
520        priv->bt_enabled = DEFAULT_BT_ENABLED;
521
522        /* Calculate the PCI windows
523         *  AMBA->PCI Window:                       AHB SLAVE AREA0
524         *  AMBA->PCI I/O cycles Window:            AHB SLAVE AREA1 Lower half
525         *  AMBA->PCI Configuration cycles Window:  AHB SLAVE AREA1 Upper half
526         */
527        priv->pci_area     = ahb->start[0];
528        priv->pci_area_end = ahb->start[0] + ahb->mask[0];
529        priv->pci_io       = ahb->start[1];
530        priv->pci_conf     = ahb->start[1] + (ahb->mask[1] >> 1);
531        priv->pci_conf_end = ahb->start[1] + ahb->mask[1];
532
533        /* On systems where PCI I/O area and configuration area is apart of the "PCI Window"
534         * the PCI Window stops at the start of the PCI I/O area
535         */
536        if ( (priv->pci_io > priv->pci_area) && (priv->pci_io < (priv->pci_area_end-1)) ) {
537                priv->pci_area_end = priv->pci_io;
538        }
539
540        /* Init PCI interrupt assignment table to all use the interrupt routed through
541         * the GRPCI core.
542         */
543        strcpy(keyname, "INTX#");
544        for (pin=1; pin<5; pin++) {
545                if ( grpci_pci_irq_table[pin-1] == 0xff ) {
546                        grpci_pci_irq_table[pin-1] = priv->irq;
547
548                        /* User may override Both hardcoded IRQ setup and Plug & Play IRQ */
549                        keyname[3] = 'A' + (pin-1);
550                        value = drvmgr_dev_key_get(priv->dev, keyname, KEY_TYPE_INT);
551                        if ( value )
552                                grpci_pci_irq_table[pin-1] = value->i;
553                }
554        }
555
556        /* User may override DEFAULT_BT_ENABLED to enable/disable byte twisting */
557        value = drvmgr_dev_key_get(priv->dev, "byteTwisting", KEY_TYPE_INT);
558        if ( value )
559                priv->bt_enabled = value->i;
560
561        /* Use GRPCI target BAR1 to map CPU RAM to PCI, this is to make it
562         * possible for PCI peripherals to do DMA directly to CPU memory.
563         */
564        value = drvmgr_dev_key_get(priv->dev, "tgtbar1", KEY_TYPE_INT);
565        if (value)
566                priv->bar1_pci_adr = value->i;
567        else
568                priv->bar1_pci_adr = SYSTEM_MAINMEM_START; /* default */
569
570        /* This driver only support HOST systems, we check for HOST */
571        if ( !(priv->regs->cfg_stat & CFGSTAT_HOST) ) {
572                /* Target not supported */
573                return -2;
574        }
575
576        /* Init the PCI Core */
577        if ( grpci_hw_init(priv) ) {
578                return -3;
579        }
580
581        /* Down streams translation table */
582        priv->maps_down[0].name = "AMBA -> PCI MEM Window";
583        priv->maps_down[0].size = priv->pci_area_end - priv->pci_area;
584        priv->maps_down[0].from_adr = (void *)priv->pci_area;
585        priv->maps_down[0].to_adr = (void *)priv->pci_area;
586        /* End table */
587        priv->maps_down[1].size = 0;
588
589        /* Up streams translation table */
590        priv->maps_up[0].name = "Target BAR1 -> AMBA";
591        priv->maps_up[0].size = priv->bar1_size;
592        priv->maps_up[0].from_adr = (void *)priv->bar1_pci_adr;
593        priv->maps_up[0].to_adr = (void *)priv->bar1_pci_adr;
594        /* End table */
595        priv->maps_up[1].size = 0;
596
597        return 0;
598}
599
600/* Called when a core is found with the AMBA device and vendor ID
601 * given in grpci_ids[]. IRQ, Console does not work here
602 */
603int grpci_init1(struct drvmgr_dev *dev)
604{
605        int status;
606        struct grpci_priv *priv;
607        struct pci_auto_setup grpci_auto_cfg;
608
609        DBG("GRPCI[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
610
611        if ( grpci_minor != 0 ) {
612                DBG("Driver only supports one PCI core\n");
613                return DRVMGR_FAIL;
614        }
615
616        if ( (strcmp(dev->parent->dev->drv->name, "AMBAPP_GRLIB_DRV") != 0) && 
617             (strcmp(dev->parent->dev->drv->name, "AMBAPP_LEON2_DRV") != 0) ) {
618                /* We only support GRPCI driver on local bus */
619                return DRVMGR_FAIL;
620        }
621
622        priv = dev->priv;
623        if ( !priv )
624                return DRVMGR_NOMEM;
625
626        priv->dev = dev;
627        priv->minor = grpci_minor++;
628
629        grpcipriv = priv;
630        status = grpci_init(priv);
631        if (status) {
632                printf("Failed to initialize grpci driver %d\n", status);
633                return DRVMGR_FAIL;
634        }
635
636
637        /* Register the PCI core at the PCI layers */
638
639        if (priv->bt_enabled == 0) {
640                /* Host is Big-Endian */
641                pci_endian = PCI_BIG_ENDIAN;
642
643                memcpy(&grpci_access_drv.io, &grpci_io_ops_be,
644                                                sizeof(grpci_io_ops_be));
645                grpci_access_drv.memreg = &pci_memreg_sparc_be_ops;
646        }
647
648        if (pci_access_drv_register(&grpci_access_drv)) {
649                /* Access routines registration failed */
650                return DRVMGR_FAIL;
651        }
652
653        /* Prepare memory MAP */
654        grpci_auto_cfg.options = 0;
655        grpci_auto_cfg.mem_start = 0;
656        grpci_auto_cfg.mem_size = 0;
657        grpci_auto_cfg.memio_start = priv->pci_area;
658        grpci_auto_cfg.memio_size = priv->pci_area_end - priv->pci_area;
659        grpci_auto_cfg.io_start = priv->pci_io;
660        grpci_auto_cfg.io_size = priv->pci_conf - priv->pci_io;
661        grpci_auto_cfg.irq_map = grpci_bus0_irq_map;
662        grpci_auto_cfg.irq_route = NULL; /* use standard routing */
663        pci_config_register(&grpci_auto_cfg);
664
665        if (pci_config_init()) {
666                /* PCI configuration failed */
667                return DRVMGR_FAIL;
668        }
669
670        priv->config.maps_down = &priv->maps_down[0];
671        priv->config.maps_up = &priv->maps_up[0];
672        return pcibus_register(dev, &priv->config);
673}
674
675/* DMA functions which uses GRPCIs optional DMA controller (len in words) */
676int grpci_dma_to_pci(unsigned int ahb_addr, unsigned int pci_addr, unsigned int len) {
677    int ret = 0;
678
679    pcidma[0] = 0x82;
680    pcidma[1] = ahb_addr;
681    pcidma[2] = pci_addr;
682    pcidma[3] = len;
683    pcidma[0] = 0x83;       
684
685    while ( (pcidma[0] & 0x4) == 0)
686        ;
687
688    if (pcidma[0] & 0x8) { /* error */ 
689        ret = -1;
690    }
691
692    pcidma[0] |= 0xC; 
693    return ret;
694
695}
696
697int grpci_dma_from_pci(unsigned int ahb_addr, unsigned int pci_addr, unsigned int len) {
698    int ret = 0;
699
700    pcidma[0] = 0x80;
701    pcidma[1] = ahb_addr;
702    pcidma[2] = pci_addr;
703    pcidma[3] = len;
704    pcidma[0] = 0x81;       
705
706    while ( (pcidma[0] & 0x4) == 0)
707        ;
708
709    if (pcidma[0] & 0x8) { /* error */ 
710        ret = -1;
711    }
712
713    pcidma[0] |= 0xC; 
714    return ret;
715
716}
Note: See TracBrowser for help on using the repository browser.