diff options
author | Yidi Lin <yidilin@chromium.org> | 2024-08-27 16:46:34 +0800 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2024-09-02 09:16:34 +0000 |
commit | cea84e2536976581223e83fead847582694fe471 (patch) | |
tree | d3a8882b757e86441f46c1287861afea462f0f83 /src | |
parent | 5665bcac4f3f2d101537f751fd3d2baa66afaafc (diff) |
soc/mediatek: Add mtk_pcie_deassert_perst for early PCIe reset
Even we assert PRSET# early to save the delay between PERST# assertion
and de-assertion. MediaTek PCIe driver still takes 47ms waiting for PCIe
link up. (1ms delay for each try)
```
[INFO ] mtk_pcie_domain_enable: PCIe link up success (47 tries)
```
Refactor common/pcie.c and add mtk_pcie_deassert_perst for early PCIe
reset. So we can de-assert PERST# at early stage to improve the boot
time.
BUG=b:361728592
TEST=emerge-cherry coreboot
Change-Id: I008e95263bfaf0119353382c2d2ce5ce29c6a382
Signed-off-by: Yidi Lin <yidilin@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/84117
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Jianjun Wang <jianjun.wang@mediatek.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/soc/mediatek/common/include/soc/pcie_common.h | 1 | ||||
-rw-r--r-- | src/soc/mediatek/common/pcie.c | 71 |
2 files changed, 54 insertions, 18 deletions
diff --git a/src/soc/mediatek/common/include/soc/pcie_common.h b/src/soc/mediatek/common/include/soc/pcie_common.h index c34bc4ee69..cfefae2c17 100644 --- a/src/soc/mediatek/common/include/soc/pcie_common.h +++ b/src/soc/mediatek/common/include/soc/pcie_common.h @@ -23,5 +23,6 @@ void mtk_pcie_domain_read_resources(struct device *dev); void mtk_pcie_domain_set_resources(struct device *dev); void mtk_pcie_domain_enable(struct device *dev); void mtk_pcie_reset(uintptr_t base_reg, bool enable); +void mtk_pcie_deassert_perst(void); #endif diff --git a/src/soc/mediatek/common/pcie.c b/src/soc/mediatek/common/pcie.c index e796dc1ece..9269fbd7d3 100644 --- a/src/soc/mediatek/common/pcie.c +++ b/src/soc/mediatek/common/pcie.c @@ -266,24 +266,9 @@ enum cb_err fill_lb_pcie(struct lb_pcie *pcie) return CB_SUCCESS; } -void mtk_pcie_domain_enable(struct device *dev) +static void wait_perst_asserted(uintptr_t base) { - const mtk_soc_config_t *config = config_of(dev); - const struct mtk_pcie_config *conf = &config->pcie_config; - const char *ltssm_state; long perst_time_us; - size_t tries = 0; - uint32_t val; - - /* Set as RC mode */ - setbits32p(conf->base + PCIE_SETTING_REG, PCIE_RC_MODE); - - /* Set class code */ - clrsetbits32p(conf->base + PCIE_PCI_IDS_1, GENMASK(31, 8), - PCI_CLASS(PCI_CLASS_BRIDGE_PCI << 8)); - - /* Mask all INTx interrupts */ - clrbits32p(conf->base + PCIE_INT_ENABLE_REG, PCIE_INTX_ENABLE); perst_time_us = early_init_get_elapsed_time_us(EARLY_INIT_PCIE); printk(BIOS_DEBUG, "%s: %ld us elapsed since assert PERST#\n", @@ -301,7 +286,7 @@ void mtk_pcie_domain_enable(struct device *dev) printk(BIOS_WARNING, "%s: PCIe early init data not found, sleeping 100ms\n", __func__); - mtk_pcie_reset(conf->base, true); + mtk_pcie_reset(base, true); } else { printk(BIOS_WARNING, "%s: Need an extra %ld us delay to meet PERST# deassertion requirement\n", @@ -310,9 +295,59 @@ void mtk_pcie_domain_enable(struct device *dev) udelay(min_perst_time_us - perst_time_us); } +} + +static void deassert_perst(uintptr_t base) +{ + /* Set as RC mode */ + setbits32p(base + PCIE_SETTING_REG, PCIE_RC_MODE); + /* Set class code */ + clrsetbits32p(base + PCIE_PCI_IDS_1, GENMASK(31, 8), + PCI_CLASS(PCI_CLASS_BRIDGE_PCI << 8)); + + /* Mask all INTx interrupts */ + clrbits32p(base + PCIE_INT_ENABLE_REG, PCIE_INTX_ENABLE); + + /* Above registers must be set before de-asserting PERST# */ /* De-assert reset signals */ - mtk_pcie_reset(conf->base, false); + mtk_pcie_reset(base, false); +} + +static void wait_perst_done(uintptr_t base) +{ + long perst_time_us; + + wait_perst_asserted(base); + + perst_time_us = early_init_get_elapsed_time_us(EARLY_INIT_PCIE_RESET); + printk(BIOS_DEBUG, "%s: %ld us elapsed since de-assert PERST#\n", + __func__, perst_time_us); + + if (!perst_time_us) { + printk(BIOS_INFO, "%s: PCIe early PERST# de-assertion is not done, " + "de-assert PERST# now\n", __func__); + deassert_perst(base); + } +} + +void mtk_pcie_deassert_perst(void) +{ + uintptr_t base = mtk_pcie_get_controller_base(0); + + wait_perst_done(base); + early_init_save_time(EARLY_INIT_PCIE_RESET); +} + +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; + size_t tries = 0; + uint32_t val; + + wait_perst_done(conf->base); if (!retry(100, (tries++, read32p(conf->base + PCIE_LINK_STATUS_REG) & |