📄 arch_pci_pb1500.c
字号:
#include <sysdefs.h>
#include <syserror.h>
#include <syscon_api.h>
#include <sys_api.h>
#include <syserror.h>
#include <pb1000.h>
#include <pci_api.h>
#include <arch_pci_pb1500.h>
#include <stdio.h>
void sys_tlb_write();
UINT32 CP0_prid_read();
void CP0_wired_write();
/*
* arch_pci_pb1500.c
*
* pb1500 PCI initialization
*
* Copyright 2001, Alchemy Semiconductor, Inc.
* Matt Brandt
*/
/************************************************************************
*
* pci_init
* Description :
* -------------
*
* PCI module initialization function
*
* Uses the first three entries of the MMU to map the following 32 MB areas:
*
* 0 0x40000000 - 0x41ffffff PCI non-cacheable memory space
* 1 0x50000000 - 0x51ffffff PCI I/O space
* 2 reserved for config access
*
* Return values :
* ---------------
*
* OK if no error, else error code
*
************************************************************************/
UINT32 pci_init(
UINT32 mem_start, // ignores these parameters
UINT32 mem_size,
UINT32 mem_offset,
UINT32 io_start,
UINT32 io_size,
UINT32 io_offset
)
{
UINT32 prid;
int i;
UINT32 pte[5];
prid = CP0_prid_read(); // get processor ID
if( (prid & 0xffff0000) != 0x01030000 && (prid & 0xffff0000) != 0x03030000)
{
printf("-not present-\n");
printf("PRID = %08x\n",prid);
return OK; // exit if not Au1500
}
if ( (prid & 0xffff0000) == 0x01030000)
DISP_STR("(Au1500)");
if ( (prid & 0xffff0000) == 0x03030000)
DISP_STR("(Au1550)");
DISP_STR(" PCI Enabled...");
// NOTE: Au15x0 PCI init code located into reset_pb15x0.S
// map physical address 0x400xxxxx to 0x40xxxxxx for PCI memory
pte[0] = 0; // entry 0
pte[1] = 0x01ffe000; // 16MB pages for memory
pte[2] = 0x40000000; // logical VPN
pte[3] = (0x40000000 >> 2) // 0x4_0000_0000 physical address
| 0x0017; // non-cacheable, d, v, and g bits set
pte[4] = (0x40100000 >> 2) // 0x4_0100_0000 physical address
| 0x0017; // non-cacheable, d, v, and g bits set
// printf("TLB = %d %08x %08x %08x %08x\n",pte[0],pte[1],pte[2],pte[3],pte[4]);
sys_tlb_write(pte);
// map physical address 0x500xxxxx to 0x50xxxxxx for PCI I/O
pte[0] = 1; // entry 1
pte[1] = 0x01ffe000; // 16MB pages for I/O
pte[2] = 0x50000000; // logical VPN
pte[3] = (0x50000000 >> 2) // 0x5_0000_0000 physical address
| 0x0017; // non-cacheable, d, v, and g bits set
pte[4] = (0x50100000 >> 2) // 0x5_0100_0000 physical address
| 0x0017; // non-cacheable, d, v, and g bits set
// printf("TLB = %d %08x %08x %08x %08x\n",pte[0],pte[1],pte[2],pte[3],pte[4]);
sys_tlb_write(pte);
sys_tlb_read(0,pte);
// printf("TLB 0 = %08x %08x %08x %08x\n",pte[0],pte[1],pte[2],pte[3]);
sys_tlb_read(1,pte);
// printf("TLB 1 = %08x %08x %08x %08x\n",pte[0],pte[1],pte[2],pte[3]);
CP0_wired_write(4); // keep 4 entries fixed
return OK;
}
/************************************************************************
*
* pci_iack
* Description :
* -------------
*
* Perform PCI Interrupt Acknowledge Cycle
*
* Return values :
* ---------------
*
* Vector obtained from cycle
*
************************************************************************/
UINT32 pci_iack( void )
{
return au_pci_spec_intack;
}
/*
* map_config_address()
*
* This function maps the address given to PCI configuration space and
* returns a pointer to where the access should occur.
*/
void *map_config_address(UINT32 addr)
{
UINT32 pte[5];
UINT32 pfn;
// grab 32M page of address and fix PFN[35:32] to PCI config space
pfn = ((addr & 0xfe000000) >> 4) | 0x60000000;
pte[0] = 3; // entry 3
pte[1] = 0x01ffe000; // 16MB pages for I/O
pte[2] = 0x60000000; // logical VPN
pte[3] = (pfn >> 2) // even physical address
| 0x0017; // non-cacheable, d, v, and g bits set
pte[4] = ((pfn | 0x00100000) >> 2) // odd physical address
| 0x0017; // non-cacheable, d, v, and g bits set
sys_tlb_write(pte);
return (void *)((addr & 0x01ffffff) | 0x60000000);
}
/************************************************************************
*
* pci_config_read32/16/8
* Description :
* -------------
*
* Low level pci configuration space read routines (32/16/8 bit)
*
* Return values :
* ---------------
*
* 0 (No error) or ERROR_PCI_ABORT
*
************************************************************************/
UINT32 pci_config_read32(
UINT32 busnum, /* IN bus number */
UINT32 devnum, /* IN device number */
UINT32 func, /* IN function number */
UINT32 reg, /* IN address */
UINT32 *data ) /* OUT pointer to data read */
{
UINT32 cfgaddr;
if( busnum == 0 ) // if local bus
{
cfgaddr = (0x00000800 << devnum)
| ((func & 0x07) << 8)
| (reg & 0x000000fc);
}
else // else create type 1 address
{
cfgaddr = ((busnum & 0x00ff) << 16)
| ((devnum & 0x001f) << 11)
| ((func & 0x0007) << 8)
| (reg & 0x00fc)
| 0x80000000; // type 1 flag
}
*data = *((UINT32 *)map_config_address(cfgaddr));
return 0;
}
UINT32 pci_config_read16(
UINT32 busnum, /* IN bus number */
UINT32 devnum, /* IN device number */
UINT32 func, /* IN function number */
UINT32 reg, /* IN address */
UINT16 *data ) /* OUT pointer to data read */
{
UINT32 cfgaddr, rdata;
int offset;
if( busnum == 0 ) // if local bus
{
cfgaddr = (0x00000800 << devnum)
| ((func & 0x07) << 8)
| (reg & 0x000000fe);
}
else // else create type 1 address
{
cfgaddr = ((busnum & 0x00ff) << 16)
| ((devnum & 0x001f) << 11)
| ((func & 0x0007) << 8)
| (reg & 0x00fc)
| 0x80000000; // type 1 flag
}
*data = *((UINT16 *)map_config_address(cfgaddr));
return 0;
}
UINT32 pci_config_read8(
UINT32 busnum, /* IN bus number */
UINT32 devnum, /* IN device number */
UINT32 func, /* IN function number */
UINT32 reg, /* IN address */
UINT8 *data ) /* OUT pointer to data read */
{
UINT32 cfgaddr, rdata;
int offset;
offset = ((int)data & 0x0003);
if( busnum == 0 ) // if local bus
{
cfgaddr = (0x00000800 << devnum)
| ((func & 0x07) << 8)
| (reg & 0x000000ff);
}
else // else create type 1 address
{
cfgaddr = ((busnum & 0x00ff) << 16)
| ((devnum & 0x001f) << 11)
| ((func & 0x0007) << 8)
| (reg & 0x00fc)
| 0x80000000; // type 1 flag
}
*data = *((UINT8 *)map_config_address(cfgaddr));
return 0;
}
/************************************************************************
*
* pci_config_write32/16/8
* Description :
* -------------
*
* Low level pci configuration space write routines (32/16/8 bit)
*
* Return values :
* ---------------
*
* 0 (No error) or ERROR_PCI_ABORT
*
************************************************************************/
UINT32 pci_config_write32(
UINT32 busnum, /* IN bus number */
UINT32 devnum, /* IN device number */
UINT32 func, /* IN function number */
UINT32 reg, /* IN address */
UINT32 data ) /* IN data to write */
{
UINT32 cfgaddr;
if( busnum == 0 ) // if local bus
{
cfgaddr = (0x00000800 << devnum)
| ((func & 0x07) << 8)
| (reg & 0x000000fc);
}
else // else create type 1 address
{
cfgaddr = ((busnum & 0x00ff) << 16)
| ((devnum & 0x001f) << 11)
| ((func & 0x0007) << 8)
| (reg & 0x00fc)
| 0x80000000; // type 1 flag
}
*((UINT32 *)map_config_address(cfgaddr)) = data;
return 0;
}
UINT32 pci_config_write16(
UINT32 busnum, /* IN bus number */
UINT32 devnum, /* IN device number */
UINT32 func, /* IN function number */
UINT32 reg, /* IN address */
UINT16 data ) /* IN data to write */
{
UINT32 cfgaddr, rdata;
int offset;
offset = ((int)data & 0x0003);
if( busnum == 0 ) // if local bus
{
cfgaddr = (0x00000800 << devnum)
| ((func & 0x07) << 8)
| (reg & 0x000000fe);
}
else // else create type 1 address
{
cfgaddr = ((busnum & 0x00ff) << 16)
| ((devnum & 0x001f) << 11)
| ((func & 0x0007) << 8)
| (reg & 0x00fc)
| 0x80000000; // type 1 flag
}
*((UINT16 *)map_config_address(cfgaddr)) = data;
return 0;
}
UINT32 pci_config_write8(
UINT32 busnum, /* IN bus number */
UINT32 devnum, /* IN device number */
UINT32 func, /* IN function number */
UINT32 reg, /* IN address */
UINT8 data ) /* IN data to write */
{
UINT32 cfgaddr, rdata;
int offset;
offset = ((int)data & 0x0003);
if( busnum == 0 ) // if local bus
{
cfgaddr = (0x00000800 << devnum)
| ((func & 0x07) << 8)
| (reg & 0x000000fc);
}
else // else create type 1 address
{
cfgaddr = ((busnum & 0x00ff) << 16)
| ((devnum & 0x001f) << 11)
| ((func & 0x0007) << 8)
| (reg & 0x00fc)
| 0x80000000; // type 1 flag
}
*((UINT8 *)map_config_address(cfgaddr)) = data;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -