summaryrefslogtreecommitdiff
path: root/src/soc/mediatek
diff options
context:
space:
mode:
authorJianjun Wang <jianjun.wang@mediatek.com>2024-04-17 10:38:53 +0800
committerYu-Ping Wu <yupingso@google.com>2024-10-28 03:35:46 +0000
commit97be4e7209bfdaa6c49a21c63f4cb0a18f77bce2 (patch)
tree700c79c22e20ac0cc098548a4e18b4e338a7d481 /src/soc/mediatek
parent186916ca1e02d77b623a75a21ccb5831c59cf4ba (diff)
soc/mediatek/mt8196: Add PCIe driver and early init support
Add PCIe driver for MT8196 platform. According to the PCIe CEM specification, the deassertion of PERST# should occur at least 100ms after the assertion. To ensure the 100ms delay requirement is met and to save delay time in the ramstage, add an early init data region to store the elapsed time since assertion. This will speed up the boot time by 100ms. PCIe port 1 and port 2 share the same PCIe resources, but PCIe port 2 is not used. Therefore, in mtk_pcie_pre_init(), make sure PCIe port 2 is reset to prevent interference with PCIe port 1. TEST=Build pass, show pcie init pass log: mtk_pcie_domain_enable: PCIe link up success (1) BUG=b:317009620 Signed-off-by: Jianjun Wang <jianjun.wang@mediatek.com> Change-Id: I826a96822e88972bcd4966b6681797a646adf3d6 Reviewed-on: https://review.coreboot.org/c/coreboot/+/84696 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Yu-Ping Wu <yupingso@google.com> Reviewed-by: Yidi Lin <yidilin@google.com>
Diffstat (limited to 'src/soc/mediatek')
-rw-r--r--src/soc/mediatek/mt8196/Makefile.mk4
-rw-r--r--src/soc/mediatek/mt8196/bootblock.c2
-rw-r--r--src/soc/mediatek/mt8196/chip.h14
-rw-r--r--src/soc/mediatek/mt8196/include/soc/memlayout.ld3
-rw-r--r--src/soc/mediatek/mt8196/include/soc/soc_chip.h8
-rw-r--r--src/soc/mediatek/mt8196/pcie.c57
6 files changed, 87 insertions, 1 deletions
diff --git a/src/soc/mediatek/mt8196/Makefile.mk b/src/soc/mediatek/mt8196/Makefile.mk
index 388dad14c4..df72ba65b9 100644
--- a/src/soc/mediatek/mt8196/Makefile.mk
+++ b/src/soc/mediatek/mt8196/Makefile.mk
@@ -10,7 +10,9 @@ all-y += timer.c timer_prepare.c
all-y += ../common/uart.c
bootblock-y += bootblock.c
+bootblock-y += ../common/early_init.c
bootblock-y += ../common/mmu_operations.c
+bootblock-$(CONFIG_PCI) += ../common/pcie.c pcie.c
bootblock-y += ../common/wdt.c ../common/wdt_req.c wdt.c
romstage-y += ../common/cbmem.c
@@ -18,9 +20,11 @@ romstage-y += emi.c
romstage-y += l2c_ops.c
romstage-y += ../common/mmu_operations.c ../common/mmu_cmops.c
+ramstage-y += ../common/early_init.c
ramstage-y += emi.c
ramstage-y += l2c_ops.c
ramstage-y += ../common/mmu_operations.c ../common/mmu_cmops.c
+ramstage-$(CONFIG_PCI) += ../common/pcie.c pcie.c
ramstage-y += soc.c
ramstage-y += ../common/usb.c usb.c
diff --git a/src/soc/mediatek/mt8196/bootblock.c b/src/soc/mediatek/mt8196/bootblock.c
index 770c6031da..1b1f09f07c 100644
--- a/src/soc/mediatek/mt8196/bootblock.c
+++ b/src/soc/mediatek/mt8196/bootblock.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <bootblock_common.h>
+#include <soc/early_init.h>
#include <soc/mmu_operations.h>
#include <soc/wdt.h>
@@ -8,4 +9,5 @@ void bootblock_soc_init(void)
{
mtk_mmu_init();
mtk_wdt_init();
+ early_init_clear();
}
diff --git a/src/soc/mediatek/mt8196/chip.h b/src/soc/mediatek/mt8196/chip.h
new file mode 100644
index 0000000000..4c3dea0a0c
--- /dev/null
+++ b/src/soc/mediatek/mt8196/chip.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+
+#ifndef SOC_MEDIATEK_CHIP_H
+#define SOC_MEDIATEK_CHIP_H
+
+#include <soc/pcie_common.h>
+
+struct soc_mediatek_mt8196_config {
+ struct mtk_pcie_config pcie_config;
+};
+
+typedef struct soc_mediatek_mt8196_config mtk_soc_config_t;
+
+#endif /* SOC_MEDIATEK_CHIP_H */
diff --git a/src/soc/mediatek/mt8196/include/soc/memlayout.ld b/src/soc/mediatek/mt8196/include/soc/memlayout.ld
index 664e55b051..3fdfebdd9d 100644
--- a/src/soc/mediatek/mt8196/include/soc/memlayout.ld
+++ b/src/soc/mediatek/mt8196/include/soc/memlayout.ld
@@ -11,7 +11,8 @@ SECTIONS
DMA_COHERENT(0x00107000, 4K)
STACK(0x00108000, 15K)
WATCHDOG_TOMBSTONE(0x0010bc00, 4)
- /* EMPTY(0x0010bc04, 29K - 4) */
+ EARLY_INIT(0x0010bc10, 128)
+ /* EMPTY(0x0010bc90, 29K - 144) */
/*
* MCUPM exchanges data with kernel driver using SRAM 0x00113000 ~
* 0x0011ffff. The address is hardcoded in MCUPM image.
diff --git a/src/soc/mediatek/mt8196/include/soc/soc_chip.h b/src/soc/mediatek/mt8196/include/soc/soc_chip.h
new file mode 100644
index 0000000000..d030628e32
--- /dev/null
+++ b/src/soc/mediatek/mt8196/include/soc/soc_chip.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+
+#ifndef SOC_MEDIATEK_SOC_CHIP_H
+#define SOC_MEDIATEK_SOC_CHIP_H
+
+#include "../../chip.h"
+
+#endif /* SOC_MEDIATEK_SOC_CHIP_H */
diff --git a/src/soc/mediatek/mt8196/pcie.c b/src/soc/mediatek/mt8196/pcie.c
new file mode 100644
index 0000000000..d307861d96
--- /dev/null
+++ b/src/soc/mediatek/mt8196/pcie.c
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+
+#include <device/mmio.h>
+#include <gpio.h>
+#include <soc/early_init.h>
+#include <soc/pcie.h>
+
+#define PCIE_REG_BASE_PORT0 0x16940000
+#define PCIE_RST_CTRL_REG (PCIE_REG_BASE_PORT0 + 0x148)
+
+#define PEXTP_CFG_BASE 0x169e0000
+#define PEXTP_SW_RST_REG (PEXTP_CFG_BASE + 0x4)
+#define PEXTP_SW_RST_MAC_P2 BIT(8)
+#define PEXTP_SW_RST_PHY_P2 BIT(9)
+#define PEXTP_REQ_CTRL_0_REG (PEXTP_CFG_BASE + 0x7c)
+#define PEXTP_PCIE26M_BYPASS BIT(4)
+
+static const struct pad_func pcie_pins[2][3] = {
+ {
+ PAD_FUNC_UP(PCIE0_PERSTN, PCIE_PERSTN),
+ PAD_FUNC_UP(PCIE0_WAKEN, PCIE_WAKEN),
+ PAD_FUNC_UP(PCIE0_CLKREQN, PCIE_CLKREQN),
+ },
+ {
+ PAD_FUNC_UP(BPI_D_BUS0, PCIE_WAKEN_1P),
+ PAD_FUNC_UP(BPI_D_BUS1, PCIE_PERSTN_1P),
+ PAD_FUNC_UP(BPI_D_BUS2, PCIE_CLKREQN_1P),
+ },
+};
+
+static void mtk_pcie_set_pinmux(uint8_t port)
+{
+ const struct pad_func *pins = pcie_pins[port];
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(pcie_pins[port]); i++) {
+ gpio_set_mode(pins[i].gpio, pins[i].func);
+ gpio_set_pull(pins[i].gpio, GPIO_PULL_ENABLE, GPIO_PULL_UP);
+ }
+}
+
+void mtk_pcie_pre_init(void)
+{
+ mtk_pcie_set_pinmux(1);
+
+ /* PCIe 2 is not used, assert it's reset for power saving */
+ clrsetbits32p(PEXTP_SW_RST_REG, GENMASK(9, 8),
+ PEXTP_SW_RST_MAC_P2 | PEXTP_SW_RST_PHY_P2);
+
+ /* PCIe 1 and 2 need to bypass PMRC signal */
+ setbits32p(PEXTP_REQ_CTRL_0_REG, PEXTP_PCIE26M_BYPASS);
+
+ /* Assert all reset signals at early stage */
+ mtk_pcie_reset(PCIE_REG_BASE_PORT0, true);
+
+ early_init_save_time(EARLY_INIT_PCIE);
+}