@ -111,6 +111,10 @@ struct pcie_dw_mvebu {
void * cfg_base ;
fdt_size_t cfg_size ;
int first_busno ;
/* IO and MEM PCI regions */
struct pci_region io ;
struct pci_region mem ;
} ;
static int pcie_dw_get_link_speed ( const void * regs_base )
@ -126,6 +130,34 @@ static int pcie_dw_get_link_width(const void *regs_base)
}
/**
* pcie_dw_prog_outbound_atu ( ) - Configure ATU for outbound accesses
*
* @ pcie : Pointer to the PCI controller state
* @ index : ATU region index
* @ type : ATU accsess type
* @ cpu_addr : the physical address for the translation entry
* @ pci_addr : the pcie bus address for the translation entry
* @ size : the size of the translation entry
*/
static void pcie_dw_prog_outbound_atu ( struct pcie_dw_mvebu * pcie , int index ,
int type , u64 cpu_addr , u64 pci_addr ,
u32 size )
{
writel ( PCIE_ATU_REGION_OUTBOUND | index ,
pcie - > ctrl_base + PCIE_ATU_VIEWPORT ) ;
writel ( lower_32_bits ( cpu_addr ) , pcie - > ctrl_base + PCIE_ATU_LOWER_BASE ) ;
writel ( upper_32_bits ( cpu_addr ) , pcie - > ctrl_base + PCIE_ATU_UPPER_BASE ) ;
writel ( lower_32_bits ( cpu_addr + size - 1 ) ,
pcie - > ctrl_base + PCIE_ATU_LIMIT ) ;
writel ( lower_32_bits ( pci_addr ) ,
pcie - > ctrl_base + PCIE_ATU_LOWER_TARGET ) ;
writel ( upper_32_bits ( pci_addr ) ,
pcie - > ctrl_base + PCIE_ATU_UPPER_TARGET ) ;
writel ( type , pcie - > ctrl_base + PCIE_ATU_CR1 ) ;
writel ( PCIE_ATU_ENABLE , pcie - > ctrl_base + PCIE_ATU_CR2 ) ;
}
/**
* set_cfg_address ( ) - Configure the PCIe controller config space access
*
* @ pcie : Pointer to the PCI controller state
@ -143,27 +175,29 @@ static uintptr_t set_cfg_address(struct pcie_dw_mvebu *pcie,
pci_dev_t d , uint where )
{
uintptr_t va_address ;
u32 atu_type ;
/*
* Region # 0 is used for Outbound CFG space access .
* Direction = Outbound
* Region Index = 0
*/
writel ( 0 , pcie - > ctrl_base + PCIE_ATU_VIEWPORT ) ;
if ( PCI_BUS ( d ) = = ( pcie - > first_busno + 1 ) )
/* For local bus, change TLP Type field to 4. */
writel ( PCIE_ATU_TYPE_CFG0 , pcie - > ctrl_base + PCIE_ATU_CR1 ) ;
atu_type = PCIE_ATU_TYPE_CFG0 ;
else
/* Otherwise, change TLP Type field to 5. */
writel ( PCIE_ATU_TYPE_CFG1 , pcie - > ctrl_base + PCIE_ATU_CR1 ) ;
atu_type = PCIE_ATU_TYPE_CFG1 ;
if ( PCI_BUS ( d ) = = pcie - > first_busno ) {
/* Accessing root port configuration space. */
va_address = ( uintptr_t ) pcie - > ctrl_base ;
} else {
d = PCI_MASK_BUS ( d ) | ( PCI_BUS ( d ) - pcie - > first_busno ) ;
writel ( d < < 8 , pcie - > ctrl_base + PCIE_ATU_LOWER_TARGET ) ;
pcie_dw_prog_outbound_atu ( pcie , PCIE_ATU_REGION_INDEX0 ,
atu_type , ( u64 ) pcie - > cfg_base ,
d < < 8 , pcie - > cfg_size ) ;
va_address = ( uintptr_t ) pcie - > cfg_base ;
}
@ -231,6 +265,10 @@ static int pcie_dw_mvebu_read_config(struct udevice *bus, pci_dev_t bdf,
debug ( " (addr,val)=(0x%04x, 0x%08lx) \n " , offset , value ) ;
* valuep = pci_conv_32_to_size ( value , offset , size ) ;
pcie_dw_prog_outbound_atu ( pcie , PCIE_ATU_REGION_INDEX0 ,
PCIE_ATU_TYPE_IO , pcie - > io . phys_start ,
pcie - > io . bus_start , pcie - > io . size ) ;
return 0 ;
}
@ -272,6 +310,10 @@ static int pcie_dw_mvebu_write_config(struct udevice *bus, pci_dev_t bdf,
value = pci_conv_size_to_32 ( old , value , offset , size ) ;
writel ( value , va_address ) ;
pcie_dw_prog_outbound_atu ( pcie , PCIE_ATU_REGION_INDEX0 ,
PCIE_ATU_TYPE_IO , pcie - > io . phys_start ,
pcie - > io . bus_start , pcie - > io . size ) ;
return 0 ;
}
@ -388,34 +430,6 @@ static int pcie_dw_mvebu_pcie_link_up(const void *regs_base, u32 cap_speed)
}
/**
* pcie_dw_regions_setup ( ) - iATU region setup
*
* @ pcie : Pointer to the PCI controller state
*
* Configure the iATU regions in the PCIe controller for outbound access .
*/
static void pcie_dw_regions_setup ( struct pcie_dw_mvebu * pcie )
{
/*
* Region # 0 is used for Outbound CFG space access .
* Direction = Outbound
* Region Index = 0
*/
writel ( 0 , pcie - > ctrl_base + PCIE_ATU_VIEWPORT ) ;
writel ( ( u32 ) ( uintptr_t ) pcie - > cfg_base , pcie - > ctrl_base
+ PCIE_ATU_LOWER_BASE ) ;
writel ( 0 , pcie - > ctrl_base + PCIE_ATU_UPPER_BASE ) ;
writel ( ( u32 ) ( uintptr_t ) pcie - > cfg_base + pcie - > cfg_size ,
pcie - > ctrl_base + PCIE_ATU_LIMIT ) ;
writel ( 0 , pcie - > ctrl_base + PCIE_ATU_LOWER_TARGET ) ;
writel ( 0 , pcie - > ctrl_base + PCIE_ATU_UPPER_TARGET ) ;
writel ( PCIE_ATU_TYPE_CFG0 , pcie - > ctrl_base + PCIE_ATU_CR1 ) ;
writel ( PCIE_ATU_ENABLE , pcie - > ctrl_base + PCIE_ATU_CR2 ) ;
}
/**
* pcie_dw_set_host_bars ( ) - Configure the host BARs
*
* @ regs_base : A pointer to the PCIe controller registers
@ -495,7 +509,18 @@ static int pcie_dw_mvebu_probe(struct udevice *dev)
hose - > first_busno ) ;
}
pcie_dw_regions_setup ( pcie ) ;
/* Store the IO and MEM windows settings for future use by the ATU */
pcie - > io . phys_start = hose - > regions [ 0 ] . phys_start ; /* IO base */
pcie - > io . bus_start = hose - > regions [ 0 ] . bus_start ; /* IO_bus_addr */
pcie - > io . size = hose - > regions [ 0 ] . size ; /* IO size */
pcie - > mem . phys_start = hose - > regions [ 1 ] . phys_start ; /* MEM base */
pcie - > mem . bus_start = hose - > regions [ 1 ] . bus_start ; /* MEM_bus_addr */
pcie - > mem . size = hose - > regions [ 1 ] . size ; /* MEM size */
pcie_dw_prog_outbound_atu ( pcie , PCIE_ATU_REGION_INDEX1 ,
PCIE_ATU_TYPE_MEM , pcie - > mem . phys_start ,
pcie - > mem . bus_start , pcie - > mem . size ) ;
/* Set the CLASS_REV of RC CFG header to PCI_CLASS_BRIDGE_PCI */
clrsetbits_le32 ( pcie - > ctrl_base + PCI_CLASS_REVISION ,