diff --git a/product/n1sdp/include/n1sdp_scc_reg.h b/product/n1sdp/include/n1sdp_scc_reg.h index 1d7420555dfc155d1c34f3aed486610785d8753a..58b3c5e711620fb4fcbcd47c9f41526d3baf3442 100644 --- a/product/n1sdp/include/n1sdp_scc_reg.h +++ b/product/n1sdp/include/n1sdp_scc_reg.h @@ -208,6 +208,9 @@ struct scc_reg { #define SCC_CCIX_PM_CTRL_PWR_REQ_POS UINT32_C(1) #define SCC_PCIE_PM_CTRL_PWR_REQ_POS UINT32_C(1) +#define SCC_CCIX_PM_CTRL_PWR_ACK_MASK UINT32_C(0x2) +#define SCC_PCIE_PM_CTRL_PWR_ACK_MASK UINT32_C(0x2) + #define SCC_SYS_MAN_RESET_CCIX_POS UINT32_C(11) #define SCC_SYS_MAN_RESET_PCIE_POS UINT32_C(10) diff --git a/product/n1sdp/include/n1sdp_scp_mmap.h b/product/n1sdp/include/n1sdp_scp_mmap.h index 94ce3dcbd45091e1ce229e6517cc2e8f582d1304..3e8e9f62828de33828cf26936c037e5cff20cad1 100644 --- a/product/n1sdp/include/n1sdp_scp_mmap.h +++ b/product/n1sdp/include/n1sdp_scp_mmap.h @@ -186,8 +186,8 @@ /* * DDR PHY base address */ -#define SCP_DDR_PHY0 (SCP_SYS0_BASE + 0x3FB60000) -#define SCP_DDR_PHY1 (SCP_SYS0_BASE + 0x3FB70000) +#define SCP_DDR_PHY0 (0x50604000) +#define SCP_DDR_PHY1 (0x50614000) /* * DMC-620 controller base address diff --git a/product/n1sdp/module/n1sdp_pcie/src/mod_n1sdp_pcie.c b/product/n1sdp/module/n1sdp_pcie/src/mod_n1sdp_pcie.c index 5d85548d3713e034a03735265be0ecbc02f015d3..6a3d6b347386f650e9986a054ee4570834a07792 100644 --- a/product/n1sdp/module/n1sdp_pcie/src/mod_n1sdp_pcie.c +++ b/product/n1sdp/module/n1sdp_pcie/src/mod_n1sdp_pcie.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -92,19 +93,45 @@ struct n1sdp_pcie_ctx pcie_ctx; static int n1sdp_pcie_setup(struct n1sdp_pcie_dev_ctx *dev_ctx) { uint32_t ecam_base_addr; + uint8_t neg_config; + struct pcie_wait_condition_data wait_data; int status; /* Enable the CCIX/PCIe controller */ + wait_data.ctrl_apb = NULL; if (dev_ctx->config->ccix_capable) { SCC->CCIX_PM_CTRL = SCC_CCIX_PM_CTRL_PWR_REQ_POS; + wait_data.stage = PCIE_INIT_STAGE_CCIX_POWER_ON; + status = pcie_ctx.timer_api->wait(FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, + 0), + PCIE_POWER_ON_TIMEOUT, + pcie_wait_condition, + &wait_data); + if (status != FWK_SUCCESS) { + pcie_ctx.log_api->log(MOD_LOG_GROUP_INFO, + "[PCIe] Controller power-on failed!\n"); + return status; + } SCC->SYS_MAN_RESET &= ~(1 << SCC_SYS_MAN_RESET_CCIX_POS); } else { SCC->PCIE_PM_CTRL = SCC_PCIE_PM_CTRL_PWR_REQ_POS; + wait_data.stage = PCIE_INIT_STAGE_PCIE_POWER_ON; + status = pcie_ctx.timer_api->wait(FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, + 0), + PCIE_POWER_ON_TIMEOUT, + pcie_wait_condition, + &wait_data); + if (status != FWK_SUCCESS) { + pcie_ctx.log_api->log(MOD_LOG_GROUP_INFO, + "[PCIe] Controller power-on failed!\n"); + return status; + } SCC->SYS_MAN_RESET &= ~(1 << SCC_SYS_MAN_RESET_PCIE_POS); } /* PHY initialization */ pcie_ctx.log_api->log(MOD_LOG_GROUP_INFO, "[PCIe] Initializing PHY..."); + pcie_phy_init(dev_ctx->phy_apb); status = pcie_init(dev_ctx->ctrl_apb, pcie_ctx.timer_api, PCIE_INIT_STAGE_PHY); @@ -138,10 +165,25 @@ static int n1sdp_pcie_setup(struct n1sdp_pcie_dev_ctx *dev_ctx) } pcie_ctx.log_api->log(MOD_LOG_GROUP_INFO, "Done\n"); + neg_config = (dev_ctx->ctrl_apb->RP_CONFIG_OUT & + RP_CONFIG_OUT_NEGOTIATED_SPD_MASK) >> RP_CONFIG_OUT_NEGOTIATED_SPD_POS; + pcie_ctx.log_api->log(MOD_LOG_GROUP_INFO, + "[PCIe] Negotiated speed: GEN%d\n", neg_config + 1); + + neg_config = (dev_ctx->ctrl_apb->RP_CONFIG_OUT & + RP_CONFIG_OUT_NEGOTIATED_LINK_WIDTH_MASK) >> + RP_CONFIG_OUT_NEGOTIATED_LINK_WIDTH_POS; + pcie_ctx.log_api->log(MOD_LOG_GROUP_INFO, + "[PCIe] Negotiated link width: x%d\n", fwk_math_pow2(neg_config)); + /* Root Complex setup */ pcie_ctx.log_api->log(MOD_LOG_GROUP_INFO, "[PCIe] Setup Type0 configuration..."); - ecam_base_addr = dev_ctx->config->axi_slave_base32 + + if (dev_ctx->config->ccix_capable) + ecam_base_addr = dev_ctx->config->axi_slave_base32 + + CCIX_AXI_ECAM_TYPE0_OFFSET; + else + ecam_base_addr = dev_ctx->config->axi_slave_base32 + PCIE_AXI_ECAM_TYPE0_OFFSET; status = axi_outbound_region_setup(dev_ctx->rc_axi_config_apb, (ecam_base_addr - SCP_AP_AXI_OFFSET), @@ -155,7 +197,11 @@ static int n1sdp_pcie_setup(struct n1sdp_pcie_dev_ctx *dev_ctx) pcie_ctx.log_api->log(MOD_LOG_GROUP_INFO, "[PCIe] Setup Type1 configuration..."); - ecam_base_addr = dev_ctx->config->axi_slave_base32 + + if (dev_ctx->config->ccix_capable) + ecam_base_addr = dev_ctx->config->axi_slave_base32 + + CCIX_AXI_ECAM_TYPE1_OFFSET; + else + ecam_base_addr = dev_ctx->config->axi_slave_base32 + PCIE_AXI_ECAM_TYPE1_OFFSET; status = axi_outbound_region_setup(dev_ctx->rc_axi_config_apb, (ecam_base_addr - SCP_AP_AXI_OFFSET), @@ -237,6 +283,14 @@ static int n1sdp_pcie_setup(struct n1sdp_pcie_dev_ctx *dev_ctx) } pcie_ctx.log_api->log(MOD_LOG_GROUP_INFO, "Done\n"); + pcie_ctx.log_api->log(MOD_LOG_GROUP_INFO, + "[PCIe] Enable Type 1 I/O configuration\n"); + *(uint32_t *)(dev_ctx->lm_apb + PCIE_LM_RC_BAR_CONFIG_REG) = + (TYPE1_PREF_MEM_BAR_ENABLE_MASK | + TYPE1_PREF_MEM_BAR_SIZE_64BIT_MASK | + TYPE1_PREF_IO_BAR_ENABLE_MASK | + TYPE1_PREF_IO_BAR_SIZE_32BIT_MASK); + return FWK_SUCCESS; } diff --git a/product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.c b/product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.c index 15f0806dd971a8d74a02a36d07f5e4701c1cfccd..6c9ad8d04eea65a14b447f5c6882e9935d375f44 100644 --- a/product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.c +++ b/product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.c @@ -14,16 +14,72 @@ #include #include #include +#include -static bool wait_condition(void *data) +void pcie_phy_init(uint32_t phy_apb_base) +{ + + uint32_t j; + + for (j = 0; j < 16; j++) + *((unsigned int *)((j << 11) | 0x1000C | phy_apb_base)) = 0x00004900; + + *((unsigned int *)(0x00188 | phy_apb_base)) = 0x00001B26; + for (j = 0; j < 16; j++) { + *((unsigned int *)((j << 11) | 0x00204 | phy_apb_base)) = 0x0000813E; + *((unsigned int *)((j << 11) | 0x00220 | phy_apb_base)) = 0x00000094; + *((unsigned int *)((j << 11) | 0x00244 | phy_apb_base)) = 0x00000314; + } + + for (j = 0; j < 16; j++) + *((unsigned int *)((j << 11) | 0x105a8 | phy_apb_base)) = 0x00002E31; + + *((unsigned int *)(0x30008 | phy_apb_base)) = 0x00004010; + *((unsigned int *)(0x3000c | phy_apb_base)) = 0x00000810; + *((unsigned int *)(0x30010 | phy_apb_base)) = 0x00001101; + *((unsigned int *)(0x30018 | phy_apb_base)) = 0x0000000A; + + for (j = 0; j < 16; j++) { + *((unsigned int *)((j << 11) | 0x10320 | phy_apb_base)) = 0x00000500; + *((unsigned int *)((j << 11) | 0x10328 | phy_apb_base)) = 0x0000A990; + *((unsigned int *)((j << 11) | 0x10540 | phy_apb_base)) = 0x00005008; + *((unsigned int *)((j << 11) | 0x10560 | phy_apb_base)) = 0x00007425; + *((unsigned int *)((j << 11) | 0x10580 | phy_apb_base)) = 0x000000AC; + } + + for (j = 0; j < 16; j++) { + *((unsigned int *)((j << 11) | 0x10110 | phy_apb_base)) = 0x00000000; + *((unsigned int *)((j << 11) | 0x10258 | phy_apb_base)) = 0x00000000; + *((unsigned int *)((j << 11) | 0x10324 | phy_apb_base)) = 0x00005664; + *((unsigned int *)((j << 11) | 0x101c4 | phy_apb_base)) = 0x00000002; + *((unsigned int *)((j << 11) | 0x10320 | phy_apb_base)) = 0x00000100; + *((unsigned int *)((j << 11) | 0x10328 | phy_apb_base)) = 0x00008190; + *((unsigned int *)((j << 11) | 0x10334 | phy_apb_base)) = 0x0000008a; + *((unsigned int *)((j << 11) | 0x1034c | phy_apb_base)) = 0x0000000a; + *((unsigned int *)((j << 11) | 0x1053c | phy_apb_base)) = 0x00005008; + *((unsigned int *)((j << 11) | 0x10540 | phy_apb_base)) = 0x00005008; + *((unsigned int *)((j << 11) | 0x10560 | phy_apb_base)) = 0x00003783; + *((unsigned int *)((j << 11) | 0x1060c | phy_apb_base)) = 0x00001002; + *((unsigned int *)((j << 11) | 0x10610 | phy_apb_base)) = 0x00002004; + *((unsigned int *)((j << 11) | 0x107bc | phy_apb_base)) = 0x00001002; + *((unsigned int *)((j << 11) | 0x107c0 | phy_apb_base)) = 0x00002004; + } +} + +bool pcie_wait_condition(void *data) { assert(data != NULL); - struct wait_condition_data *wait_data = (struct wait_condition_data *)data; + struct pcie_wait_condition_data *wait_data = + (struct pcie_wait_condition_data *)data; struct pcie_ctrl_apb_reg *ctrl_apb = (struct pcie_ctrl_apb_reg *)(wait_data->ctrl_apb); switch (wait_data->stage) { + case PCIE_INIT_STAGE_PCIE_POWER_ON: + return ((SCC->PCIE_PM_CTRL & SCC_PCIE_PM_CTRL_PWR_ACK_MASK) != 0); + case PCIE_INIT_STAGE_CCIX_POWER_ON: + return ((SCC->CCIX_PM_CTRL & SCC_CCIX_PM_CTRL_PWR_ACK_MASK) != 0); case PCIE_INIT_STAGE_PHY: return ((ctrl_apb->RESET_STATUS & RESET_STATUS_PHY_REL_ST_MASK) != 0); @@ -46,7 +102,7 @@ int pcie_init(struct pcie_ctrl_apb_reg *ctrl_apb, assert(timer_api != NULL); assert(stage < PCIE_INIT_STAGE_COUNT); - struct wait_condition_data wait_data; + struct pcie_wait_condition_data wait_data; int status; wait_data.ctrl_apb = ctrl_apb; @@ -58,7 +114,7 @@ int pcie_init(struct pcie_ctrl_apb_reg *ctrl_apb, ctrl_apb->RESET_CTRL = RESET_CTRL_PHY_REL_MASK; status = timer_api->wait(FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0), PCIE_PHY_PLL_LOCK_TIMEOUT, - wait_condition, + pcie_wait_condition, &wait_data); if (status != FWK_SUCCESS) return status; @@ -69,10 +125,12 @@ int pcie_init(struct pcie_ctrl_apb_reg *ctrl_apb, /* Clear ARI & SR_IOV bits */ ctrl_apb->RP_CONFIG_IN &= ~RP_CONFIG_IN_ARI_EN_MASK; ctrl_apb->RP_CONFIG_IN &= ~RP_CONFIG_IN_SR_IOV_EN_MASK; + ctrl_apb->RP_CONFIG_IN = (0x4 << RP_CONFIG_IN_LANE_CNT_IN_POS) | + (0x1 << RP_CONFIG_IN_PCIE_GEN_SEL_POS); ctrl_apb->RESET_CTRL = RESET_CTRL_RC_REL_MASK; status = timer_api->wait(FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0), PCIE_CTRL_RC_RESET_TIMEOUT, - wait_condition, + pcie_wait_condition, &wait_data); if (status != FWK_SUCCESS) return status; @@ -83,7 +141,7 @@ int pcie_init(struct pcie_ctrl_apb_reg *ctrl_apb, ctrl_apb->RP_CONFIG_IN |= RP_CONFIG_IN_LINK_TRNG_EN_MASK; status = timer_api->wait(FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0), PCIE_LINK_TRAINING_TIMEOUT, - wait_condition, + pcie_wait_condition, &wait_data); if (status != FWK_SUCCESS) return status; diff --git a/product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.h b/product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.h index 2d6ad80de925fdb9a6304bf0db99ce932c868794..4616b323e024be7b0fd150cd94d1a2d3d05850d4 100644 --- a/product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.h +++ b/product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.h @@ -66,7 +66,10 @@ */ #define PCIE_PHY_PLL_LOCK_TIMEOUT UINT32_C(100) #define PCIE_CTRL_RC_RESET_TIMEOUT UINT32_C(100) -#define PCIE_LINK_TRAINING_TIMEOUT UINT32_C(20000) +#define PCIE_LINK_TRAINING_TIMEOUT UINT32_C(50000) + +/* PCIe controller power on timeout (in microseconds) */ +#define PCIE_POWER_ON_TIMEOUT UINT32_C(10) /* PCIe configuration space offset definitions */ #define PCIE_CLASS_CODE_OFFSET 0x8 @@ -74,6 +77,17 @@ /* PCIe class code for PCI bridge */ #define PCIE_CLASS_CODE_PCI_BRIDGE UINT32_C(0x06040000) +/* PCIe controller local management (LM) register offsets */ +#define PCIE_LM_RC_BAR_CONFIG_REG UINT32_C(0x300) + +/* PCIe LM root complex bar configuration register bit masks */ +#define TYPE1_PREF_MEM_BAR_ENABLE_MASK (1U << 17) +#define TYPE1_PREF_MEM_BAR_SIZE_32BIT_MASK (0U << 18) +#define TYPE1_PREF_MEM_BAR_SIZE_64BIT_MASK (1U << 18) +#define TYPE1_PREF_IO_BAR_ENABLE_MASK (1U << 19) +#define TYPE1_PREF_IO_BAR_SIZE_32BIT_MASK (0U << 20) +#define TYPE1_PREF_IO_BAR_SIZE_64BIT_MASK (1U << 20) + /* * Root port's config space cannot be written directly with its base address. * Bit 21 has to be set in the base address to enable writing to root port's @@ -90,7 +104,7 @@ /* Maximum bus levels for type 0 and type 1 transactions */ #define MAX_TYPE0_BUS_LEVELS 2 -#define MAX_TYPE1_BUS_LEVELS 8 +#define MAX_TYPE1_BUS_LEVELS 16 /* Maximum AXI space for type 0 and type 1 transactions */ #define AXI_ECAM_TYPE0_SIZE (MAX_TYPE0_BUS_LEVELS * \ @@ -114,7 +128,7 @@ /* * CCIX AXI slave ECAM memory mapping */ -#define CCIX_AXI_ECAM_TYPE0_OFFSET (16 * FWK_MIB) +#define CCIX_AXI_ECAM_TYPE0_OFFSET (32 * FWK_MIB) #define CCIX_AXI_ECAM_TYPE1_OFFSET (CCIX_AXI_ECAM_TYPE0_OFFSET + \ AXI_ECAM_TYPE0_SIZE) @@ -326,6 +340,12 @@ struct axi_ob_config { * Identifiers of PCIe initialization stages */ enum pcie_init_stage { + /* PCIe controller power ON stage */ + PCIE_INIT_STAGE_PCIE_POWER_ON, + + /* CCIX controller power ON stage */ + PCIE_INIT_STAGE_CCIX_POWER_ON, + /* PHY initialization stage */ PCIE_INIT_STAGE_PHY, @@ -342,7 +362,7 @@ enum pcie_init_stage { /* * Structure defining data to be passed to timer API */ -struct wait_condition_data { +struct pcie_wait_condition_data { void *ctrl_apb; enum pcie_init_stage stage; }; @@ -386,6 +406,16 @@ int axi_inbound_region_setup(uint32_t axi_config_base_addr, uint32_t region_size, uint8_t bar); +/* + * Brief - Function to check PCIe status in various initialization stages. + * + * param - data - Pointer to wait condition data + * + * retval - true - if the condition is met + * false - if the condition is not met + */ +bool pcie_wait_condition(void *data); + /* * Brief - Function to initialize different stages of PCIe module. * @@ -400,6 +430,13 @@ int pcie_init(struct pcie_ctrl_apb_reg *ctrl_apb, struct mod_timer_api *timer_api, enum pcie_init_stage stage); +/* + * Brief - Function to initialize PCIe PHY layer. + * + * param - pcie_phy_base - Base address of the PHY layer registers + */ +void pcie_phy_init(uint32_t phy_apb_base); + /* * Brief - Function to write to Root Port's/End Point's configuration space. *