2011-05-23 21:04:47 +00:00
/*
* leon_pci . c : LEON Host PCI support
*
* Copyright ( C ) 2011 Aeroflex Gaisler AB , Daniel Hellstrom
*
* Code is partially derived from pcic . c
*/
# include <linux/of_device.h>
# include <linux/kernel.h>
# include <linux/pci.h>
2011-07-18 15:57:46 -04:00
# include <linux/export.h>
2011-05-23 21:04:47 +00:00
# include <asm/leon.h>
# include <asm/leon_pci.h>
/* The LEON architecture does not rely on a BIOS or bootloader to setup
* PCI for us . The Linux generic routines are used to setup resources ,
2012-02-23 20:19:04 -07:00
* reset values of configuration - space register settings are preserved .
*
* PCI Memory and Prefetchable Memory is direct - mapped . However I / O Space is
* accessed through a Window which is translated to low 64 KB in PCI space , the
* first 4 KB is not used so 60 KB is available .
2011-05-23 21:04:47 +00:00
*/
void leon_pci_init ( struct platform_device * ofdev , struct leon_pci_info * info )
{
2011-10-28 16:27:58 -06:00
LIST_HEAD ( resources ) ;
2011-05-23 21:04:47 +00:00
struct pci_bus * root_bus ;
2012-02-23 20:19:04 -07:00
pci_add_resource_offset ( & resources , & info - > io_space ,
info - > io_space . start - 0x1000 ) ;
2011-10-28 16:27:58 -06:00
pci_add_resource ( & resources , & info - > mem_space ) ;
2013-03-04 00:24:27 +00:00
info - > busn . flags = IORESOURCE_BUS ;
pci_add_resource ( & resources , & info - > busn ) ;
2011-05-23 21:04:47 +00:00
2011-10-28 16:27:58 -06:00
root_bus = pci_scan_root_bus ( & ofdev - > dev , 0 , info - > ops , info ,
& resources ) ;
2015-03-12 15:07:04 -05:00
if ( ! root_bus ) {
2011-10-28 16:27:58 -06:00
pci_free_resource_list ( & resources ) ;
2015-03-12 15:07:04 -05:00
return ;
2011-05-23 21:04:47 +00:00
}
2015-03-12 15:07:04 -05:00
/* Setup IRQs of all devices using custom routines */
pci_fixup_irqs ( pci_common_swizzle , info - > map_irq ) ;
/* Assign devices with resources */
pci_assign_unassigned_resources ( ) ;
pci_bus_add_devices ( root_bus ) ;
2011-05-23 21:04:47 +00:00
}
2012-12-21 14:03:26 -08:00
void pcibios_fixup_bus ( struct pci_bus * pbus )
2011-05-23 21:04:47 +00:00
{
struct pci_dev * dev ;
int i , has_io , has_mem ;
u16 cmd ;
list_for_each_entry ( dev , & pbus - > devices , bus_list ) {
/*
* We can not rely on that the bootloader has enabled I / O
* or memory access to PCI devices . Instead we enable it here
* if the device has BARs of respective type .
*/
has_io = has_mem = 0 ;
for ( i = 0 ; i < PCI_ROM_RESOURCE ; i + + ) {
unsigned long f = dev - > resource [ i ] . flags ;
if ( f & IORESOURCE_IO )
has_io = 1 ;
else if ( f & IORESOURCE_MEM )
has_mem = 1 ;
}
/* ROM BARs are mapped into 32-bit memory space */
if ( dev - > resource [ PCI_ROM_RESOURCE ] . end ! = 0 ) {
dev - > resource [ PCI_ROM_RESOURCE ] . flags | =
IORESOURCE_ROM_ENABLE ;
has_mem = 1 ;
}
pci_bus_read_config_word ( pbus , dev - > devfn , PCI_COMMAND , & cmd ) ;
if ( has_io & & ! ( cmd & PCI_COMMAND_IO ) ) {
# ifdef CONFIG_PCI_DEBUG
printk ( KERN_INFO " LEONPCI: Enabling I/O for dev %s \n " ,
pci_name ( dev ) ) ;
# endif
cmd | = PCI_COMMAND_IO ;
pci_bus_write_config_word ( pbus , dev - > devfn , PCI_COMMAND ,
cmd ) ;
}
if ( has_mem & & ! ( cmd & PCI_COMMAND_MEMORY ) ) {
# ifdef CONFIG_PCI_DEBUG
printk ( KERN_INFO " LEONPCI: Enabling MEMORY for dev "
" %s \n " , pci_name ( dev ) ) ;
# endif
cmd | = PCI_COMMAND_MEMORY ;
pci_bus_write_config_word ( pbus , dev - > devfn , PCI_COMMAND ,
cmd ) ;
}
}
}
resource_size_t pcibios_align_resource ( void * data , const struct resource * res ,
resource_size_t size , resource_size_t align )
{
return res - > start ;
}