source: rtems/c/src/lib/libbsp/sparc/leon2/pci/pci.c @ 8bbf69e

4.11
Last change on this file since 8bbf69e was 8bbf69e, checked in by Joel Sherrill <joel.sherrill@…>, on May 16, 2012 at 9:04:10 PM

pci.h cleanup - Consolidate common defines to cpukit pci.h

+ libbsp/sparc/shared/include/pci.h was largely a copy of

an older version of the cpukit pci.h. Removed much of the
contents and included <rtems/pci.h>.

+ sparc/*/pci*.c - Move to <rtems/pci.h> required updating

to use uint32_t for dword accesses.

+ Rename PCI_MULTI_FUNCTION to PCI_HEADER_TYPE_MULTI_FUNCTION
+ Define PCI_HEADER_TYPE_MULTI_FUNCTION in cpukit pci.h and remove

PCI_MULTI_FUNCTION definitions in C files.

+ Move PCI_INVALID_VENDORDEVICEID definitions from various C files

to cpukit pci.h

  • Property mode set to 100644
File size: 19.2 KB
Line 
1/*
2 * pci.c :  this file contains basic PCI Io functions.
3 *
4 *  Copyright (C) 1999 valette@crf.canon.fr
5 *
6 *  This code is heavily inspired by the public specification of STREAM V2
7 *  that can be found at :
8 *
9 *      <http://www.chorus.com/Documentation/index.html> by following
10 *  the STREAM API Specification Document link.
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
15 *
16 *  Till Straumann, <strauman@slac.stanford.edu>, 1/2002
17 *   - separated bridge detection code out of this file
18 *
19 *  Adapted to LEON2 AT697 PCI
20 *  Copyright (C) 2006 Gaisler Research
21 *
22 */
23
24#include <pci.h>
25#include <rtems/bspIo.h>
26#include <stdlib.h>
27
28/* Define PCI_INFO to get a listing of configured devices at boot time */
29#define PCI_INFO 1
30
31/* #define DEBUG 1 */
32
33#ifdef DEBUG
34#define DBG(x...) printk(x)
35#else
36#define DBG(x...)
37#endif
38
39/* allow for overriding these definitions */
40#ifndef PCI_CONFIG_ADDR
41#define PCI_CONFIG_ADDR                 0xcf8
42#endif
43#ifndef PCI_CONFIG_DATA
44#define PCI_CONFIG_DATA                 0xcfc
45#endif
46
47/* define a shortcut */
48#define pci     BSP_pci_configuration
49
50/*
51 * Bit encode for PCI_CONFIG_HEADER_TYPE register
52 */
53unsigned char ucMaxPCIBus;
54
55typedef struct {
56    volatile unsigned int pciid1;        /* 0x80000100 - PCI Device identification register 1         */
57    volatile unsigned int pcisc;         /* 0x80000104 - PCI Status & Command                         */
58    volatile unsigned int pciid2;        /* 0x80000108 - PCI Device identification register 2         */
59    volatile unsigned int pcibhlc;       /* 0x8000010c - BIST, Header type, Cache line size register  */
60    volatile unsigned int mbar1;         /* 0x80000110 - Memory Base Address Register 1               */
61    volatile unsigned int mbar2;         /* 0x80000114 - Memory Base Address Register 2               */
62    volatile unsigned int iobar3;        /* 0x80000118 - IO Base Address Register 3                   */
63    volatile unsigned int dummy1[4];     /* 0x8000011c - 0x80000128                                   */
64    volatile unsigned int pcisid;        /* 0x8000012c - Subsystem identification register            */
65    volatile unsigned int dummy2;        /* 0x80000130                                                */
66    volatile unsigned int pcicp;         /* 0x80000134 - PCI capabilities pointer register            */
67    volatile unsigned int dummy3;        /* 0x80000138                                                */
68    volatile unsigned int pcili;         /* 0x8000013c - PCI latency interrupt register               */
69    volatile unsigned int pcirt;         /* 0x80000140 - PCI retry, trdy config                       */
70    volatile unsigned int pcicw;         /* 0x80000144 - PCI configuration write register             */
71    volatile unsigned int pcisa;         /* 0x80000148 - PCI Initiator Start Address                  */
72    volatile unsigned int pciiw;         /* 0x8000014c - PCI Initiator Write Register                 */
73    volatile unsigned int pcidma;        /* 0x80000150 - PCI DMA configuration register               */
74    volatile unsigned int pciis;         /* 0x80000154 - PCI Initiator Status Register                */
75    volatile unsigned int pciic;         /* 0x80000158 - PCI Initiator Configuration                  */
76    volatile unsigned int pcitpa;        /* 0x8000015c - PCI Target Page Address Register             */
77    volatile unsigned int pcitsc;        /* 0x80000160 - PCI Target Status-Command Register           */
78    volatile unsigned int pciite;        /* 0x80000164 - PCI Interrupt Enable Register                */
79    volatile unsigned int pciitp;        /* 0x80000168 - PCI Interrupt Pending Register               */
80    volatile unsigned int pciitf;        /* 0x8000016c - PCI Interrupt Force Register                 */
81    volatile unsigned int pcid;          /* 0x80000170 - PCI Data Register                            */
82    volatile unsigned int pcibe;         /* 0x80000174 - PCI Burst End Register                       */
83    volatile unsigned int pcidmaa;       /* 0x80000178 - PCI DMA Address Register                     */
84} AT697_PCI_Map;
85
86AT697_PCI_Map *pcic = (AT697_PCI_Map *) 0x80000100;
87
88#define PCI_MEM_START 0xa0000000
89#define PCI_MEM_END   0xf0000000
90#define PCI_MEM_SIZE  (PCI_MEM_START - PCI_MEM_END)
91
92
93struct pci_res {
94    unsigned int size;
95    unsigned char bar;
96    unsigned char devfn;
97};
98
99/*  The configuration access functions uses the DMA functionality of the
100 *  AT697 pci controller to be able access all slots
101 */
102
103static int
104BSP_pci_read_config_dword(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned int *val) {
105
106    volatile unsigned int data;
107
108    if (offset & 3) return PCIBIOS_BAD_REGISTER_NUMBER;
109
110    pcic->pciitp = 0xff; /* clear interrupts */
111
112    pcic->pcisa = (  1<<(11+slot) ) | ((function & 7)<<8) |  (offset&0x3f);
113    pcic->pcidma = 0xa01;
114    pcic->pcidmaa = (unsigned int) &data;
115
116    while (pcic->pciitp == 0)
117        ;
118
119    pcic->pciitp = 0xff; /* clear interrupts */
120
121    if (pcic->pcisc & 0x20000000)  { /* Master Abort */
122        pcic->pcisc |= 0x20000000;
123        *val = 0xffffffff;
124    }
125    else
126        *val = data;
127
128    DBG("pci_read - bus: %d, dev: %d, fn: %d, off: %d => addr: %x, val: %x\n", bus, slot, function, offset,  (1<<(11+slot) ) | ((function & 7)<<8) |  (offset&0x3f), *val);
129
130    return PCIBIOS_SUCCESSFUL;
131}
132
133
134static int
135BSP_pci_read_config_word(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned short *val) {
136    unsigned int v;
137
138    if (offset & 1) return PCIBIOS_BAD_REGISTER_NUMBER;
139
140    pci_read_config_dword(bus, slot, function, offset&~3, &v);
141    *val = 0xffff & (v >> (8*(offset & 3)));
142
143    return PCIBIOS_SUCCESSFUL;
144}
145
146
147static int
148BSP_pci_read_config_byte(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned char *val) {
149    unsigned int v;
150
151    pci_read_config_dword(bus, slot, function, offset&~3, &v);
152
153    *val = 0xff & (v >> (8*(offset & 3)));
154
155    return PCIBIOS_SUCCESSFUL;
156}
157
158
159static int
160BSP_pci_write_config_dword(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned int val) {
161
162    if (offset & 3) return PCIBIOS_BAD_REGISTER_NUMBER;
163
164    pcic->pciitp = 0xff; /* clear interrupts */
165
166    pcic->pcisa = (  1<<(11+slot) ) | ((function & 7)<<8) |  (offset&0x3f);
167    pcic->pcidma = 0xb01;
168    pcic->pcidmaa = (unsigned int) &val;
169
170    while (pcic->pciitp == 0)
171        ;
172
173    if (pcic->pcisc & 0x20000000)  { /* Master Abort */
174        pcic->pcisc |= 0x20000000;
175    }
176
177    pcic->pciitp = 0xff; /* clear interrupts */
178
179/*    DBG("pci write - bus: %d, dev: %d, fn: %d, off: %d => addr: %x, val: %x\n", bus, slot, function, offset, (1<<(11+slot) ) | ((function & 7)<<8) |  (offset&0x3f), val); */
180
181    return PCIBIOS_SUCCESSFUL;
182}
183
184
185static int
186BSP_pci_write_config_word(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned short val) {
187    unsigned int v;
188
189    if (offset & 1) return PCIBIOS_BAD_REGISTER_NUMBER;
190
191    pci_read_config_dword(bus, slot, function, offset&~3, &v);
192
193    v = (v & ~(0xffff << (8*(offset&3)))) | ((0xffff&val) << (8*(offset&3)));
194
195    return pci_write_config_dword(bus, slot, function, offset&~3, v);
196}
197
198
199static int
200BSP_pci_write_config_byte(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned char val) {
201    unsigned int v;
202
203    pci_read_config_dword(bus, slot, function, offset&~3, &v);
204
205    v = (v & ~(0xff << (8*(offset&3)))) | ((0xff&val) << (8*(offset&3)));
206
207    return pci_write_config_dword(bus, slot, function, offset&~3, v);
208}
209
210
211
212const pci_config_access_functions pci_access_functions = {
213    BSP_pci_read_config_byte,
214    BSP_pci_read_config_word,
215    BSP_pci_read_config_dword,
216    BSP_pci_write_config_byte,
217    BSP_pci_write_config_word,
218    BSP_pci_write_config_dword
219};
220
221rtems_pci_config_t BSP_pci_configuration = {
222    (volatile unsigned char*)PCI_CONFIG_ADDR,
223    (volatile unsigned char*)PCI_CONFIG_DATA,
224    &pci_access_functions
225};
226
227
228void init_at697_pci(void) {
229
230    /* Reset */
231    pcic->pciic = 0xffffffff;
232
233    /* Map system RAM at pci address 0x40000000 and system SDRAM to pci address 0x60000000  */
234    pcic->mbar1  = 0x40000000;
235    pcic->mbar2  = 0x60000000;
236    pcic->pcitpa = 0x40006000;
237
238    /* Enable PCI master and target memory command response  */
239    pcic->pcisc |= 0x40 | 0x6;
240
241    /* Set latency timer to 64 */
242    pcic->pcibhlc = 0x00004000;
243
244    /* Set Inititator configuration so that AHB slave accesses generate memory read/write commands */
245    pcic->pciic = 0x41;
246
247    pcic->pciite = 0xff;
248
249}
250
251/* May not pass a 1k boundary */
252int dma_from_pci_1k(unsigned int addr, unsigned int paddr, unsigned char len) {
253
254    int retval = 0;
255
256    if (addr & 3) {
257        return -1;
258    }
259
260    pcic->pciitp = 0xff; /* clear interrupts */
261
262    pcic->pcisa = paddr;
263    pcic->pcidma = 0xc00 | len;
264    pcic->pcidmaa = addr;
265
266    while (pcic->pciitp == 0)
267        ;
268
269    if (pcic->pciitp & 0x7F) {
270        retval = -1;
271    }
272
273    pcic->pciitp = 0xff; /* clear interrupts */
274
275    if (pcic->pcisc & 0x20000000)  { /* Master Abort */
276        pcic->pcisc |= 0x20000000;
277        retval = -1;
278    }
279
280    return retval;
281}
282
283/* May not pass a 1k boundary */
284int dma_to_pci_1k(unsigned int addr, unsigned int paddr, unsigned char len) {
285
286    int retval = 0;
287
288    if (addr & 3) return -1;
289
290    pcic->pciitp = 0xff; /* clear interrupts */
291
292    pcic->pcisa = paddr;
293    pcic->pcidma = 0x700 | len;
294    pcic->pcidmaa = addr;
295
296    while (pcic->pciitp == 0)
297        ;
298
299    if (pcic->pciitp & 0x7F) retval = -1;
300
301    pcic->pciitp = 0xff; /* clear interrupts */
302
303    if (pcic->pcisc & 0x20000000)  { /* Master Abort */
304        pcic->pcisc |= 0x20000000;
305        retval =  -1;
306    }
307
308    return retval;
309}
310
311/* Transfer len number of words from addr to paddr */
312int dma_to_pci(unsigned int addr, unsigned int paddr, unsigned int len) {
313
314    int tmp_len;
315
316    /* Align to 1k boundary */
317    tmp_len = ((addr + 1024)  & 0xfffffc00) - addr;
318
319    tmp_len = (tmp_len/4 < len) ? tmp_len : (len*4);
320
321    if (dma_to_pci_1k(addr, paddr, tmp_len/4) < 0)
322        return -1;
323
324    addr += tmp_len;
325    paddr += tmp_len;
326    len -= tmp_len/4;
327
328    /* Transfer all 1k blocks */
329    while (len >= 128) {
330
331        if (dma_to_pci_1k(addr, paddr, 128) < 0)
332            return -1;
333
334        addr += 512;
335        paddr += 512;
336        len -= 128;
337
338    }
339
340    /* Transfer last words */
341    if (len) return dma_to_pci_1k(addr, paddr, len);
342
343    return 0;
344}
345
346/* Transfer len number of words from paddr to addr */
347int dma_from_pci(unsigned int addr, unsigned int paddr, unsigned int len) {
348
349    int tmp_len;
350
351    /* Align to 1k boundary */
352    tmp_len = ((addr + 1024)  & 0xfffffc00) - addr;
353
354    tmp_len = (tmp_len/4 < len) ? tmp_len : (len*4);
355
356    if (dma_from_pci_1k(addr, paddr, tmp_len/4) < 0)
357        return -1;
358
359    addr += tmp_len;
360    paddr += tmp_len;
361    len -= tmp_len/4;
362
363    /* Transfer all 1k blocks */
364    while (len >= 128) {
365
366        if (dma_from_pci_1k(addr, paddr, 128) < 0)
367            return -1;
368        addr += 512;
369        paddr += 512;
370        len -= 128;
371
372    }
373
374    /* Transfer last words */
375    if (len) return dma_from_pci_1k(addr, paddr, len);
376
377    return 0;
378}
379
380void pci_mem_enable(unsigned char bus, unsigned char slot, unsigned char function) {
381    unsigned int data;
382
383    pci_read_config_dword(0, slot, function, PCI_COMMAND, &data);
384    pci_write_config_dword(0, slot, function, PCI_COMMAND, data | PCI_COMMAND_MEMORY);
385
386}
387
388void pci_master_enable(unsigned char bus, unsigned char slot, unsigned char function) {
389    unsigned int data;
390
391    pci_read_config_dword(0, slot, function, PCI_COMMAND, &data);
392    pci_write_config_dword(0, slot, function, PCI_COMMAND, data | PCI_COMMAND_MASTER);
393
394}
395
396static inline void swap_res(struct pci_res **p1, struct pci_res **p2) {
397
398    struct pci_res *tmp = *p1;
399    *p1 = *p2;
400    *p2 = tmp;
401
402}
403
404/* pci_allocate_resources
405 *
406 * This function scans the bus and assigns PCI addresses to all devices. It handles both
407 * single function and multi function devices. All allocated devices are enabled and
408 * latency timers are set to 40.
409 *
410 * NOTE that it only allocates PCI memory space devices. IO spaces are not enabled.
411 * Also, it does not handle pci-pci bridges. They are left disabled.
412 *
413 *
414*/
415void pci_allocate_resources(void) {
416
417    unsigned int slot, numfuncs, func, id, pos, size, tmp, i, swapped, addr, dev, fn;
418    unsigned char header;
419    struct pci_res **res;
420
421    res = (struct pci_res **) malloc(sizeof(struct pci_res *)*32*8*6);
422
423    for (i = 0; i < 32*8*6; i++) {
424        res[i] = (struct pci_res *) malloc(sizeof(struct pci_res));
425        res[i]->size = 0;
426        res[i]->devfn = i;
427    }
428
429    for(slot = 0; slot< PCI_MAX_DEVICES; slot++) {
430
431        pci_read_config_dword(0, slot, 0, PCI_VENDOR_ID, &id);
432
433        if(id == PCI_INVALID_VENDORDEVICEID || id == 0) {
434            /*
435             * This slot is empty
436             */
437            continue;
438        }
439
440        pci_read_config_byte(0, slot, 0, PCI_HEADER_TYPE, &header);
441
442        if(header & PCI_HEADER_TYPE_MULTI_FUNCTION)     {
443            numfuncs = PCI_MAX_FUNCTIONS;
444        }
445        else {
446            numfuncs = 1;
447        }
448
449        for(func = 0; func < numfuncs; func++) {
450
451            pci_read_config_dword(0, slot, func, PCI_VENDOR_ID, &id);
452            if(id == PCI_INVALID_VENDORDEVICEID || id == 0) {
453                continue;
454            }
455
456            pci_read_config_dword(0, slot, func, PCI_CLASS_REVISION, &tmp);
457            tmp >>= 16;
458            if (tmp == PCI_CLASS_BRIDGE_PCI) {
459                continue;
460            }
461
462            for (pos = 0; pos < 6; pos++) {
463                pci_write_config_dword(0, slot, func, PCI_BASE_ADDRESS_0 + (pos<<2), 0xffffffff);
464                pci_read_config_dword(0, slot, func, PCI_BASE_ADDRESS_0 + (pos<<2), &size);
465
466                if (size == 0 || size == 0xffffffff || (size & 0xff) != 0) {
467                    pci_write_config_dword(0, slot, func, PCI_BASE_ADDRESS_0 + (pos<<2), 0);
468                    continue;
469                }
470
471                else {
472                    res[slot*8*6+func*6+pos]->size  = ~size+1;
473                    res[slot*8*6+func*6+pos]->devfn = slot*8 + func;
474                    res[slot*8*6+func*6+pos]->bar   = pos;
475
476                    DBG("Slot: %d, function: %d, bar%d size: %x\n", slot, func, pos, ~size+1);
477                }
478            }
479        }
480    }
481
482
483    /* Sort the resources in descending order */
484
485    swapped = 1;
486    while (swapped == 1) {
487        swapped = 0;
488        for (i = 0; i < 32*8*6-1; i++) {
489            if (res[i]->size < res[i+1]->size) {
490                swap_res(&res[i], &res[i+1]);
491                swapped = 1;
492            }
493        }
494        i++;
495    }
496
497    /* Assign the BARs */
498
499    addr = PCI_MEM_START;
500    for (i = 0; i < 32*8*6; i++) {
501
502        if (res[i]->size == 0) {
503            goto done;
504        }
505        if ( (addr + res[i]->size) > PCI_MEM_END) {
506            printk("Out of PCI memory space, all devices not configured.\n");
507            goto done;
508        }
509
510        dev = res[i]->devfn >> 3;
511        fn  = res[i]->devfn & 7;
512
513        DBG("Assigning PCI addr %x to device %d, function %d, bar %d\n", addr, dev, fn, res[i]->bar);
514        pci_write_config_dword(0, dev, fn, PCI_BASE_ADDRESS_0+res[i]->bar*4, addr);
515        addr += res[i]->size;
516
517        /* Set latency timer to 64 */
518        pci_read_config_dword(0, dev, fn, 0xC, &tmp);
519        pci_write_config_dword(0, dev, fn, 0xC, tmp|0x4000);
520
521        pci_mem_enable(0, dev, fn);
522
523    }
524
525
526
527done:
528
529#ifdef PCI_INFO
530    printk("\nPCI devices found and configured:\n");
531    for (slot = 0; slot < PCI_MAX_DEVICES; slot++) {
532
533        pci_read_config_byte(0, slot, 0, PCI_HEADER_TYPE, &header);
534
535        if(header & PCI_HEADER_TYPE_MULTI_FUNCTION)     {
536            numfuncs = PCI_MAX_FUNCTIONS;
537        }
538        else {
539            numfuncs = 1;
540        }
541
542        for (func = 0; func < numfuncs; func++) {
543
544            pci_read_config_dword(0, slot, func, PCI_COMMAND, &tmp);
545
546            if (tmp & PCI_COMMAND_MEMORY) {
547
548                pci_read_config_dword(0, slot, func, PCI_VENDOR_ID,  &id);
549
550                if (id == PCI_INVALID_VENDORDEVICEID || id == 0) continue;
551
552                printk("\nSlot %d function: %d\nVendor id: 0x%x, device id: 0x%x\n", slot, func, id & 0xffff, id>>16);
553
554                for (pos = 0; pos < 6; pos++) {
555                    pci_read_config_dword(0, slot, func, PCI_BASE_ADDRESS_0 + pos*4, &tmp);
556
557                    if (tmp != 0 && tmp != 0xffffffff && (tmp & 0xff) == 0) {
558
559                        printk("\tBAR %d: %x\n", pos, tmp);
560                    }
561
562                }
563                printk("\n");
564
565            }
566
567        }
568     }
569    printk("\n");
570#endif
571
572    for (i = 0; i < 1536; i++) {
573        free(res[i]);
574    }
575    free(res);
576}
577
578
579
580
581
582
583
584/*
585 * This routine determines the maximum bus number in the system
586 */
587int init_pci(void)
588{
589    unsigned char ucSlotNumber, ucFnNumber, ucNumFuncs;
590    unsigned char ucHeader;
591    unsigned char ucMaxSubordinate;
592    unsigned int  ulClass, ulDeviceID;
593
594    init_at697_pci();
595    pci_allocate_resources();
596
597/*
598 * Scan PCI bus 0 looking for PCI-PCI bridges
599 */
600    for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
601        (void)pci_read_config_dword(0,
602                                    ucSlotNumber,
603                                    0,
604                                    PCI_VENDOR_ID,
605                                    &ulDeviceID);
606        if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
607/*
608 * This slot is empty
609 */
610            continue;
611        }
612        (void)pci_read_config_byte(0,
613                                   ucSlotNumber,
614                                   0,
615                                   PCI_HEADER_TYPE,
616                                   &ucHeader);
617        if(ucHeader&PCI_HEADER_TYPE_MULTI_FUNCTION)     {
618            ucNumFuncs=PCI_MAX_FUNCTIONS;
619        }
620        else {
621            ucNumFuncs=1;
622        }
623        for(ucFnNumber=0;ucFnNumber<ucNumFuncs;ucFnNumber++) {
624            (void)pci_read_config_dword(0,
625                                        ucSlotNumber,
626                                        ucFnNumber,
627                                        PCI_VENDOR_ID,
628                                        &ulDeviceID);
629            if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
630/*
631 * This slot/function is empty
632 */
633                continue;
634            }
635
636/*
637 * This slot/function has a device fitted.
638 */
639            (void)pci_read_config_dword(0,
640                                        ucSlotNumber,
641                                        ucFnNumber,
642                                        PCI_CLASS_REVISION,
643                                        &ulClass);
644            ulClass >>= 16;
645            if (ulClass == PCI_CLASS_BRIDGE_PCI) {
646/*
647 * We have found a PCI-PCI bridge
648 */
649                (void)pci_read_config_byte(0,
650                                           ucSlotNumber,
651                                           ucFnNumber,
652                                           PCI_SUBORDINATE_BUS,
653                                           &ucMaxSubordinate);
654                if(ucMaxSubordinate>ucMaxPCIBus) {
655                    ucMaxPCIBus=ucMaxSubordinate;
656                }
657            }
658        }
659    }
660    return 0;
661}
662
663/*
664 * Return the number of PCI busses in the system
665 */
666unsigned char BusCountPCI(void)
667{
668    return(ucMaxPCIBus+1);
669}
Note: See TracBrowser for help on using the repository browser.