@ -1,5 +1,8 @@
/*
* IXP PCI Init
*
* ( C ) Copyright 2011
* Michael Schwingen , michael @ schwingen . org
* ( C ) Copyright 2004 eslab . whut . edu . cn
* Yue Hu ( huyue_whut @ yahoo . com . cn ) , Ligong Xue ( lgxue @ hotmail . com )
*
@ -22,7 +25,6 @@
* MA 02111 - 1307 USA
*/
# include <common.h>
# include <asm/processor.h>
# include <asm/io.h>
@ -30,542 +32,336 @@
# include <asm/arch/ixp425.h>
# include <asm/arch/ixp425pci.h>
static void non_prefetch_read ( unsigned int addr , unsigned int cmd ,
unsigned int * data ) ;
static void non_prefetch_write ( unsigned int addr , unsigned int cmd ,
unsigned int data ) ;
static void configure_pins ( void ) ;
static void sys_pci_gpio_clock_config ( void ) ;
static void pci_bus_scan ( void ) ;
static int pci_device_exists ( unsigned int deviceNo ) ;
static void sys_pci_bar_info_get ( unsigned int devnum , unsigned int bus ,
unsigned int dev , unsigned int func ) ;
static void sys_pci_device_bars_write ( void ) ;
static void calc_bars ( PciBar * Bars [ ] , unsigned int nBars ,
unsigned int startAddr ) ;
DECLARE_GLOBAL_DATA_PTR ;
static void non_prefetch_read ( unsigned int addr , unsigned int cmd ,
unsigned int * data ) ;
static void non_prefetch_write ( unsigned int addr , unsigned int cmd ,
unsigned int data ) ;
/*define the sub vendor and subsystem to be used */
# define IXP425_PCI_SUB_VENDOR_SYSTEM 0x00000000
# define PCI_MEMORY_BUS 0x00000000
# define PCI_MEMORY_PHY 0x48 000000
# define PCI_MEMORY_PHY 0x00000000
# define PCI_MEMORY_SIZE 0x04000000
# define PCI_MEM_BUS 0x40 000000
# define PCI_MEM_BUS 0x48 000000
# define PCI_MEM_PHY 0x00000000
# define PCI_MEM_SIZE 0x04000000
# define PCI_IO_BUS 0x40000000
# define PCI_IO_PHY 0x50000000
# define PCI_IO_SIZE 0x10000000
# define PCI_IO_BUS 0x00000000
# define PCI_IO_PHY 0x00000000
# define PCI_IO_SIZE 0x00010000
/* build address value for config sycle */
static unsigned int pci_config_addr ( pci_dev_t bdf , unsigned int reg )
{
unsigned int bus = PCI_BUS ( bdf ) ;
unsigned int dev = PCI_DEV ( bdf ) ;
unsigned int func = PCI_FUNC ( bdf ) ;
unsigned int addr ;
if ( bus ) { /* secondary bus, use type 1 config cycle */
addr = bdf | ( reg & ~ 3 ) | 1 ;
} else {
/*
primary bus , type 0 config cycle . address bits 31 : 28
specify the device 10 : 8 specify the function
*/
addr = BIT ( ( 31 - dev ) ) | ( func < < 8 ) | ( reg & ~ 3 ) ;
}
return addr ;
}
static int pci_config_status ( void )
{
unsigned int regval ;
struct pci_controller hose ;
regval = readl ( PCI_CSR_BASE + PCI_ISR_OFFSET ) ;
if ( ( regval & PCI_ISR_PFE ) = = 0 )
return OK ;
unsigned int nDevices ;
unsigned int nMBars ;
unsigned int nIOBars ;
PciBar * memBars [ IXP425_PCI_MAX_BAR ] ;
PciBar * ioBars [ IXP425_PCI_MAX_BAR ] ;
PciDevice devices [ IXP425_PCI_MAX_FUNC_ON_BUS ] ;
/* no device present, make sure that the master abort bit is reset */
writel ( PCI_ISR_PFE , PCI_CSR_BASE + PCI_ISR_OFFSET ) ;
return ERROR ;
}
int pci_read_config_dword ( pci_dev_t dev , int where , unsigned int * val )
static int pci_ixp_hose_read_config_dword ( struct pci_controller * hose ,
pci_dev_t bdf , int where , unsigned int * val )
{
unsigned int retval ;
unsigned int addr ;
int stat ;
/*address bits 31:28 specify the device 10:8 specify the function */
debug ( " pci_ixp_hose_read_config_dword: bdf %x, reg %x " , bdf , where ) ;
/*Set the address to be read */
addr = BIT ( ( 31 - dev ) ) | ( where & ~ 3 ) ;
non_prefetch_read ( addr , NP_CMD_CONFIGREAD , & retval ) ;
addr = pci_config_addr ( bdf , where ) ;
non_prefetch_read ( addr , NP_CMD_CONFIGREAD , & retval ) ;
* val = retval ;
return ( OK ) ;
stat = pci_config_status ( ) ;
if ( stat < 0 )
* val = - 1 ;
debug ( " -> val %x, status %x \n " , * val , stat ) ;
return stat ;
}
int pci_read_config_word ( pci_dev_t dev , int where , unsigned short * val )
static int pci_ixp_hose_read_config_word ( struct pci_controller * hose ,
pci_dev_t bdf , int where , unsigned short * val )
{
unsigned int n ;
unsigned int retval ;
unsigned int addr ;
unsigned int byteEnables ;
int stat ;
debug ( " pci_ixp_hose_read_config_word: bdf %x, reg %x " , bdf , where ) ;
n = where % 4 ;
/*byte enables are 4 bits active low, the position of each
bit maps to the byte that it enables */
byteEnables =
( ~ ( BIT ( n ) | BIT ( ( n + 1 ) ) ) ) &
( ~ ( BIT ( n ) | BIT ( ( n + 1 ) ) ) ) &
IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK ;
byteEnables = byteEnables < < PCI_NP_CBE_BESL ;
/*address bits 31:28 specify the device 10:8 specify the function */
/*Set the address to be read */
addr = BIT ( ( 31 - dev ) ) | ( where & ~ 3 ) ;
non_prefetch_read ( addr , byteEnables | NP_CMD_CONFIGREAD , & retval ) ;
addr = pci_config_addr ( bdf , where ) ;
non_prefetch_read ( addr , byteEnables | NP_CMD_CONFIGREAD , & retval ) ;
/*Pick out the word we are interested in */
* val = ( retval > > ( 8 * n ) ) ;
* val = retval > > ( 8 * n ) ;
return ( OK ) ;
stat = pci_config_status ( ) ;
if ( stat < 0 )
* val = - 1 ;
debug ( " -> val %x, status %x \n " , * val , stat ) ;
return stat ;
}
int pci_read_config_byte ( pci_dev_t dev , int where , unsigned char * val )
static int pci_ixp_hose_read_config_byte ( struct pci_controller * hose ,
pci_dev_t bdf , int where , unsigned char * val )
{
unsigned int retval ;
unsigned int n ;
unsigned int byteEnables ;
unsigned int addr ;
int stat ;
debug ( " pci_ixp_hose_read_config_byte: bdf %x, reg %x " , bdf , where ) ;
n = where % 4 ;
/*byte enables are 4 bits, active low, the position of each
bit maps to the byte that it enables */
byteEnables = ( ~ BIT ( n ) ) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK ;
byteEnables = ( ~ BIT ( n ) ) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK ;
byteEnables = byteEnables < < PCI_NP_CBE_BESL ;
/*address bits 31:28 specify the device, 10:8 specify the function */
/*Set the address to be read */
addr = BIT ( ( 31 - dev ) ) | ( where & ~ 3 ) ;
non_prefetch_read ( addr , byteEnables | NP_CMD_CONFIGREAD , & retval ) ;
addr = pci_config_addr ( bdf , where ) ;
non_prefetch_read ( addr , byteEnables | NP_CMD_CONFIGREAD , & retval ) ;
/*Pick out the byte we are interested in */
* val = ( retval > > ( 8 * n ) ) ;
* val = retval > > ( 8 * n ) ;
return ( OK ) ;
stat = pci_config_status ( ) ;
if ( stat < 0 )
* val = - 1 ;
debug ( " -> val %x, status %x \n " , * val , stat ) ;
return stat ;
}
int pci_write_config_byte ( pci_dev_t dev , int where , unsigned char val )
static int pci_ixp_hose_write_config_byte ( struct pci_controller * hose ,
pci_dev_t bdf , int where , unsigned char val )
{
unsigned int addr ;
unsigned int byteEnables ;
unsigned int n ;
unsigned int ldata ;
int stat ;
debug ( " pci_ixp_hose_write_config_byte: bdf %x, reg %x, val %x " ,
bdf , where , val ) ;
n = where % 4 ;
/*byte enables are 4 bits active low, the position of each
bit maps to the byte that it enables */
byteEnables = ( ~ BIT ( n ) ) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK ;
byteEnables = ( ~ BIT ( n ) ) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK ;
byteEnables = byteEnables < < PCI_NP_CBE_BESL ;
ldata = val < < ( 8 * n ) ;
/*address bits 31:28 specify the device 10:8 specify the function */
/*Set the address to be written */
addr = BIT ( ( 31 - dev ) ) | ( where & ~ 3 ) ;
non_prefetch_write ( addr , byteEnables | NP_CMD_CONFIGWRITE , ldata ) ;
addr = pci_config_addr ( bdf , where ) ;
non_prefetch_write ( addr , byteEnables | NP_CMD_CONFIGWRITE , ldata ) ;
return ( OK ) ;
stat = pci_config_status ( ) ;
debug ( " -> status %x \n " , stat ) ;
return stat ;
}
int pci_write_config_word ( pci_dev_t dev , int where , unsigned short val )
static int pci_ixp_hose_write_config_word ( struct pci_controller * hose ,
pci_dev_t bdf , int where , unsigned short val )
{
unsigned int addr ;
unsigned int byteEnables ;
unsigned int n ;
unsigned int ldata ;
int stat ;
debug ( " pci_ixp_hose_write_config_word: bdf %x, reg %x, val %x " ,
bdf , where , val ) ;
n = where % 4 ;
/*byte enables are 4 bits active low, the position of each
bit maps to the byte that it enables */
byteEnables =
( ~ ( BIT ( n ) | BIT ( ( n + 1 ) ) ) ) &
( ~ ( BIT ( n ) | BIT ( ( n + 1 ) ) ) ) &
IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK ;
byteEnables = byteEnables < < PCI_NP_CBE_BESL ;
ldata = val < < ( 8 * n ) ;
/*address bits 31:28 specify the device 10:8 specify the function */
/*Set the address to be written */
addr = BIT ( 31 - dev ) | ( where & ~ 3 ) ;
non_prefetch_write ( addr , byteEnables | NP_CMD_CONFIGWRITE , ldata ) ;
addr = pci_config_addr ( bdf , where ) ;
non_prefetch_write ( addr , byteEnables | NP_CMD_CONFIGWRITE , ldata ) ;
return ( OK ) ;
stat = pci_config_status ( ) ;
debug ( " -> status %x \n " , stat ) ;
return stat ;
}
int pci_write_config_dword ( pci_dev_t dev , int where , unsigned int val )
static int pci_ixp_hose_write_config_dword ( struct pci_controller * hose ,
pci_dev_t bdf , int where , unsigned int val )
{
unsigned int addr ;
int stat ;
/*address bits 31:28 specify the device 10:8 specify the function */
debug ( " pci_ixp_hose_write_config_dword: bdf %x, reg %x, val %x " ,
bdf , where , val ) ;
/*Set the address to be written */
addr = BIT ( 31 - dev ) | ( where & ~ 3 ) ;
non_prefetch_write ( addr , NP_CMD_CONFIGWRITE , val ) ;
addr = pci_config_addr ( bdf , where ) ;
non_prefetch_write ( addr , NP_CMD_CONFIGWRITE , val ) ;
return ( OK ) ;
stat = pci_config_status ( ) ;
debug ( " -> status %x \n " , stat ) ;
return stat ;
}
void non_prefetch_read ( unsigned int addr ,
unsigned int cmd , unsigned int * data )
static void non_prefetch_read ( unsigned int addr ,
unsigned int cmd , unsigned int * data )
{
REG_WRITE ( PCI_CSR_BASE , PCI_NP_AD_OFFSET , addr ) ;
writel ( addr , PCI_CSR_BASE + PCI_NP_AD_OFFSET ) ;
/*set up and execute the read */
REG_WRITE ( PCI_CSR_BASE , PCI_NP_CBE_OFFSET , cmd ) ;
writel ( cmd , PCI_CSR_BASE + PCI_NP_CBE_OFFSET ) ;
/*The result of the read is now in np_rdata */
REG_READ ( PCI_CSR_BASE , PCI_NP_RDATA_OFFSET , * data ) ;
* data = readl ( PCI_CSR_BASE + PCI_NP_RDATA_OFFSET ) ;
return ;
}
void non_prefetch_write ( unsigned int addr ,
unsigned int cmd , unsigned int data )
static void non_prefetch_write ( unsigned int addr ,
unsigned int cmd , unsigned int data )
{
REG_WRITE ( PCI_CSR_BASE , PCI_NP_AD_OFFSET , addr ) ;
writel ( addr , PCI_CSR_BASE + PCI_NP_AD_OFFSET ) ;
/*set up the write */
REG_WRITE ( PCI_CSR_BASE , PCI_NP_CBE_OFFSET , cmd ) ;
writel ( cmd , PCI_CSR_BASE + PCI_NP_CBE_OFFSET ) ;
/*Execute the write by writing to NP_WDATA */
REG_WRITE ( PCI_CSR_BASE , PCI_NP_WDATA_OFFSET , data ) ;
writel ( data , PCI_CSR_BASE + PCI_NP_WDATA_OFFSET ) ;
return ;
}
/*
* PCI controller config registers are accessed through these functions
* i . e . these allow us to set up our own BARs etc .
*/
void crp_read ( unsigned int offset , unsigned int * data )
static void crp_write ( unsigned int offset , unsigned int data )
{
REG_WRITE ( PCI_CSR_BASE , PCI_CRP_AD_CBE_OFFSET , offset ) ;
REG_READ ( PCI_CSR_BASE , PCI_CRP_RDATA_OFFSET , * data ) ;
}
void crp_write ( unsigned int offset , unsigned int data )
{
/*The CRP address register bit 16 indicates that we want to do a write */
REG_WRITE ( PCI_CSR_BASE , PCI_CRP_AD_CBE_OFFSET ,
PCI_CRP_WRITE | offset ) ;
REG_WRITE ( PCI_CSR_BASE , PCI_CRP_WDATA_OFFSET , data ) ;
}
/*struct pci_controller *hose*/
void pci_ixp_init ( struct pci_controller * hose )
{
unsigned int regval ;
hose - > first_busno = 0 ;
hose - > last_busno = 0x00 ;
/* System memory space */
pci_set_region ( hose - > regions + 0 ,
PCI_MEMORY_BUS ,
PCI_MEMORY_PHY , PCI_MEMORY_SIZE , PCI_REGION_SYS_MEMORY ) ;
/* PCI memory space */
pci_set_region ( hose - > regions + 1 ,
PCI_MEM_BUS ,
PCI_MEM_PHY , PCI_MEM_SIZE , PCI_REGION_MEM ) ;
/* PCI I/O space */
pci_set_region ( hose - > regions + 2 ,
PCI_IO_BUS , PCI_IO_PHY , PCI_IO_SIZE , PCI_REGION_IO ) ;
hose - > region_count = 3 ;
pci_register_hose ( hose ) ;
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Init IXP PCI
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
REG_READ ( PCI_CSR_BASE , PCI_CSR_OFFSET , regval ) ;
regval | = 1 < < 2 ;
REG_WRITE ( PCI_CSR_BASE , PCI_CSR_OFFSET , regval ) ;
configure_pins ( ) ;
READ_GPIO_REG ( IXP425_GPIO_GPOUTR , regval ) ;
WRITE_GPIO_REG ( IXP425_GPIO_GPOUTR , regval & ( ~ ( 1 < < 13 ) ) ) ;
udelay ( 533 ) ;
sys_pci_gpio_clock_config ( ) ;
REG_WRITE ( PCI_CSR_BASE , PCI_INTEN_OFFSET , 0 ) ;
udelay ( 100 ) ;
READ_GPIO_REG ( IXP425_GPIO_GPOUTR , regval ) ;
WRITE_GPIO_REG ( IXP425_GPIO_GPOUTR , regval | ( 1 < < 13 ) ) ;
udelay ( 533 ) ;
crp_write ( PCI_CFG_BASE_ADDRESS_0 , IXP425_PCI_BAR_0_DEFAULT ) ;
crp_write ( PCI_CFG_BASE_ADDRESS_1 , IXP425_PCI_BAR_1_DEFAULT ) ;
crp_write ( PCI_CFG_BASE_ADDRESS_2 , IXP425_PCI_BAR_2_DEFAULT ) ;
crp_write ( PCI_CFG_BASE_ADDRESS_3 , IXP425_PCI_BAR_3_DEFAULT ) ;
crp_write ( PCI_CFG_BASE_ADDRESS_4 , IXP425_PCI_BAR_4_DEFAULT ) ;
crp_write ( PCI_CFG_BASE_ADDRESS_5 , IXP425_PCI_BAR_5_DEFAULT ) ;
/*Setup PCI-AHB and AHB-PCI address mappings */
REG_WRITE ( PCI_CSR_BASE , PCI_AHBMEMBASE_OFFSET ,
IXP425_PCI_AHBMEMBASE_DEFAULT ) ;
REG_WRITE ( PCI_CSR_BASE , PCI_AHBIOBASE_OFFSET ,
IXP425_PCI_AHBIOBASE_DEFAULT ) ;
REG_WRITE ( PCI_CSR_BASE , PCI_PCIMEMBASE_OFFSET ,
IXP425_PCI_PCIMEMBASE_DEFAULT ) ;
crp_write ( PCI_CFG_SUB_VENDOR_ID , IXP425_PCI_SUB_VENDOR_SYSTEM ) ;
REG_READ ( PCI_CSR_BASE , PCI_CSR_OFFSET , regval ) ;
regval | = PCI_CSR_IC | PCI_CSR_ABE | PCI_CSR_PDS ;
REG_WRITE ( PCI_CSR_BASE , PCI_CSR_OFFSET , regval ) ;
crp_write ( PCI_CFG_COMMAND , PCI_CFG_CMD_MAE | PCI_CFG_CMD_BME ) ;
udelay ( 1000 ) ;
pci_write_config_word ( 0 , PCI_CFG_COMMAND , INITIAL_PCI_CMD ) ;
REG_WRITE ( PCI_CSR_BASE , PCI_ISR_OFFSET , PCI_ISR_PSE
| PCI_ISR_PFE | PCI_ISR_PPE | PCI_ISR_AHBE ) ;
# ifdef CONFIG_PCI_SCAN_SHOW
printf ( " Device bus dev func deviceID vendorID \n " ) ;
# endif
pci_bus_scan ( ) ;
}
void configure_pins ( void )
{
unsigned int regval ;
/* Disable clock on GPIO PIN 14 */
READ_GPIO_REG ( IXP425_GPIO_GPCLKR , regval ) ;
WRITE_GPIO_REG ( IXP425_GPIO_GPCLKR , regval & ( ~ ( 1 < < 8 ) ) ) ;
READ_GPIO_REG ( IXP425_GPIO_GPCLKR , regval ) ;
READ_GPIO_REG ( IXP425_GPIO_GPOER , regval ) ;
WRITE_GPIO_REG ( IXP425_GPIO_GPOER ,
( ( ( ~ ( 3 < < 13 ) ) & regval ) | ( 0xf < < 8 ) ) ) ;
READ_GPIO_REG ( IXP425_GPIO_GPOER , regval ) ;
READ_GPIO_REG ( IXP425_GPIO_GPIT2R , regval ) ;
WRITE_GPIO_REG ( IXP425_GPIO_GPIT2R ,
( regval &
( ( 0x1 < < 9 ) | ( 0x1 < < 6 ) | ( 0x1 < < 3 ) | 0x1 ) ) ) ;
READ_GPIO_REG ( IXP425_GPIO_GPIT2R , regval ) ;
READ_GPIO_REG ( IXP425_GPIO_GPISR , regval ) ;
WRITE_GPIO_REG ( IXP425_GPIO_GPISR , ( regval | ( 0xf < < 8 ) ) ) ;
READ_GPIO_REG ( IXP425_GPIO_GPISR , regval ) ;
/*
* The CRP address register bit 16 indicates that we want to do a
* write
*/
writel ( PCI_CRP_WRITE | offset , PCI_CSR_BASE + PCI_CRP_AD_CBE_OFFSET ) ;
writel ( data , PCI_CSR_BASE + PCI_CRP_WDATA_OFFSET ) ;
}
void sys_pci_gpio_clock_config ( void )
void pci_ixp_init ( struct pci_controller * hose )
{
unsigned int regval ;
READ_GPIO_REG ( IXP425_GPIO_GPCLKR , regval ) ;
regval | = 0x1 < < 4 ;
WRITE_GPIO_REG ( IXP425_GPIO_GPCLKR , regval ) ;
READ_GPIO_REG ( IXP425_GPIO_GPCLKR , regval ) ;
regval | = 0x1 < < 8 ;
WRITE_GPIO_REG ( IXP425_GPIO_GPCLKR , regval ) ;
}
unsigned int csr ;
void pci_bus_scan ( void )
{
unsigned int bus = 0 , dev , func = 0 ;
unsigned short data16 ;
unsigned int data32 ;
unsigned char intPin ;
/* Assign first device to ourselves */
devices [ 0 ] . bus = 0 ;
devices [ 0 ] . device = 0 ;
devices [ 0 ] . func = 0 ;
crp_read ( PCI_CFG_VENDOR_ID , & data32 ) ;
devices [ 0 ] . vendor_id = data32 & IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK ;
devices [ 0 ] . device_id = data32 > > 16 ;
devices [ 0 ] . error = FALSE ;
devices [ 0 ] . bar [ NO_BAR ] . size = 0 ; /*dummy - required */
nDevices = 1 ;
nMBars = 0 ;
nIOBars = 0 ;
for ( dev = 0 ; dev < IXP425_PCI_MAX_DEV ; dev + + ) {
/*Check whether a device is present */
if ( pci_device_exists ( dev ) ! = TRUE ) {
/*Clear error bits in ISR, write 1 to clear */
REG_WRITE ( PCI_CSR_BASE , PCI_ISR_OFFSET , PCI_ISR_PSE
| PCI_ISR_PFE | PCI_ISR_PPE |
PCI_ISR_AHBE ) ;
continue ;
}
/*A device is present, add an entry to the array */
devices [ nDevices ] . bus = bus ;
devices [ nDevices ] . device = dev ;
devices [ nDevices ] . func = func ;
pci_read_config_word ( dev , PCI_CFG_VENDOR_ID , & data16 ) ;
devices [ nDevices ] . vendor_id = data16 ;
pci_read_config_word ( dev , PCI_CFG_DEVICE_ID , & data16 ) ;
devices [ nDevices ] . device_id = data16 ;
/*The device is functioning correctly, set error to FALSE */
devices [ nDevices ] . error = FALSE ;
/*Figure out what BARs are on this device */
sys_pci_bar_info_get ( nDevices , bus , dev , func ) ;
/*Figure out what INTX# line the card uses */
pci_read_config_byte ( dev , PCI_CFG_DEV_INT_PIN , & intPin ) ;
/*assign the appropriate irq line */
if ( intPin > PCI_IRQ_LINES ) {
devices [ nDevices ] . error = TRUE ;
} else if ( intPin ! = 0 ) {
/*This device uses an interrupt line */
/*devices[nDevices].irq = ixp425PciIntTranslate[dev][intPin-1]; */
devices [ nDevices ] . irq = intPin ;
}
# ifdef CONFIG_PCI_SCAN_SHOW
printf ( " %06d %03d %03d %04d %08d %08x \n " , nDevices ,
devices [ nDevices ] . vendor_id ) ;
/*
* Specify that the AHB bus is operating in big endian mode . Set up
* byte lane swapping between little - endian PCI and the big - endian
* AHB bus
*/
# ifdef __ARMEB__
csr = PCI_CSR_ABE | PCI_CSR_PDS | PCI_CSR_ADS ;
# else
csr = PCI_CSR_ABE ;
# endif
nDevices + + ;
}
calc_bars ( memBars , nMBars , IXP425_PCI_BAR_MEM_BASE ) ;
sys_pci_device_bars_write ( ) ;
REG_WRITE ( PCI_CSR_BASE , PCI_ISR_OFFSET , PCI_ISR_PSE
| PCI_ISR_PFE | PCI_ISR_PPE | PCI_ISR_AHBE ) ;
}
void sys_pci_bar_info_get ( unsigned int devnum ,
unsigned int bus ,
unsigned int dev , unsigned int func )
{
unsigned int data32 ;
unsigned int tmp ;
unsigned int size ;
pci_write_config_dword ( devnum ,
PCI_CFG_BASE_ADDRESS_0 , IXP425_PCI_BAR_QUERY ) ;
pci_read_config_dword ( devnum , PCI_CFG_BASE_ADDRESS_0 , & data32 ) ;
writel ( csr , PCI_CSR_BASE + PCI_CSR_OFFSET ) ;
devices [ devnum ] . bar [ 0 ] . address = ( data32 & 1 ) ;
writel ( 0 , PCI_CSR_BASE + PCI_INTEN_OFFSET ) ;
if ( data32 & 1 ) {
/* IO space */
tmp = data32 & ~ 0x3 ;
size = ~ ( tmp - 1 ) ;
devices [ devnum ] . bar [ 0 ] . size = size ;
if ( nIOBars < IXP425_PCI_MAX_BAR ) {
ioBars [ nIOBars + + ] = & devices [ devnum ] . bar [ 0 ] ;
}
} else {
/* Mem space */
tmp = data32 & ~ IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK ;
size = ~ ( tmp - 1 ) ;
devices [ devnum ] . bar [ 0 ] . size = size ;
if ( nMBars < IXP425_PCI_MAX_BAR ) {
memBars [ nMBars + + ] = & devices [ devnum ] . bar [ 0 ] ;
} else {
devices [ devnum ] . error = TRUE ;
}
}
devices [ devnum ] . bar [ 1 ] . size = 0 ;
}
void sortBars ( PciBar * Bars [ ] , unsigned int nBars )
{
unsigned int i , j ;
PciBar * tmp ;
if ( nBars = = 0 ) {
return ;
}
/* Sort biggest to smallest */
for ( i = 0 ; i < nBars - 1 ; i + + ) {
for ( j = i + 1 ; j < nBars ; j + + ) {
if ( Bars [ j ] - > size > Bars [ i ] - > size ) {
/* swap them */
tmp = Bars [ i ] ;
Bars [ i ] = Bars [ j ] ;
Bars [ j ] = tmp ;
}
}
}
}
/*
* We configure the PCI inbound memory windows to be
* 1 : 1 mapped to SDRAM
*/
crp_write ( PCI_CFG_BASE_ADDRESS_0 , 0x00000000 ) ;
crp_write ( PCI_CFG_BASE_ADDRESS_1 , 0x01000000 ) ;
crp_write ( PCI_CFG_BASE_ADDRESS_2 , 0x02000000 ) ;
crp_write ( PCI_CFG_BASE_ADDRESS_3 , 0x03000000 ) ;
/*
* Enable CSR window at 64 MiB to allow PCI masters
* to continue prefetching past 64 MiB boundary .
*/
crp_write ( PCI_CFG_BASE_ADDRESS_4 , 0x04000000 ) ;
/*
* Enable the IO window to be way up high , at 0xfffffc00
*/
crp_write ( PCI_CFG_BASE_ADDRESS_5 , 0xfffffc01 ) ;
void calc_bars ( PciBar * Bars [ ] , unsigned int nBars , unsigned int startAddr )
{
unsigned int i ;
/*Setup PCI-AHB and AHB-PCI address mappings */
writel ( 0x00010203 , PCI_CSR_BASE + PCI_AHBMEMBASE_OFFSET ) ;
if ( nBars = = 0 ) {
return ;
}
writel ( 0x00000000 , PCI_CSR_BASE + PCI_AHBIOBASE_OFFSET ) ;
for ( i = 0 ; i < nBars ; i + + ) {
Bars [ i ] - > address | = startAddr ;
startAddr + = Bars [ i ] - > size ;
}
}
writel ( 0x48494a4b , PCI_CSR_BASE + PCI_PCIMEMBASE_OFFSET ) ;
void sys_pci_device_bars_write ( void )
{
unsigned int i ;
int addr ;
for ( i = 1 ; i < nDevices ; i + + ) {
if ( devices [ i ] . error ) {
continue ;
}
pci_write_config_dword ( devices [ i ] . device ,
PCI_CFG_BASE_ADDRESS_0 ,
devices [ i ] . bar [ 0 ] . address ) ;
addr = BIT ( 31 - devices [ i ] . device ) |
( 0 < < PCI_NP_AD_FUNCSL ) |
( PCI_CFG_BASE_ADDRESS_0 & ~ 3 ) ;
pci_write_config_dword ( devices [ i ] . device ,
PCI_CFG_DEV_INT_LINE , devices [ i ] . irq ) ;
pci_write_config_word ( devices [ i ] . device ,
PCI_CFG_COMMAND , INITIAL_PCI_CMD ) ;
crp_write ( PCI_CFG_SUB_VENDOR_ID , IXP425_PCI_SUB_VENDOR_SYSTEM ) ;
}
}
crp_write ( PCI_CFG_COMMAND , PCI_CFG_CMD_MAE | PCI_CFG_CMD_BME ) ;
udelay ( 1000 ) ;
/* clear error bits in status register */
writel ( PCI_ISR_PSE | PCI_ISR_PFE | PCI_ISR_PPE | PCI_ISR_AHBE ,
PCI_CSR_BASE + PCI_ISR_OFFSET ) ;
int pci_device_exists ( unsigned int deviceNo )
{
unsigned int vendorId ;
unsigned int regval ;
pci_read_config_dword ( deviceNo , PCI_CFG_VENDOR_ID , & vendorId ) ;
/* There are two ways to find out an empty device.
* 1. check Master Abort bit after the access .
* 2. check whether the vendor id read back is 0x0 .
/*
* Set Initialize Complete in PCI Control Register : allow IXP4XX to
* respond to PCI configuration cycles .
*/
REG_READ ( PCI_CSR_BASE , PCI_ISR_OFFSET , regval ) ;
if ( ( vendorId ! = 0x0 ) & & ( ( regval & PCI_ISR_PFE ) = = 0 ) ) {
return TRUE ;
}
/*no device present, make sure that the master abort bit is reset */
csr | = PCI_CSR_IC ;
writel ( csr , PCI_CSR_BASE + PCI_CSR_OFFSET ) ;
REG_WRITE ( PCI_CSR_BASE , PCI_ISR_OFFSET , PCI_ISR_PFE ) ;
return FALSE ;
}
hose - > first_busno = 0 ;
hose - > last_busno = 0 ;
pci_dev_t pci_find_devices ( struct pci_device_id * ids , int devNo )
{
unsigned int i ;
unsigned int devdidvid ;
unsigned int didvid ;
unsigned int vendorId , deviceId ;
/* System memory space */
pci_set_region ( hose - > regions + 0 ,
PCI_MEMORY_BUS ,
PCI_MEMORY_PHY , PCI_MEMORY_SIZE , PCI_REGION_SYS_MEMORY ) ;
vendorId = ids - > vendor ;
deviceId = ids - > device ;
didvid = ( ( deviceId < < 16 ) & IXP425_PCI_TOP_WORD_OF_LONG_MASK ) |
( vendorId & IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK ) ;
/* PCI memory space */
pci_set_region ( hose - > regions + 1 ,
PCI_MEM_BUS ,
PCI_MEM_PHY , PCI_MEM_SIZE , PCI_REGION_MEM ) ;
/* PCI I/O space */
pci_set_region ( hose - > regions + 2 ,
PCI_IO_BUS , PCI_IO_PHY , PCI_IO_SIZE , PCI_REGION_IO ) ;
for ( i = devNo + 1 ; i < nDevices ; i + + ) {
hose - > region_count = 3 ;
pci_read_config_dword ( devices [ i ] . device , PCI_CFG_VENDOR_ID ,
& devdidvid ) ;
pci_set_ops ( hose ,
pci_ixp_hose_read_config_byte ,
pci_ixp_hose_read_config_word ,
pci_ixp_hose_read_config_dword ,
pci_ixp_hose_write_config_byte ,
pci_ixp_hose_write_config_word ,
pci_ixp_hose_write_config_dword ) ;
if ( devdidvid = = didvid ) {
return devices [ i ] . device ;
}
}
return - 1 ;
pci_register_hose ( hose ) ;
hose - > last_busno = pci_hose_scan ( hose ) ;
}