@ -25,6 +25,10 @@
# define CONFIG_SYS_PCI_MEMORY_SIZE (2 * 1024 * 1024 * 1024UL) /* 2G */
# endif
# ifndef CONFIG_SYS_PCI_EP_MEMORY_BASE
# define CONFIG_SYS_PCI_EP_MEMORY_BASE CONFIG_SYS_LOAD_ADDR
# endif
/* iATU registers */
# define PCIE_ATU_VIEWPORT 0x900
# define PCIE_ATU_REGION_INBOUND (0x1 << 31)
@ -41,6 +45,7 @@
# define PCIE_ATU_CR2 0x908
# define PCIE_ATU_ENABLE (0x1 << 31)
# define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
# define PCIE_ATU_BAR_NUM(bar) ((bar) << 8)
# define PCIE_ATU_LOWER_BASE 0x90C
# define PCIE_ATU_UPPER_BASE 0x910
# define PCIE_ATU_LIMIT 0x914
@ -52,6 +57,7 @@
/* LUT registers */
# define PCIE_LUT_BASE 0x80000
# define PCIE_LUT_LCTRL0 0x7F8
# define PCIE_LUT_DBG 0x7FC
# define PCIE_DBI_RO_WR_EN 0x8bc
@ -65,6 +71,25 @@
# define PCIE_DBI_SIZE 0x100000 /* 1M */
# define PCIE_LCTRL0_CFG2_ENABLE (1 << 31)
# define PCIE_LCTRL0_VF(vf) ((vf) << 22)
# define PCIE_LCTRL0_PF(pf) ((pf) << 16)
# define PCIE_LCTRL0_VF_ACTIVE (1 << 21)
# define PCIE_LCTRL0_VAL(pf, vf) (PCIE_LCTRL0_PF(pf) | \
PCIE_LCTRL0_VF ( vf ) | \
( ( vf ) = = 0 ? 0 : PCIE_LCTRL0_VF_ACTIVE ) | \
PCIE_LCTRL0_CFG2_ENABLE )
# define PCIE_NO_SRIOV_BAR_BASE 0x1000
# define PCIE_PF_NUM 2
# define PCIE_VF_NUM 64
# define PCIE_BAR0_SIZE (4 * 1024) /* 4K */
# define PCIE_BAR1_SIZE (8 * 1024) /* 8K for MSIX */
# define PCIE_BAR2_SIZE (4 * 1024) /* 4K */
# define PCIE_BAR4_SIZE (1 * 1024 * 1024) /* 1M */
struct ls_pcie {
int idx ;
void __iomem * dbi ;
@ -76,6 +101,7 @@ struct ls_pcie {
struct ls_pcie_info {
unsigned long regs ;
int pci_num ;
u64 phys_base ;
u64 cfg0_phys ;
u64 cfg0_size ;
u64 cfg1_phys ;
@ -91,6 +117,7 @@ struct ls_pcie_info {
# define SET_LS_PCIE_INFO(x, num) \
{ \
x . regs = CONFIG_SYS_PCIE # # num # # _ADDR ; \
x . phys_base = CONFIG_SYS_PCIE # # num # # _PHYS_ADDR ; \
x . cfg0_phys = CONFIG_SYS_PCIE_CFG0_PHYS_OFF + \
CONFIG_SYS_PCIE # # num # # _PHYS_ADDR ; \
x . cfg0_size = CONFIG_SYS_PCIE_CFG0_SIZE ; \
@ -197,6 +224,18 @@ static void ls_pcie_iatu_outbound_set(struct ls_pcie *pcie, int idx, int type,
writel ( PCIE_ATU_ENABLE , pcie - > dbi + PCIE_ATU_CR2 ) ;
}
/* Use bar match mode and MEM type as default */
static void ls_pcie_iatu_inbound_set ( struct ls_pcie * pcie , int idx ,
int bar , u64 phys )
{
writel ( PCIE_ATU_REGION_INBOUND | idx , pcie - > dbi + PCIE_ATU_VIEWPORT ) ;
writel ( ( u32 ) phys , pcie - > dbi + PCIE_ATU_LOWER_TARGET ) ;
writel ( phys > > 32 , pcie - > dbi + PCIE_ATU_UPPER_TARGET ) ;
writel ( PCIE_ATU_TYPE_MEM , pcie - > dbi + PCIE_ATU_CR1 ) ;
writel ( PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE |
PCIE_ATU_BAR_NUM ( bar ) , pcie - > dbi + PCIE_ATU_CR2 ) ;
}
static void ls_pcie_setup_atu ( struct ls_pcie * pcie , struct ls_pcie_info * info )
{
# ifdef DEBUG
@ -350,6 +389,97 @@ static void ls_pcie_setup_ctrl(struct ls_pcie *pcie,
# endif
}
static void ls_pcie_ep_setup_atu ( struct ls_pcie * pcie ,
struct ls_pcie_info * info )
{
u64 phys = CONFIG_SYS_PCI_EP_MEMORY_BASE ;
/* ATU 0 : INBOUND : map BAR0 */
ls_pcie_iatu_inbound_set ( pcie , PCIE_ATU_REGION_INDEX0 , 0 , phys ) ;
/* ATU 1 : INBOUND : map BAR1 */
phys + = PCIE_BAR1_SIZE ;
ls_pcie_iatu_inbound_set ( pcie , PCIE_ATU_REGION_INDEX1 , 1 , phys ) ;
/* ATU 2 : INBOUND : map BAR2 */
phys + = PCIE_BAR2_SIZE ;
ls_pcie_iatu_inbound_set ( pcie , PCIE_ATU_REGION_INDEX2 , 2 , phys ) ;
/* ATU 3 : INBOUND : map BAR4 */
phys = CONFIG_SYS_PCI_EP_MEMORY_BASE + PCIE_BAR4_SIZE ;
ls_pcie_iatu_inbound_set ( pcie , PCIE_ATU_REGION_INDEX3 , 4 , phys ) ;
/* ATU 0 : OUTBOUND : map 4G MEM */
ls_pcie_iatu_outbound_set ( pcie , PCIE_ATU_REGION_INDEX0 ,
PCIE_ATU_TYPE_MEM ,
info - > phys_base ,
0 ,
4 * 1024 * 1024 * 1024ULL ) ;
}
/* BAR0 and BAR1 are 32bit BAR2 and BAR4 are 64bit */
static void ls_pcie_ep_setup_bar ( void * bar_base , int bar , u32 size )
{
if ( size < 4 * 1024 )
return ;
switch ( bar ) {
case 0 :
writel ( size - 1 , bar_base + PCI_BASE_ADDRESS_0 ) ;
break ;
case 1 :
writel ( size - 1 , bar_base + PCI_BASE_ADDRESS_1 ) ;
break ;
case 2 :
writel ( size - 1 , bar_base + PCI_BASE_ADDRESS_2 ) ;
writel ( 0 , bar_base + PCI_BASE_ADDRESS_3 ) ;
break ;
case 4 :
writel ( size - 1 , bar_base + PCI_BASE_ADDRESS_4 ) ;
writel ( 0 , bar_base + PCI_BASE_ADDRESS_5 ) ;
break ;
default :
break ;
}
}
static void ls_pcie_ep_setup_bars ( void * bar_base )
{
/* BAR0 - 32bit - 4K configuration */
ls_pcie_ep_setup_bar ( bar_base , 0 , PCIE_BAR0_SIZE ) ;
/* BAR1 - 32bit - 8K MSIX*/
ls_pcie_ep_setup_bar ( bar_base , 1 , PCIE_BAR1_SIZE ) ;
/* BAR2 - 64bit - 4K MEM desciptor */
ls_pcie_ep_setup_bar ( bar_base , 2 , PCIE_BAR2_SIZE ) ;
/* BAR4 - 64bit - 1M MEM*/
ls_pcie_ep_setup_bar ( bar_base , 4 , PCIE_BAR4_SIZE ) ;
}
static void ls_pcie_setup_ep ( struct ls_pcie * pcie , struct ls_pcie_info * info )
{
struct pci_controller * hose = & pcie - > hose ;
pci_dev_t dev = PCI_BDF ( hose - > first_busno , 0 , 0 ) ;
int sriov ;
sriov = pci_hose_find_ext_capability ( hose , dev , PCI_EXT_CAP_ID_SRIOV ) ;
if ( sriov ) {
int pf , vf ;
for ( pf = 0 ; pf < PCIE_PF_NUM ; pf + + ) {
for ( vf = 0 ; vf < = PCIE_VF_NUM ; vf + + ) {
writel ( PCIE_LCTRL0_VAL ( pf , vf ) ,
pcie - > dbi + PCIE_LUT_BASE +
PCIE_LUT_LCTRL0 ) ;
ls_pcie_ep_setup_bars ( pcie - > dbi ) ;
ls_pcie_ep_setup_atu ( pcie , info ) ;
}
}
/* Disable CFG2 */
writel ( 0 , pcie - > dbi + PCIE_LUT_BASE + PCIE_LUT_LCTRL0 ) ;
} else {
ls_pcie_ep_setup_bars ( pcie - > dbi + PCIE_NO_SRIOV_BAR_BASE ) ;
ls_pcie_ep_setup_atu ( pcie , info ) ;
}
}
int ls_pcie_init_ctrl ( int busno , enum srds_prtcl dev , struct ls_pcie_info * info )
{
struct ls_pcie * pcie ;
@ -426,6 +556,11 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info)
printf ( " PCIe%u: %s " , info - > pci_num ,
ep_mode ? " Endpoint " : " Root Complex " ) ;
if ( ep_mode )
ls_pcie_setup_ep ( pcie , info ) ;
else
ls_pcie_setup_ctrl ( pcie , info ) ;
linkup = ls_pcie_link_up ( pcie ) ;
if ( ! linkup ) {
@ -443,8 +578,6 @@ int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info)
if ( ep_mode )
return busno ;
ls_pcie_setup_ctrl ( pcie , info ) ;
pci_register_hose ( hose ) ;
hose - > last_busno = pci_hose_scan ( hose ) ;