OpenCores
URL https://opencores.org/ocsvn/mips_enhanced/mips_enhanced/trunk

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [software/] [leon3/] [pcitest.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dimamali
static unsigned int PCI_ADDR;
2
static unsigned int PCI_CONF;
3
static unsigned int PCI_MEM_START;
4
//#define PCI_MEM_END   0x00000000
5
//#define PCI_MEM_SIZE  (PCI_MEM_START - PCI_MEM_END)
6
 
7
#include "pcitest.h"
8
 
9
//#define DEBUG 1 
10
 
11
#ifdef DEBUG
12
#define DBG(x...) printf(x)
13
#else
14
#define DBG(x...) 
15
#endif
16
 
17
/* allow for overriding these definitions */
18
#ifndef PCI_CONFIG_ADDR
19
#define PCI_CONFIG_ADDR                 0xcf8
20
#endif
21
#ifndef PCI_CONFIG_DATA
22
#define PCI_CONFIG_DATA                 0xcfc
23
#endif
24
#define PCI_INVALID_VENDORDEVICEID      0xffffffff
25
#define PCI_MULTI_FUNCTION              0x80
26
 
27
typedef struct {
28
        volatile unsigned int cfg_stat;
29
        volatile unsigned int bar0;
30
        volatile unsigned int page0;
31
        volatile unsigned int bar1;
32
        volatile unsigned int page1;
33
        volatile unsigned int iomap;
34
        volatile unsigned int stat_cmd;
35
} LEON3_GRPCI_Regs_Map;
36
 
37
static LEON3_GRPCI_Regs_Map *pcic;
38
 
39
struct pci_res {
40
    unsigned int size;
41
    unsigned char bar;
42
    unsigned char devfn;
43
};
44
 
45
static inline unsigned int flip_dword (unsigned int l)
46
{
47
        return ((l&0xff)<<24) | (((l>>8)&0xff)<<16) | (((l>>16)&0xff)<<8)| ((l>>24)&0xff);
48
}
49
 
50
int
51
pci_read_config_dword(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned int *val) {
52
 
53
    volatile unsigned int *pci_conf;
54
 
55
    if (offset & 3) return PCIBIOS_BAD_REGISTER_NUMBER;
56
 
57
    if (slot >= 21) {
58
        *val = 0xffffffff;
59
        return PCIBIOS_SUCCESSFUL;
60
    }
61
 
62
    pci_conf = (int*)(PCI_CONF + ((slot<<11) | (function<<8) | offset));
63
 
64
    *val =  *pci_conf;
65
 
66
    if (pcic->cfg_stat & 0x100) {
67
        *val = 0xffffffff;
68
    }
69
 
70
/*    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);
71
 */
72
 
73
    return PCIBIOS_SUCCESSFUL;
74
}
75
 
76
 
77
int
78
pci_read_config_word(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned short *val) {
79
    unsigned int v;
80
 
81
    if (offset & 1) return PCIBIOS_BAD_REGISTER_NUMBER;
82
 
83
    pci_read_config_dword(bus, slot, function, offset&~3, &v);
84
    *val = 0xffff & (v >> (8*(offset & 3)));
85
 
86
    return PCIBIOS_SUCCESSFUL;
87
}
88
 
89
 
90
int
91
pci_read_config_byte(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned char *val) {
92
    unsigned int v;
93
 
94
    pci_read_config_dword(bus, slot, function, offset&~3, &v);
95
 
96
    *val = 0xff & (v >> (8*(offset & 3)));
97
 
98
    return PCIBIOS_SUCCESSFUL;
99
}
100
 
101
 
102
int
103
pci_write_config_dword(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned int val) {
104
 
105
    volatile unsigned int *pci_conf;
106
 
107
    if (offset & 3 || bus != 0) return PCIBIOS_BAD_REGISTER_NUMBER;
108
 
109
 
110
    pci_conf = (int*)(PCI_CONF + ((slot<<11) | (function<<8) | (offset & ~3)));
111
 
112
    *pci_conf = val;
113
 
114
/*    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); */
115
 
116
    return PCIBIOS_SUCCESSFUL;
117
}
118
 
119
 
120
int
121
pci_write_config_word(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned short val) {
122
    unsigned int v;
123
 
124
    if (offset & 1) return PCIBIOS_BAD_REGISTER_NUMBER;
125
 
126
    pci_read_config_dword(bus, slot, function, offset&~3, &v);
127
 
128
    v = (v & ~(0xffff << (8*(offset&3)))) | ((0xffff&val) << (8*(offset&3)));
129
 
130
    return pci_write_config_dword(bus, slot, function, offset&~3, v);
131
}
132
 
133
 
134
int
135
pci_write_config_byte(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned char val) {
136
    unsigned int v;
137
 
138
    pci_read_config_dword(bus, slot, function, offset&~3, &v);
139
 
140
    v = (v & ~(0xff << (8*(offset&3)))) | ((0xff&val) << (8*(offset&3)));
141
 
142
    return pci_write_config_dword(bus, slot, function, offset&~3, v);
143
}
144
 
145
 
146
void init_grpci(void) {
147
 
148
    volatile unsigned int *page0 =  (unsigned volatile int *)PCI_MEM_START;
149
    unsigned int data, addr;
150
 
151
    pci_write_config_dword(0,0,0,0x10, 0xffffffff);
152
    pci_read_config_dword(0,0,0,0x10, &addr);
153
    pci_write_config_dword(0,0,0,0x10, flip_dword(0x80000000));    /* Setup bar0 to nonzero value (grpci considers BAR==0 as invalid) */
154
    addr = (~flip_dword(addr)+1)>>1;                               /* page0 is accessed through upper half of bar0 */
155
    pcic->cfg_stat |= 0x80000000;                                  /* Setup mmap reg so we can reach bar0 */
156
    page0[addr/4] = flip_dword(0x80000000);                                             /* Disable bytetwisting ... */
157
 
158
 
159
    /* set 1:1 mapping between AHB -> PCI memory */
160
    pcic->cfg_stat = (pcic->cfg_stat & 0x0fffffff) | PCI_MEM_START;
161
 
162
    /* and map system RAM at pci address 0xc0000000 */
163
    pci_write_config_dword(0, 0, 0, 0x14, 0xc0000000);
164
    pcic->page1 = 0x40000000;
165
 
166
    /* set as bus master and enable pci memory responses */
167
    pci_read_config_dword(0, 0, 0, 0x4, &data);
168
    pci_write_config_dword(0, 0, 0, 0x4, data | 0x6);
169
 
170
 
171
}
172
 
173
void pci_mem_enable(unsigned char bus, unsigned char slot, unsigned char function) {
174
    unsigned int data;
175
 
176
    pci_read_config_dword(0, slot, function, PCI_COMMAND, &data);
177
    pci_write_config_dword(0, slot, function, PCI_COMMAND, data | PCI_COMMAND_MEMORY);
178
 
179
}
180
 
181
void pci_master_enable(unsigned char bus, unsigned char slot, unsigned char function) {
182
    unsigned int data;
183
 
184
    pci_read_config_dword(0, slot, function, PCI_COMMAND, &data);
185
    pci_write_config_dword(0, slot, function, PCI_COMMAND, data | PCI_COMMAND_MASTER);
186
 
187
}
188
 
189
static inline void swap_res(struct pci_res **p1, struct pci_res **p2) {
190
 
191
    struct pci_res *tmp = *p1;
192
    *p1 = *p2;
193
    *p2 = tmp;
194
 
195
}
196
 
197
/* pci_allocate_resources
198
 *
199
 * This function scans the bus and assigns PCI addresses to all devices. It handles both
200
 * single function and multi function devices. All allocated devices are enabled and
201
 * latency timers are set to 40.
202
 *
203
 * NOTE that it only allocates PCI memory space devices. IO spaces are not enabled.
204
 * Also, it does not handle pci-pci bridges. They are left disabled.
205
 *
206
 *
207
*/
208
void pci_allocate_resources(void) {
209
 
210
    unsigned int slot, numfuncs, func, id, pos, size, tmp, i, swapped, addr, dev, fn;
211
    unsigned char header;
212
    struct pci_res **res;
213
    int bar;
214
 
215
 /*    res = (struct pci_res **) malloc(sizeof(struct pci_res *)*32*8*6); */
216
 
217
/*     for (i = 0; i < 32*8*6; i++) { */
218
/*         res[i] = (struct pci_res *) malloc(sizeof(struct pci_res));      */
219
/*         res[i]->size = 0; */
220
/*         res[i]->devfn = i; */
221
/*     } */
222
 
223
    addr = PCI_MEM_START+0x10000000;
224
    for(slot = 1; slot < PCI_MAX_DEVICES; slot++) {
225
 
226
        pci_read_config_dword(0, slot, 0, PCI_VENDOR_ID, &id);
227
 
228
        if(id == PCI_INVALID_VENDORDEVICEID || id == 0) {
229
            /*
230
             * This slot is empty
231
             */
232
            continue;
233
        }
234
 
235
        pci_read_config_byte(0, slot, 0, PCI_HEADER_TYPE, &header);
236
 
237
        if(header & PCI_MULTI_FUNCTION) {
238
            numfuncs = PCI_MAX_FUNCTIONS;
239
        }
240
        else {
241
            numfuncs = 1;
242
        }
243
 
244
        for(func = 0; func < numfuncs; func++) {
245
 
246
            pci_read_config_dword(0, slot, func, PCI_VENDOR_ID, &id);
247
            if(id == PCI_INVALID_VENDORDEVICEID || id == 0) {
248
                continue;
249
            }
250
 
251
            pci_read_config_dword(0, slot, func, PCI_CLASS_REVISION, &tmp);
252
            tmp >>= 16;
253
            if (tmp == PCI_CLASS_BRIDGE_PCI) {
254
                continue;
255
            }
256
 
257
            for (pos = 0; pos < 6; pos++) {
258
                pci_write_config_dword(0, slot, func, PCI_BASE_ADDRESS_0 + (pos<<2), 0xffffffff);
259
                pci_read_config_dword(0, slot, func, PCI_BASE_ADDRESS_0 + (pos<<2), &size);
260
 
261
                if (size == 0 || size == 0xffffffff || (size & 0xff1) != 0)
262
                    continue;
263
 
264
                else {
265
                    size &= 0xfffffff0;
266
           /*          res[slot*8*6+func*6+pos]->size  = ~size+1; */
267
/*                     res[slot*8*6+func*6+pos]->devfn = slot*8 + func; */
268
/*                     res[slot*8*6+func*6+pos]->bar   = pos; */
269
 
270
                    size  = ~size+1;
271
                    bar = pos;
272
                    dev = (slot*8 + func) >> 3;
273
                    fn  = (slot*8 + func) & 7;
274
 
275
                    pci_write_config_dword(0, dev, fn, PCI_BASE_ADDRESS_0+bar*4, addr);
276
                    addr += size;
277
                    pci_read_config_dword(0, dev, fn, 0xC, &tmp);
278
                    pci_write_config_dword(0, dev, fn, 0xC, tmp|0x4000);
279
 
280
                    pci_mem_enable(0, dev, fn);
281
 
282
                    DBG("Slot: %d, function: %d, bar%d size: %x\n", slot, func, pos, ~size+1);
283
                }
284
            }
285
        }
286
    }
287
 
288
 
289
    /* Sort the resources in descending order */
290
 
291
 /*    swapped = 1; */
292
/*     while (swapped == 1) { */
293
/*         swapped = 0; */
294
/*         for (i = 0; i < 32*8*6-1; i++) { */
295
/*             if (res[i]->size < res[i+1]->size) { */
296
/*                 swap_res(&res[i], &res[i+1]); */
297
/*                 swapped = 1; */
298
/*             } */
299
/*         } */
300
/*         i++; */
301
/*     } */
302
 
303
    /* Assign the BARs */
304
 
305
  /*   addr = PCI_MEM_START; */
306
/*     for (i = 0; i < 32*8*6; i++) { */
307
 
308
/*         if (res[i]->size == 0) { */
309
/*             goto done; */
310
/*         } */
311
/*         if ( (addr + res[i]->size) > PCI_MEM_END) { */
312
/*             goto done; */
313
/*         } */
314
 
315
/*         dev = res[i]->devfn >> 3; */
316
/*         fn  = res[i]->devfn & 7; */
317
 
318
/*         DBG("Assigning PCI addr %x to device %d, function %d, bar %d\n", addr, dev, fn, res[i]->bar); */
319
/*         pci_write_config_dword(0, dev, fn, PCI_BASE_ADDRESS_0+res[i]->bar*4, addr); */
320
/*         addr += res[i]->size; */
321
 
322
/*         /\* Set latency timer to 64 *\/ */
323
/*         pci_read_config_dword(0, dev, fn, 0xC, &tmp);     */
324
/*         pci_write_config_dword(0, dev, fn, 0xC, tmp|0x4000); */
325
 
326
/*         pci_mem_enable(0, dev, fn);   */
327
 
328
/*     }  */
329
 
330
 
331
 
332
/* done: */
333
 
334
 
335
    /*   for (i = 0; i < 1536; i++) { */
336
/*         free(res[i]); */
337
/*     } */
338
/*     free(res); */
339
}
340
 
341
 
342
 
343
 
344
 
345
/*
346
 * This routine determines the maximum bus number in the system
347
 */
348
void init_pci()
349
{
350
//    DBG("Initializing PCI\n");
351
    init_grpci();
352
    pci_allocate_resources();
353
//    DBG("PCI resource allocation done\n");
354
 
355
}
356
 
357
static inline int storemem(int addr, int val)
358
{
359
  asm volatile (" sta %0, [%1]1 \n "
360
      : // no outputs
361
      : "r"(val), "r" (addr)
362
    );
363
}
364
 
365
static inline int loadmem(int addr)
366
{
367
  int tmp;
368
  asm volatile (" lda [%1]1, %0 "
369
      : "=r"(tmp)
370
      : "r"(addr)
371
    );
372
  return tmp;
373
}
374
 
375
 
376
int pci_test(int apbaddr, int ioaddr, int ahbaddr) {
377
 
378
int pcidata ;
379
 
380
    PCI_ADDR  = 0x80000400;
381
    PCI_CONF  = 0xfff10000;
382
    PCI_MEM_START  = 0xc0000000;
383
    pcic = (LEON3_GRPCI_Regs_Map *) PCI_ADDR;
384
    report_device(0x01014000);
385
 
386
    init_pci();
387
 
388
    storemem(0xc0080000, 0xdeadbeef);
389
    pcidata = loadmem(0xc0080000);
390
 
391
    return 0;
392
 
393
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.