aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManoj Kumar <manoj.kumar3@arm.com>2019-01-18 11:11:50 +0530
committerronald-cron-arm <39518861+ronald-cron-arm@users.noreply.github.com>2019-02-18 17:31:23 +0100
commit6fdc649acef185f5ade4b29afda8f1af8d111611 (patch)
tree48d11e2edd07bd57a722bd5f43e5368b5aedefe8
parentd8f60de2e348c56893762a01549fdbfeb6d66fa2 (diff)
n1sdp: add fixes for pcie driver
This patch fixes: - Type 0 & 1 configuration for both PCIe & CCIX RCs - Enable Type 1 MEM & IO bars in root ports - Log negotiated speed and lane count Change-Id: Id3a9996ff79e9db30aac19756df7df48a2273478 Signed-off-by: Manoj Kumar <manoj.kumar3@arm.com>
-rw-r--r--product/n1sdp/module/n1sdp_pcie/src/mod_n1sdp_pcie.c57
-rw-r--r--product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.c20
-rw-r--r--product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.h38
3 files changed, 103 insertions, 12 deletions
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 5d85548d..698c3fd1 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 <fwk_assert.h>
#include <fwk_errno.h>
#include <fwk_id.h>
+#include <fwk_math.h>
#include <fwk_mm.h>
#include <fwk_module.h>
#include <fwk_module_idx.h>
@@ -92,14 +93,39 @@ 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);
}
@@ -138,10 +164,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 +196,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 +282,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 15f0806d..e3594296 100644
--- a/product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.c
+++ b/product/n1sdp/module/n1sdp_pcie/src/n1sdp_pcie.c
@@ -14,16 +14,22 @@
#include <mod_n1sdp_pcie.h>
#include <mod_timer.h>
#include <n1sdp_pcie.h>
+#include <n1sdp_scp_pik.h>
-static bool wait_condition(void *data)
+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 +52,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 +64,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 +75,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 +91,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 2d6ad80d..37c2cfed 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;
};
@@ -387,6 +407,16 @@ int axi_inbound_region_setup(uint32_t axi_config_base_addr,
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.
*
* param - ctrl_apb - Pointer to APB controller register space