diff --git a/src/soc/mediatek/common/pcie.c b/src/soc/mediatek/common/pcie.c index c46b53f516..3a75f6bbbc 100644 --- a/src/soc/mediatek/common/pcie.c +++ b/src/soc/mediatek/common/pcie.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -214,6 +215,7 @@ void mtk_pcie_domain_enable(struct device *dev) const mtk_soc_config_t *config = config_of(dev); const struct mtk_pcie_config *conf = &config->pcie_config; const char *ltssm_state; + uint64_t perst_time_us; size_t tries = 0; uint32_t val; @@ -233,6 +235,32 @@ void mtk_pcie_domain_enable(struct device *dev) val &= ~PCIE_INTX_ENABLE; write32p(conf->base + PCIE_INT_ENABLE_REG, val); + perst_time_us = early_init_get_elapsed_time_us(EARLY_INIT_PCIE); + printk(BIOS_DEBUG, "%s: %lld us elapsed since assert PERST#\n", + __func__, perst_time_us); + + /* + * Described in PCIe CEM specification sections 2.2 + * (PERST# Signal) and 2.2.1 (Initial Power-Up (G3 to S0)). + * The deassertion of PERST# should be delayed 100ms (TPVPERL) + * for the power and clock to become stable. + */ + const uint64_t min_perst_time_us = 100000; /* 100 ms */ + if (perst_time_us < min_perst_time_us) { + if (!perst_time_us) { + printk(BIOS_WARNING, + "%s: PCIe early init data not found, sleeping 100ms\n", + __func__); + mtk_pcie_reset(conf->base + PCIE_RST_CTRL_REG, true); + } else { + printk(BIOS_WARNING, + "%s: Need an extra %lld us delay to meet PERST# deassertion requirement\n", + __func__, min_perst_time_us - perst_time_us); + } + + udelay(min_perst_time_us - perst_time_us); + } + /* De-assert reset signals */ mtk_pcie_reset(conf->base + PCIE_RST_CTRL_REG, false); diff --git a/src/soc/mediatek/mt8195/pcie.c b/src/soc/mediatek/mt8195/pcie.c index 1a17c6c459..df347c0768 100644 --- a/src/soc/mediatek/mt8195/pcie.c +++ b/src/soc/mediatek/mt8195/pcie.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -72,4 +73,6 @@ void mtk_pcie_pre_init(void) /* Assert all reset signals at early stage */ mtk_pcie_reset(PCIE_RST_CTRL_REG, true); + + early_init_save_time(EARLY_INIT_PCIE); }