@ -93,6 +93,7 @@ struct ls_pcie {
void __iomem * dbi ;
void __iomem * va_cfg0 ;
void __iomem * va_cfg1 ;
int next_lut_index ;
struct pci_controller hose ;
} ;
@ -482,6 +483,147 @@ static void ls_pcie_setup_ep(struct ls_pcie *pcie, struct ls_pcie_info *info)
}
}
# ifdef CONFIG_FSL_LSCH3
/*
* Return next available LUT index .
*/
static int ls_pcie_next_lut_index ( struct ls_pcie * pcie )
{
if ( pcie - > next_lut_index < PCIE_LUT_ENTRY_COUNT )
return pcie - > next_lut_index + + ;
else
return - 1 ; /* LUT is full */
}
/*
* Program a single LUT entry
*/
static void ls_pcie_lut_set_mapping ( struct ls_pcie * pcie , int index , u32 devid ,
u32 streamid )
{
void __iomem * lut ;
lut = pcie - > dbi + PCIE_LUT_BASE ;
/* leave mask as all zeroes, want to match all bits */
writel ( ( devid < < 16 ) , lut + PCIE_LUT_UDR ( index ) ) ;
writel ( streamid | PCIE_LUT_ENABLE , lut + PCIE_LUT_LDR ( index ) ) ;
}
/* returns the next available streamid */
static u32 ls_pcie_next_streamid ( void )
{
static int next_stream_id = FSL_PEX_STREAM_ID_START ;
if ( next_stream_id > FSL_PEX_STREAM_ID_END )
return 0xffffffff ;
return next_stream_id + + ;
}
/*
* An msi - map is a property to be added to the pci controller
* node . It is a table , where each entry consists of 4 fields
* e . g . :
*
* msi - map = < [ devid ] [ phandle - to - msi - ctrl ] [ stream - id ] [ count ]
* [ devid ] [ phandle - to - msi - ctrl ] [ stream - id ] [ count ] > ;
*/
static void fdt_pcie_set_msi_map_entry ( void * blob , struct ls_pcie * pcie ,
u32 devid , u32 streamid )
{
char pcie_path [ 19 ] ;
u32 * prop ;
u32 phandle ;
int nodeoffset ;
/* find pci controller node */
snprintf ( pcie_path , sizeof ( pcie_path ) , " /soc/pcie@%llx " ,
( u64 ) pcie - > dbi ) ;
nodeoffset = fdt_path_offset ( blob , pcie_path ) ;
if ( nodeoffset < 0 ) {
printf ( " \n %s: ERROR: unable to update PCIe node: %s \n " ,
__func__ , pcie_path ) ;
return ;
}
/* get phandle to MSI controller */
prop = ( u32 * ) fdt_getprop ( blob , nodeoffset , " msi-parent " , 0 ) ;
if ( prop = = NULL ) {
printf ( " \n %s: ERROR: missing msi-parent: %s \n " , __func__ ,
pcie_path ) ;
return ;
}
phandle = be32_to_cpu ( * prop ) ;
/* set one msi-map row */
fdt_appendprop_u32 ( blob , nodeoffset , " msi-map " , devid ) ;
fdt_appendprop_u32 ( blob , nodeoffset , " msi-map " , phandle ) ;
fdt_appendprop_u32 ( blob , nodeoffset , " msi-map " , streamid ) ;
fdt_appendprop_u32 ( blob , nodeoffset , " msi-map " , 1 ) ;
}
static void fdt_fixup_pcie ( void * blob )
{
unsigned int found_multi = 0 ;
unsigned char header_type ;
int index ;
u32 streamid ;
pci_dev_t dev ;
int bus ;
unsigned short id ;
struct pci_controller * hose ;
struct ls_pcie * pcie ;
int i ;
for ( i = 0 , hose = pci_get_hose_head ( ) ; hose ; hose = hose - > next , i + + ) {
pcie = hose - > priv_data ;
for ( bus = hose - > first_busno ; bus < = hose - > last_busno ; bus + + ) {
for ( dev = PCI_BDF ( bus , 0 , 0 ) ;
dev < PCI_BDF ( bus , PCI_MAX_PCI_DEVICES - 1 ,
PCI_MAX_PCI_FUNCTIONS - 1 ) ;
dev + = PCI_BDF ( 0 , 0 , 1 ) ) {
if ( PCI_FUNC ( dev ) & & ! found_multi )
continue ;
pci_read_config_word ( dev , PCI_VENDOR_ID , & id ) ;
pci_read_config_byte ( dev , PCI_HEADER_TYPE ,
& header_type ) ;
if ( ( id = = 0xFFFF ) | | ( id = = 0x0000 ) )
continue ;
if ( ! PCI_FUNC ( dev ) )
found_multi = header_type & 0x80 ;
streamid = ls_pcie_next_streamid ( ) ;
if ( streamid = = 0xffffffff ) {
printf ( " ERROR: no stream ids free \n " ) ;
continue ;
}
index = ls_pcie_next_lut_index ( pcie ) ;
if ( index < 0 ) {
printf ( " ERROR: no LUT indexes free \n " ) ;
continue ;
}
/* map PCI b.d.f to streamID in LUT */
ls_pcie_lut_set_mapping ( pcie , index , dev > > 8 ,
streamid ) ;
/* update msi-map in device tree */
fdt_pcie_set_msi_map_entry ( blob , pcie , dev > > 8 ,
streamid ) ;
}
}
}
}
# endif
int ls_pcie_init_ctrl ( int busno , enum srds_prtcl dev , struct ls_pcie_info * info )
{
struct ls_pcie * pcie ;
@ -513,6 +655,7 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info)
pcie - > va_cfg1 = map_physmem ( info - > cfg1_phys ,
info - > cfg1_size ,
MAP_NOCACHE ) ;
pcie - > next_lut_index = 0 ;
/* outbound memory */
pci_set_region ( & hose - > regions [ 0 ] ,
@ -657,6 +800,10 @@ void ft_pci_setup(void *blob, bd_t *bd)
# ifdef CONFIG_PCIE4
ft_pcie_ls_setup ( blob , FSL_PCIE_COMPAT , CONFIG_SYS_PCIE4_ADDR , PCIE4 ) ;
# endif
# ifdef CONFIG_FSL_LSCH3
fdt_fixup_pcie ( blob ) ;
# endif
}
# else