@ -2,7 +2,7 @@
* ( C ) Copyright 2001 Sysgo Real - Time Solutions , GmbH < www . elinos . com >
* Andreas Heppel < aheppel @ sysgo . de >
*
* ( C ) Copyright 2002
* ( C ) Copyright 2002 , 2003
* Wolfgang Denk , DENX Software Engineering , wd @ denx . de .
*
* See file CREDITS for list of people who contributed to this
@ -48,12 +48,12 @@
*
*/
# define PCI_HOSE_OP(rw, size, type) \
int pci_hose_ # # rw # # _config_ # # size ( struct pci_controller * hose , \
pci_dev_t dev , \
int offset , type value ) \
{ \
return hose - > rw # # _ # # size ( hose , dev , offset , value ) ; \
# define PCI_HOSE_OP(rw, size, type) \
int pci_hose_ # # rw # # _config_ # # size ( struct pci_controller * hose , \
pci_dev_t dev , \
int offset , type value ) \
{ \
return hose - > rw # # _ # # size ( hose , dev , offset , value ) ; \
}
PCI_HOSE_OP ( read , byte , u8 * )
@ -63,18 +63,18 @@ PCI_HOSE_OP(write, byte, u8)
PCI_HOSE_OP ( write , word , u16 )
PCI_HOSE_OP ( write , dword , u32 )
# define PCI_OP(rw, size, type, error_code) \
int pci_ # # rw # # _config_ # # size ( pci_dev_t dev , int offset , type value ) \
{ \
struct pci_controller * hose = pci_bus_to_hose ( PCI_BUS ( dev ) ) ; \
\
if ( ! hose ) \
{ \
error_code ; \
return - 1 ; \
} \
\
return pci_hose_ # # rw # # _config_ # # size ( hose , dev , offset , value ) ; \
# define PCI_OP(rw, size, type, error_code) \
int pci_ # # rw # # _config_ # # size ( pci_dev_t dev , int offset , type value ) \
{ \
struct pci_controller * hose = pci_bus_to_hose ( PCI_BUS ( dev ) ) ; \
\
if ( ! hose ) \
{ \
error_code ; \
return - 1 ; \
} \
\
return pci_hose_ # # rw # # _config_ # # size ( hose , dev , offset , value ) ; \
}
PCI_OP ( read , byte , u8 * , * value = 0xff )
@ -84,40 +84,40 @@ PCI_OP(write, byte, u8, )
PCI_OP ( write , word , u16 , )
PCI_OP ( write , dword , u32 , )
# define PCI_READ_VIA_DWORD_OP(size, type, off_mask) \
int pci_hose_read_config_ # # size # # _via_dword ( struct pci_controller * hose , \
pci_dev_t dev , \
int offset , type val ) \
{ \
u32 val32 ; \
\
if ( pci_hose_read_config_dword ( hose , dev , offset & 0xfc , & val32 ) < 0 ) \
return - 1 ; \
\
* val = ( val32 > > ( ( offset & ( int ) off_mask ) * 8 ) ) ; \
\
return 0 ; \
# define PCI_READ_VIA_DWORD_OP(size, type, off_mask) \
int pci_hose_read_config_ # # size # # _via_dword ( struct pci_controller * hose , \
pci_dev_t dev , \
int offset , type val ) \
{ \
u32 val32 ; \
\
if ( pci_hose_read_config_dword ( hose , dev , offset & 0xfc , & val32 ) < 0 ) \
return - 1 ; \
\
* val = ( val32 > > ( ( offset & ( int ) off_mask ) * 8 ) ) ; \
\
return 0 ; \
}
# define PCI_WRITE_VIA_DWORD_OP(size, type, off_mask, val_mask) \
int pci_hose_write_config_ # # size # # _via_dword ( struct pci_controller * hose , \
pci_dev_t dev , \
int offset , type val ) \
{ \
u32 val32 , mask , ldata ; \
\
if ( pci_hose_read_config_dword ( hose , dev , offset & 0xfc , & val32 ) < 0 ) \
return - 1 ; \
\
mask = val_mask ; \
# define PCI_WRITE_VIA_DWORD_OP(size, type, off_mask, val_mask) \
int pci_hose_write_config_ # # size # # _via_dword ( struct pci_controller * hose , \
pci_dev_t dev , \
int offset , type val ) \
{ \
u32 val32 , mask , ldata ; \
\
if ( pci_hose_read_config_dword ( hose , dev , offset & 0xfc , & val32 ) < 0 ) \
return - 1 ; \
\
mask = val_mask ; \
ldata = ( ( ( unsigned long ) val ) & mask ) < < ( ( offset & ( int ) off_mask ) * 8 ) ; \
mask < < = ( ( mask & ( int ) off_mask ) * 8 ) ; \
val32 = ( val32 & ~ mask ) | ldata ; \
\
if ( pci_hose_write_config_dword ( hose , dev , offset & 0xfc , val32 ) < 0 ) \
return - 1 ; \
\
return 0 ; \
mask < < = ( ( mask & ( int ) off_mask ) * 8 ) ; \
val32 = ( val32 & ~ mask ) | ldata ; \
\
if ( pci_hose_write_config_dword ( hose , dev , offset & 0xfc , val32 ) < 0 ) \
return - 1 ; \
\
return 0 ; \
}
PCI_READ_VIA_DWORD_OP ( byte , u8 * , 0x03 )
@ -143,13 +143,12 @@ void pci_register_hose(struct pci_controller* hose)
* phose = hose ;
}
struct pci_controller * pci_bus_to_hose ( int bus )
struct pci_controller * pci_bus_to_hose ( int bus )
{
struct pci_controller * hose ;
for ( hose = hose_head ; hose ; hose = hose - > next )
if ( bus > = hose - > first_busno & &
bus < = hose - > last_busno )
if ( bus > = hose - > first_busno & & bus < = hose - > last_busno )
return hose ;
return NULL ;
@ -178,16 +177,13 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
# endif
bdf + = PCI_BDF ( 0 , 0 , 1 ) )
{
if ( ! PCI_FUNC ( bdf ) )
{
if ( ! PCI_FUNC ( bdf ) ) {
pci_read_config_byte ( bdf ,
PCI_HEADER_TYPE ,
& header_type ) ;
found_multi = header_type & 0x80 ;
}
else
{
} else {
if ( ! found_multi )
continue ;
}
@ -228,22 +224,20 @@ pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
*
*/
unsigned long pci_hose_phys_to_bus ( struct pci_controller * hose ,
unsigned long phys_addr ,
unsigned long flags )
unsigned long pci_hose_phys_to_bus ( struct pci_controller * hose ,
unsigned long phys_addr ,
unsigned long flags )
{
struct pci_region * res ;
unsigned long bus_addr ;
int i ;
if ( ! hose )
{
printf ( " pci_hose_phys_to_bus: %s \n " , " invalid hose " ) ;
if ( ! hose ) {
printf ( " pci_hose_phys_to_bus: %s \n " , " invalid hose " ) ;
goto Done ;
}
for ( i = 0 ; i < hose - > region_count ; i + + )
{
for ( i = 0 ; i < hose - > region_count ; i + + ) {
res = & hose - > regions [ i ] ;
if ( ( ( res - > flags ^ flags ) & PCI_REGION_TYPE ) ! = 0 )
@ -252,15 +246,14 @@ unsigned long pci_hose_phys_to_bus(struct pci_controller* hose,
bus_addr = phys_addr - res - > phys_start + res - > bus_start ;
if ( bus_addr > = res - > bus_start & &
bus_addr < res - > bus_start + res - > size )
{
bus_addr < res - > bus_start + res - > size ) {
return bus_addr ;
}
}
printf ( " pci_hose_phys_to_bus: %s \n " , " invalid physical address " ) ;
printf ( " pci_hose_phys_to_bus: %s \n " , " invalid physical address " ) ;
Done :
Done :
return 0 ;
}
@ -271,29 +264,26 @@ unsigned long pci_hose_bus_to_phys(struct pci_controller* hose,
struct pci_region * res ;
int i ;
if ( ! hose )
{
printf ( " pci_hose_bus_to_phys: %s \n " , " invalid hose " ) ;
if ( ! hose ) {
printf ( " pci_hose_bus_to_phys: %s \n " , " invalid hose " ) ;
goto Done ;
}
for ( i = 0 ; i < hose - > region_count ; i + + )
{
for ( i = 0 ; i < hose - > region_count ; i + + ) {
res = & hose - > regions [ i ] ;
if ( ( ( res - > flags ^ flags ) & PCI_REGION_TYPE ) ! = 0 )
continue ;
if ( bus_addr > = res - > bus_start & &
bus_addr < res - > bus_start + res - > size )
{
bus_addr < res - > bus_start + res - > size ) {
return bus_addr - res - > bus_start + res - > phys_start ;
}
}
printf ( " pci_hose_bus_to_phys: %s \n " , " invalid physical address " ) ;
printf ( " pci_hose_bus_to_phys: %s \n " , " invalid physical address " ) ;
Done :
Done :
return 0 ;
}
@ -311,14 +301,14 @@ int pci_hose_config_device(struct pci_controller *hose,
unsigned char pin ;
int bar , found_mem64 ;
DEBUGF ( " PCI Config: I/O=0x%lx, Memory=0x%lx, Command=0x%lx \n " , io , mem , command ) ;
DEBUGF ( " PCI Config: I/O=0x%lx, Memory=0x%lx, Command=0x%lx \n " ,
io , mem , command ) ;
pci_hose_write_config_dword ( hose , dev , PCI_COMMAND , 0 ) ;
pci_hose_write_config_dword ( hose , dev , PCI_COMMAND , 0 ) ;
for ( bar = PCI_BASE_ADDRESS_0 ; bar < PCI_BASE_ADDRESS_5 ; bar + = 4 )
{
pci_hose_write_config_dword ( hose , dev , bar , 0xffffffff ) ;
pci_hose_read_config_dword ( hose , dev , bar , & bar_response ) ;
for ( bar = PCI_BASE_ADDRESS_0 ; bar < PCI_BASE_ADDRESS_5 ; bar + = 4 ) {
pci_hose_write_config_dword ( hose , dev , bar , 0xffffffff ) ;
pci_hose_read_config_dword ( hose , dev , bar , & bar_response ) ;
if ( ! bar_response )
continue ;
@ -326,51 +316,51 @@ int pci_hose_config_device(struct pci_controller *hose,
found_mem64 = 0 ;
/* Check the BAR type and set our address mask */
if ( bar_response & PCI_BASE_ADDRESS_SPACE )
{
if ( bar_response & PCI_BASE_ADDRESS_SPACE ) {
bar_size = ~ ( bar_response & PCI_BASE_ADDRESS_IO_MASK ) + 1 ;
bar_value = io ;
/* round up region base address to a multiple of size */
io = ( ( io - 1 ) | ( bar_size - 1 ) ) + 1 ;
}
else
{
if ( ( bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK ) = =
PCI_BASE_ADDRESS_MEM_TYPE_64 )
bar_value = io ;
/* compute new region base address */
io = io + bar_size ;
} else {
if ( ( bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK ) = =
PCI_BASE_ADDRESS_MEM_TYPE_64 )
found_mem64 = 1 ;
bar_size = ~ ( bar_response & PCI_BASE_ADDRESS_MEM_MASK ) + 1 ;
bar_value = mem ;
/* round up region base address to multiple of size */
mem = ( ( mem - 1 ) | ( bar_size - 1 ) ) + 1 ;
bar_value = mem ;
/* compute new region base address */
mem = mem + bar_size ;
}
/* Write it out and update our limit */
pci_hose_write_config_dword ( hose , dev , bar , bar_value ) ;
pci_hose_write_config_dword ( hose , dev , bar , bar_value ) ;
if ( found_mem64 )
{
if ( found_mem64 ) {
bar + = 4 ;
pci_hose_write_config_dword ( hose , dev , bar , 0x00000000 ) ;
pci_hose_write_config_dword ( hose , dev , bar , 0x00000000 ) ;
}
}
/* Configure Cache Line Size Register */
pci_hose_write_config_byte ( hose , dev , PCI_CACHE_LINE_SIZE , 0x08 ) ;
pci_hose_write_config_byte ( hose , dev , PCI_CACHE_LINE_SIZE , 0x08 ) ;
/* Configure Latency Timer */
pci_hose_write_config_byte ( hose , dev , PCI_LATENCY_TIMER , 0x80 ) ;
pci_hose_write_config_byte ( hose , dev , PCI_LATENCY_TIMER , 0x80 ) ;
/* Disable interrupt line, if device says it wants to use interrupts */
pci_hose_read_config_byte ( hose , dev , PCI_INTERRUPT_PIN , & pin ) ;
if ( pin ! = 0 )
{
pci_hose_write_config_byte ( hose , dev , PCI_INTERRUPT_LINE , 0xff ) ;
pci_hose_read_config_byte ( hose , dev , PCI_INTERRUPT_PIN , & pin ) ;
if ( pin ! = 0 ) {
pci_hose_write_config_byte ( hose , dev , PCI_INTERRUPT_LINE , 0xff ) ;
}
pci_hose_read_config_dword ( hose , dev , PCI_COMMAND , & old_command ) ;
pci_hose_write_config_dword ( hose , dev , PCI_COMMAND ,
( old_command & 0xffff0000 ) | command ) ;
pci_hose_read_config_dword ( hose , dev , PCI_COMMAND , & old_command ) ;
pci_hose_write_config_dword ( hose , dev , PCI_COMMAND ,
( old_command & 0xffff0000 ) | command ) ;
return 0 ;
}
@ -389,15 +379,13 @@ struct pci_config_table *pci_find_config(struct pci_controller *hose,
{
struct pci_config_table * table ;
for ( table = hose - > config_table ; table & & table - > vendor ; table + + )
{
for ( table = hose - > config_table ; table & & table - > vendor ; table + + ) {
if ( ( table - > vendor = = PCI_ANY_ID | | table - > vendor = = vendor ) & &
( table - > device = = PCI_ANY_ID | | table - > device = = device ) & &
( table - > class = = PCI_ANY_ID | | table - > class = = class ) & &
( table - > bus = = PCI_ANY_ID | | table - > bus = = bus ) & &
( table - > dev = = PCI_ANY_ID | | table - > dev = = dev ) & &
( table - > func = = PCI_ANY_ID | | table - > func = = func ) )
{
( table - > func = = PCI_ANY_ID | | table - > func = = func ) ) {
return table ;
}
}