source: rtems/c/src/lib/libbsp/sparc/leon2/pci/pci.c @ 9b4422a2

4.115
Last change on this file since 9b4422a2 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

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