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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [arm/] [xscale/] [iop310/] [current/] [src/] [iop310_pci.c] - Blame information for rev 856

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      iop310_pci.c
4
//
5
//      HAL board support code for XScale IOP310 PCI
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    msalter
43
// Contributors: msalter
44
// Date:         2000-10-10
45
// Purpose:      PCI support
46
// Description:  Implementations of HAL PCI interfaces
47
//
48
//####DESCRIPTIONEND####
49
//
50
//========================================================================*/
51
 
52
#include <pkgconf/hal.h>
53
#include <pkgconf/system.h>
54
#include CYGBLD_HAL_PLATFORM_H
55
#include CYGHWR_MEMORY_LAYOUT_H
56
 
57
#include <cyg/infra/cyg_type.h>         // base types
58
#include <cyg/infra/cyg_trac.h>         // tracing macros
59
#include <cyg/infra/cyg_ass.h>          // assertion macros
60
 
61
#include <cyg/hal/hal_io.h>             // IO macros
62
#include <cyg/hal/hal_if.h>             // calling interface API
63
#include <cyg/hal/hal_arch.h>           // Register state info
64
#include <cyg/hal/hal_diag.h>
65
#include <cyg/hal/hal_intr.h>           // Interrupt names
66
#include <cyg/hal/hal_cache.h>
67
#include <cyg/hal/hal_iop310.h>         // Hardware definitions
68
#include <cyg/io/pci_hw.h>
69
#include <cyg/io/pci.h>
70
 
71
static cyg_uint8 pbus_nr;
72
static cyg_uint8 sbus_nr;
73
static cyg_uint8 subbus_nr;
74
 
75
void cyg_hal_plf_pci_init(void)
76
{
77
    cyg_uint32 limit_reg;
78
    cyg_uint8  next_bus;
79
 
80
    // ************ bridge registers *******************
81
    if (iop310_is_host()) {
82
 
83
        // set the primary inbound ATU base address to the start of DRAM
84
        *PIABAR_REG = MEMBASE_DRAM & 0xFFFFF000;
85
 
86
        // ********* Set Primary Outbound Windows *********
87
 
88
        // Note: The primary outbound ATU memory window value register
89
        //       and i/o window value registers are defaulted to 0
90
 
91
        // set the primary outbound windows to directly map Local - PCI
92
        // requests
93
        // outbound memory window
94
        *POMWVR_REG = PRIMARY_MEM_BASE;
95
 
96
        // outbound DAC Window
97
        *PODWVR_REG = PRIMARY_DAC_BASE;
98
 
99
        // outbound I/O window
100
        *POIOWVR_REG = PRIMARY_IO_BASE;
101
 
102
        // set the bridge command register
103
        *PCR_REG = (CYG_PCI_CFG_COMMAND_SERR   | \
104
                    CYG_PCI_CFG_COMMAND_PARITY | \
105
                    CYG_PCI_CFG_COMMAND_MASTER | \
106
                    CYG_PCI_CFG_COMMAND_MEMORY);
107
 
108
        // set the subordinate bus number to 0xFF
109
        *SUBBNR_REG = 0xFF;
110
        // set the secondary bus number to 1
111
        *SBNR_REG = SECONDARY_BUS_NUM;
112
        *BCR_REG = 0x0823;
113
        // set the primary bus number to 0
114
        *PBNR_REG = PRIMARY_BUS_NUM;
115
 
116
        // allow primary ATU to act as a bus master, respond to PCI 
117
        // memory accesses, assert P_SERR#, and enable parity checking
118
        *PATUCMD_REG = (CYG_PCI_CFG_COMMAND_SERR   | \
119
                        CYG_PCI_CFG_COMMAND_PARITY | \
120
                        CYG_PCI_CFG_COMMAND_MASTER | \
121
                        CYG_PCI_CFG_COMMAND_MEMORY);
122
    } else {
123
#ifdef CYGSEM_HAL_ARM_IOP310_CLEAR_PCI_RETRY
124
        // Wait for PC BIOS to initialize bus number
125
        int i;
126
 
127
        for (i = 0; i < 15000; i++) {
128
            if (*PCR_REG & CYG_PCI_CFG_COMMAND_MEMORY)
129
                break;
130
            hal_delay_us(1000);  // 1msec
131
        }
132
        for (i = 0; i < 15000; i++) {
133
            if (*SBNR_REG != 0)
134
                break;
135
            hal_delay_us(1000);  // 1msec
136
        }
137
#endif
138
        if (*SBNR_REG == 0)
139
            *SBNR_REG = SECONDARY_BUS_NUM;
140
        if (*SUBBNR_REG == 0)
141
            *SUBBNR_REG = 0xFF;
142
        if (*BCR_REG == 0)
143
            *BCR_REG = 0x0823;
144
        if (*PCR_REG == 0)
145
            *PCR_REG = (CYG_PCI_CFG_COMMAND_SERR   | \
146
                        CYG_PCI_CFG_COMMAND_PARITY | \
147
                        CYG_PCI_CFG_COMMAND_MASTER | \
148
                        CYG_PCI_CFG_COMMAND_MEMORY);
149
        if (*PATUCMD_REG == 0)
150
            *PATUCMD_REG = (CYG_PCI_CFG_COMMAND_SERR   | \
151
                            CYG_PCI_CFG_COMMAND_PARITY | \
152
                            CYG_PCI_CFG_COMMAND_MASTER | \
153
                            CYG_PCI_CFG_COMMAND_MEMORY);
154
    }
155
 
156
    // Initialize Secondary PCI bus (bus 1)
157
    *BCR_REG |= 0x40;           // reset secondary bus
158
    hal_delay_us(10 * 1000);    // 10ms enough??
159
    *BCR_REG &= ~0x40;          // release reset
160
 
161
    // ******** Secondary Inbound ATU ***********
162
 
163
    // set secondary inbound ATU translate value register to point to base
164
    // of local DRAM
165
    *SIATVR_REG = MEMBASE_DRAM & 0xFFFFFFFC;
166
 
167
    // set secondary inbound ATU base address to start of DRAM
168
    *SIABAR_REG = MEMBASE_DRAM & 0xFFFFF000;
169
 
170
    //  always allow secondary pci access to all memory (even with A0 step)
171
    limit_reg = (0xFFFFFFFF - (hal_dram_size - 1)) & 0xFFFFFFF0;
172
    *SIALR_REG = limit_reg;
173
 
174
    // ********** Set Secondary Outbound Windows ***********
175
 
176
    // Note: The secondary outbound ATU memory window value register
177
    // and i/o window value registers are defaulted to 0
178
 
179
    // set the secondary outbound window to directly map Local - PCI requests
180
    // outbound memory window
181
    *SOMWVR_REG = SECONDARY_MEM_BASE;
182
 
183
    // outbound DAC Window
184
    *SODWVR_REG = SECONDARY_DAC_BASE;
185
 
186
    // outbound I/O window
187
    *SOIOWVR_REG = SECONDARY_IO_BASE;
188
 
189
    // allow secondary ATU to act as a bus master, respond to PCI memory
190
    // accesses, and assert S_SERR#
191
    *SATUCMD_REG = (CYG_PCI_CFG_COMMAND_SERR   | \
192
                    CYG_PCI_CFG_COMMAND_PARITY | \
193
                    CYG_PCI_CFG_COMMAND_MASTER | \
194
                    CYG_PCI_CFG_COMMAND_MEMORY);
195
 
196
    // enable primary and secondary outbound ATUs, BIST, and primary bus
197
    // direct addressing
198
    *ATUCR_REG = 0x00000006;
199
 
200
    pbus_nr = *PBNR_REG;
201
    sbus_nr = *SBNR_REG;
202
 
203
    // Now initialize the PCI busses.
204
 
205
    // Next assignable bus number. Yavapai primary bus is fixed as
206
    // bus zero and yavapai secondary is fixed as bus 1.
207
    next_bus = sbus_nr + 1;
208
 
209
    // If we are the host on the Primary bus, then configure it.
210
    if (iop310_is_host()) {
211
 
212
        // Initialize these so all config cycles first go out over
213
        // the Primary side
214
        pbus_nr = 0;
215
        sbus_nr = 0xff;
216
 
217
        // set the primary bus number to 0
218
        *PBNR_REG = 0;
219
        next_bus = 1;
220
 
221
        // Initialize Primary PCI bus (bus 0)
222
        cyg_pci_set_memory_base(PRIMARY_MEM_BASE);
223
        cyg_pci_set_io_base(PRIMARY_IO_BASE);
224
        cyg_pci_configure_bus(0, &next_bus);
225
 
226
        // set the secondary bus number to next available number
227
        *SBNR_REG = sbus_nr = next_bus;
228
 
229
        pbus_nr = *PBNR_REG;
230
        next_bus = sbus_nr + 1;
231
    }
232
 
233
    // Initialize Secondary PCI bus (bus 1)
234
    cyg_pci_set_memory_base(SECONDARY_MEM_BASE);
235
    cyg_pci_set_io_base(SECONDARY_IO_BASE);
236
    subbus_nr = 0xFF;
237
    cyg_pci_configure_bus(sbus_nr, &next_bus);
238
    *SUBBNR_REG = subbus_nr = next_bus - 1;
239
 
240
 
241
    if (0){
242
        cyg_uint8 devfn;
243
        cyg_pci_device_id devid;
244
        cyg_pci_device dev_info;
245
 
246
        diag_printf("pbus[%d] sbus[%d] subbus[%d]\n", pbus_nr, sbus_nr, subbus_nr);
247
 
248
        devid = CYG_PCI_DEV_MAKE_ID(sbus_nr, 0) | CYG_PCI_NULL_DEVFN;
249
        while (cyg_pci_find_next(devid, &devid)) {
250
            devfn = CYG_PCI_DEV_GET_DEVFN(devid);
251
            cyg_pci_get_device_info(devid, &dev_info);
252
 
253
            diag_printf("\n");
254
            diag_printf("            Bus:        %d\n", CYG_PCI_DEV_GET_BUS(devid));
255
            diag_printf("            PCI Device: %d\n", CYG_PCI_DEV_GET_DEV(devfn));
256
            diag_printf("            PCI Func  : %d\n", CYG_PCI_DEV_GET_FN(devfn));
257
            diag_printf("            Vendor Id : 0x%08X\n", dev_info.vendor);
258
            diag_printf("            Device Id : 0x%08X\n", dev_info.device);
259
        }
260
    }
261
}
262
 
263
// Use "naked" attribute to suppress C prologue/epilogue
264
static void __attribute__ ((naked)) __pci_abort_handler(void)
265
{
266
    asm ( "subs pc, lr, #4\n" );
267
}
268
 
269
static cyg_uint32 orig_abort_vec;
270
 
271
static inline cyg_uint32 *pci_config_setup(cyg_uint32 bus,
272
                                           cyg_uint32 devfn,
273
                                           cyg_uint32 offset)
274
{
275
    volatile cyg_uint32 *pdata, *paddr;
276
    cyg_uint32 dev = CYG_PCI_DEV_GET_DEV(devfn);
277
    cyg_uint32 fn  = CYG_PCI_DEV_GET_FN(devfn);
278
 
279
    if (bus < sbus_nr || bus > subbus_nr)  {
280
        paddr = (volatile cyg_uint32 *)POCCAR_ADDR;
281
        pdata = (volatile cyg_uint32 *)POCCDR_ADDR;
282
    } else {
283
        paddr = (volatile cyg_uint32 *)SOCCAR_ADDR;
284
        pdata = (volatile cyg_uint32 *)SOCCDR_ADDR;
285
    }
286
 
287
    /* Offsets must be dword-aligned */
288
    offset &= ~3;
289
 
290
    /* Primary or secondary bus use type 0 config */
291
    /* all others use type 1 config */
292
    if (bus == pbus_nr || bus == sbus_nr)
293
        *paddr = ( (1 << (dev + 16)) | (fn << 8) | offset | 0 );
294
    else
295
        *paddr = ( (bus << 16) | (dev << 11) | (fn << 8) | offset | 1 );
296
 
297
    orig_abort_vec = ((volatile cyg_uint32 *)0x20)[4];
298
    ((volatile unsigned *)0x20)[4] = (unsigned)__pci_abort_handler;
299
    HAL_ICACHE_SYNC();
300
 
301
    return pdata;
302
}
303
 
304
static inline int pci_config_cleanup(cyg_uint32 bus)
305
{
306
    cyg_uint32 status = 0, err = 0;
307
 
308
    if (bus < sbus_nr || bus > subbus_nr)  {
309
        status = *PATUSR_REG;
310
        if ((status & 0xF900) != 0) {
311
            err = 1;
312
            *PATUSR_REG = status & 0xF980;
313
        }
314
        status = *PSR_REG;
315
        if ((status & 0xF900) != 0) {
316
            err = 1;
317
            *PSR_REG = status & 0xF980;
318
        }
319
        status = *PATUISR_REG;
320
        if ((status & 0x79F) != 0) {
321
            err = 1;
322
            *PATUISR_REG = status & 0x79f;
323
        }
324
        status = *PBISR_REG;
325
        if ((status & 0x3F) != 0) {
326
            err = 1;
327
            *PBISR_REG = status & 0x3F;
328
        }
329
    } else {
330
        status = *SATUSR_REG;
331
        if ((status & 0xF900) != 0) {
332
            err = 1;
333
            *SATUSR_REG = status & 0xF900;
334
        }
335
        status = *SSR_REG;
336
        if ((status & 0xF900) != 0) {
337
            err = 1;
338
            *SSR_REG = status & 0xF980;
339
        }
340
        status = *SATUISR_REG;
341
        if ((status & 0x69F) != 0) {
342
            err = 1;
343
            *SATUISR_REG = status & 0x69F;
344
        }
345
    }
346
 
347
    ((volatile unsigned *)0x20)[4] = orig_abort_vec;
348
    HAL_ICACHE_SYNC();
349
 
350
    return err;
351
}
352
 
353
 
354
 
355
cyg_uint32 cyg_hal_plf_pci_cfg_read_dword (cyg_uint32 bus,
356
                                           cyg_uint32 devfn,
357
                                           cyg_uint32 offset)
358
{
359
    cyg_uint32 *pdata, config_data;
360
 
361
    pdata = pci_config_setup(bus, devfn, offset);
362
 
363
    config_data = *pdata;
364
 
365
    if (pci_config_cleanup(bus))
366
      return 0xffffffff;
367
    else
368
      return config_data;
369
}
370
 
371
 
372
void cyg_hal_plf_pci_cfg_write_dword (cyg_uint32 bus,
373
                                      cyg_uint32 devfn,
374
                                      cyg_uint32 offset,
375
                                      cyg_uint32 data)
376
{
377
    cyg_uint32 *pdata;
378
 
379
    pdata = pci_config_setup(bus, devfn, offset);
380
 
381
    *pdata = data;
382
 
383
    pci_config_cleanup(bus);
384
}
385
 
386
 
387
cyg_uint16 cyg_hal_plf_pci_cfg_read_word (cyg_uint32 bus,
388
                                          cyg_uint32 devfn,
389
                                          cyg_uint32 offset)
390
{
391
    cyg_uint32 *pdata;
392
    cyg_uint16 config_data;
393
 
394
    pdata = pci_config_setup(bus, devfn, offset);
395
 
396
    config_data = (cyg_uint16)(((*pdata) >> ((offset % 0x4) * 8)) & 0xffff);
397
 
398
    if (pci_config_cleanup(bus))
399
      return 0xffff;
400
    else
401
      return config_data;
402
}
403
 
404
void cyg_hal_plf_pci_cfg_write_word (cyg_uint32 bus,
405
                                     cyg_uint32 devfn,
406
                                     cyg_uint32 offset,
407
                                     cyg_uint16 data)
408
{
409
    cyg_uint32 *pdata, mask, temp;
410
 
411
    pdata = pci_config_setup(bus, devfn, offset);
412
 
413
    mask = ~(0x0000ffff << ((offset % 0x4) * 8));
414
 
415
    temp = (cyg_uint32)(((cyg_uint32)data) << ((offset % 0x4) * 8));
416
    *pdata = (*pdata & mask) | temp;
417
 
418
    pci_config_cleanup(bus);
419
}
420
 
421
cyg_uint8 cyg_hal_plf_pci_cfg_read_byte (cyg_uint32 bus,
422
                                         cyg_uint32 devfn,
423
                                         cyg_uint32 offset)
424
{
425
    cyg_uint32 *pdata;
426
    cyg_uint8 config_data;
427
 
428
    pdata = pci_config_setup(bus, devfn, offset);
429
 
430
    config_data = (cyg_uint8)(((*pdata) >> ((offset % 0x4) * 8)) & 0xff);
431
 
432
    if (pci_config_cleanup(bus))
433
        return 0xff;
434
    else
435
        return config_data;
436
}
437
 
438
 
439
void cyg_hal_plf_pci_cfg_write_byte (cyg_uint32 bus,
440
                                     cyg_uint32 devfn,
441
                                     cyg_uint32 offset,
442
                                     cyg_uint8 data)
443
{
444
    cyg_uint32 *pdata, mask, temp;
445
 
446
    pdata = pci_config_setup(bus, devfn, offset);
447
 
448
    mask = ~(0x000000ff << ((offset % 0x4) * 8));
449
    temp = (cyg_uint32)(((cyg_uint32)data) << ((offset % 0x4) * 8));
450
    *pdata = (*pdata & mask) | temp;
451
 
452
    pci_config_cleanup(bus);
453
}
454
 
455
 
456
 

powered by: WebSVN 2.1.0

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