source: rtems/c/src/lib/libbsp/sparc/leon2/pci/pci.c @ 363b1f7

4.115
Last change on this file since 363b1f7 was 363b1f7, checked in by Daniel Cederman <cederman@…>, on 05/08/14 at 13:42:12

bsps/sparc: Make lines in SPARC BSPs adhere to 80 character limit.

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