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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [hal/] [arm/] [xscale/] [iop310/] [v2_0/] [src/] [iop310_pci.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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