a gentle ping...any comments? regards Frank
> Gesendet: Freitag, 12. April 2024 um 16:10 Uhr > Von: "Frank Wunderlich" <li...@fw-web.de> > An: "Tom Rini" <tr...@konsulko.com>, "Lukasz Majewski" <lu...@denx.de>, "Sean > Anderson" <sean...@gmail.com>, "Ryder Lee" <ryder....@mediatek.com>, "Weijie > Gao" <weijie....@mediatek.com>, "Chunfeng Yun" <chunfeng....@mediatek.com>, > "GSS_MTK_Uboot_upstream" <gss_mtk_uboot_upstr...@mediatek.com>, "John > Crispin" <j...@phrozen.org> > Cc: "Frank Wunderlich" <fran...@public-files.de>, u-boot@lists.denx.de > Betreff: [RFC] pci: mediatek: add PCIe controller support for Filogic > > From: John Crispin <j...@phrozen.org> > > This adds PCIe controller support for the MediaTek Filogic family.. > > Signed-off-by: John Crispin <j...@phrozen.org> > Signed-off-by: Frank Wunderlich <fran...@public-files.de> > --- > Note for mt7988: pcie2 needs a dedicated phy which has no driver > in uboot yet, so this pcie port is not enabled in the board device- > trees. > > Note for mt7981: i have no board and have no dts nodes yet for it, > so only clock change first. > --- > arch/arm/dts/mt7986.dtsi | 46 +++ > arch/arm/dts/mt7988-rfb.dts | 12 + > arch/arm/dts/mt7988-sd-rfb.dts | 12 + > arch/arm/dts/mt7988.dtsi | 164 +++++++++++ > drivers/clk/mediatek/clk-mt7986.c | 5 +- > drivers/pci/Kconfig | 7 + > drivers/pci/Makefile | 1 + > drivers/pci/pcie_mediatek_gen3.c | 382 +++++++++++++++++++++++++ > include/dt-bindings/clock/mt7981-clk.h | 3 +- > include/dt-bindings/clock/mt7986-clk.h | 3 +- > 10 files changed, 631 insertions(+), 4 deletions(-) > create mode 100644 drivers/pci/pcie_mediatek_gen3.c > > diff --git a/arch/arm/dts/mt7986.dtsi b/arch/arm/dts/mt7986.dtsi > index c9aeeaca2b11..9a9b0b64cc68 100644 > --- a/arch/arm/dts/mt7986.dtsi > +++ b/arch/arm/dts/mt7986.dtsi > @@ -375,5 +375,51 @@ > #phy-cells = <1>; > status = "okay"; > }; > + > + pcie_port: pcie-phy@11c00000 { > + reg = <0x11c00000 0x20000>; > + clocks = <&dummy_clk>; > + clock-names = "ref"; > + #phy-cells = <1>; > + status = "okay"; > + }; > + }; > + > + pcie: pcie@11280000 { > + compatible = "mediatek,mt7986-pcie", > + "mediatek,mt8192-pcie"; > + device_type = "pci"; > + reg = <0x11280000 0x4000>; > + reg-names = "pcie-mac"; > + #address-cells = <3>; > + #size-cells = <2>; > + > + clocks = <&infracfg_ao CK_INFRA_IPCIE_PIPE_CK>, > + <&infracfg_ao CK_INFRA_IPCIE_CK>, > + <&infracfg_ao CK_INFRA_IPCIER_CK>, > + <&infracfg_ao CK_INFRA_IPCIEB_CK>; > + clock-names = "pl_250m", "tl_26m", "peri_26m", "top_133m"; > + > + bus-range = <0x00 0xff>; > + ranges = <0x82000000 0 0x20000000 0x20000000 0 0x10000000>; > + > + interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; > + #interrupt-cells = <2>; > + interrupt-map-mask = <0 0 0 7>; > + interrupt-map = <0 0 0 1 &pcie_intc 0>, /* INTA */ > + <0 0 0 2 &pcie_intc 1>, /* INTB */ > + <0 0 0 3 &pcie_intc 2>, /* INTC */ > + <0 0 0 4 &pcie_intc 3>; /* INTD */ > + > + phy-names = "pcie-phy"; > + phys = <&pcie_port PHY_TYPE_PCIE>; > + > + status = "okay"; > + > + pcie_intc: legacy-interrupt-controller { > + interrupt-controller; > + #address-cells = <0>; > + #interrupt-cells = <1>; > + }; > }; > }; > diff --git a/arch/arm/dts/mt7988-rfb.dts b/arch/arm/dts/mt7988-rfb.dts > index 2c1142843091..2f0d00b6950b 100644 > --- a/arch/arm/dts/mt7988-rfb.dts > +++ b/arch/arm/dts/mt7988-rfb.dts > @@ -180,3 +180,15 @@ > non-removable; > status = "okay"; > }; > + > +&pcie0 { > + status = "okay"; > +}; > + > +&pcie1 { > + status = "okay"; > +}; > + > +&pcie3 { > + status = "okay"; > +}; > diff --git a/arch/arm/dts/mt7988-sd-rfb.dts b/arch/arm/dts/mt7988-sd-rfb.dts > index a3df37d252de..0a3eb5360d21 100644 > --- a/arch/arm/dts/mt7988-sd-rfb.dts > +++ b/arch/arm/dts/mt7988-sd-rfb.dts > @@ -132,3 +132,15 @@ > vqmmc-supply = <®_3p3v>; > status = "okay"; > }; > + > +&pcie0 { > + status = "okay"; > +}; > + > +&pcie1 { > + status = "okay"; > +}; > + > +&pcie3 { > + status = "okay"; > +}; > diff --git a/arch/arm/dts/mt7988.dtsi b/arch/arm/dts/mt7988.dtsi > index ac476d5cdd7f..b2e2724732fc 100644 > --- a/arch/arm/dts/mt7988.dtsi > +++ b/arch/arm/dts/mt7988.dtsi > @@ -194,6 +194,152 @@ > status = "okay"; > }; > > + pcie2: pcie@11280000 { > + compatible = "mediatek,mt7988-pcie", > + "mediatek,mt7986-pcie", > + "mediatek,mt8192-pcie"; > + device_type = "pci"; > + #address-cells = <3>; > + #size-cells = <2>; > + reg = <0 0x11280000 0 0x2000>; > + reg-names = "pcie-mac"; > + linux,pci-domain = <3>; > + interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>; > + bus-range = <0x00 0xff>; > + ranges = <0x82000000 0 0x20200000 0 0x20200000 0 0x07e00000>; > + clocks = <&infracfg_ao_cgs CK_INFRA_PCIE_PIPE_P2>, > + <&infracfg_ao_cgs CK_INFRA_PCIE_GFMUX_TL_P2>, > + <&infracfg_ao_cgs CK_INFRA_PCIE_PERI_26M_CK_P2>, > + <&infracfg_ao_cgs CK_INFRA_133M_PCIE_CK_P2>; > + clock-names = "pl_250m", "tl_26m", "peri_26m", > + "top_133m"; > + phys = <&xphyu3port0 PHY_TYPE_PCIE>; > + phy-names = "pcie-phy"; > + > + status = "disabled"; > + > + #interrupt-cells = <1>; > + interrupt-map-mask = <0 0 0 0x7>; > + interrupt-map = <0 0 0 1 &pcie_intc2 0>, > + <0 0 0 2 &pcie_intc2 1>, > + <0 0 0 3 &pcie_intc2 2>, > + <0 0 0 4 &pcie_intc2 3>; > + > + pcie_intc2: interrupt-controller { > + #address-cells = <0>; > + #interrupt-cells = <1>; > + interrupt-controller; > + }; > + }; > + > + pcie3: pcie@11290000 { > + compatible = "mediatek,mt7988-pcie", > + "mediatek,mt7986-pcie", > + "mediatek,mt8192-pcie"; > + device_type = "pci"; > + #address-cells = <3>; > + #size-cells = <2>; > + reg = <0 0x11290000 0 0x2000>; > + reg-names = "pcie-mac"; > + linux,pci-domain = <2>; > + interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>; > + bus-range = <0x00 0xff>; > + ranges = <0x82000000 0 0x28200000 0 0x28200000 0 0x07e00000>; > + clocks = <&infracfg_ao_cgs CK_INFRA_PCIE_PIPE_P3>, > + <&infracfg_ao_cgs CK_INFRA_PCIE_GFMUX_TL_P3>, > + <&infracfg_ao_cgs CK_INFRA_PCIE_PERI_26M_CK_P3>, > + <&infracfg_ao_cgs CK_INFRA_133M_PCIE_CK_P3>; > + clock-names = "pl_250m", "tl_26m", "peri_26m", > + "top_133m"; > + use-dedicated-phy; > + > + status = "disabled"; > + > + #interrupt-cells = <1>; > + interrupt-map-mask = <0 0 0 0x7>; > + interrupt-map = <0 0 0 1 &pcie_intc3 0>, > + <0 0 0 2 &pcie_intc3 1>, > + <0 0 0 3 &pcie_intc3 2>, > + <0 0 0 4 &pcie_intc3 3>; > + pcie_intc3: interrupt-controller { > + #address-cells = <0>; > + #interrupt-cells = <1>; > + interrupt-controller; > + }; > + }; > + > + pcie0: pcie@11300000 { > + compatible = "mediatek,mt7988-pcie", > + "mediatek,mt7986-pcie", > + "mediatek,mt8192-pcie"; > + device_type = "pci"; > + #address-cells = <3>; > + #size-cells = <2>; > + reg = <0 0x11300000 0 0x2000>; > + reg-names = "pcie-mac"; > + linux,pci-domain = <0>; > + interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; > + bus-range = <0x00 0xff>; > + ranges = <0x82000000 0 0x30200000 0 0x30200000 0 0x07e00000>; > + clocks = <&infracfg_ao_cgs CK_INFRA_PCIE_PIPE_P0>, > + <&infracfg_ao_cgs CK_INFRA_PCIE_GFMUX_TL_P0>, > + <&infracfg_ao_cgs CK_INFRA_PCIE_PERI_26M_CK_P0>, > + <&infracfg_ao_cgs CK_INFRA_133M_PCIE_CK_P0>; > + clock-names = "pl_250m", "tl_26m", "peri_26m", > + "top_133m"; > + use-dedicated-phy; > + > + status = "disabled"; > + > + #interrupt-cells = <1>; > + interrupt-map-mask = <0 0 0 0x7>; > + interrupt-map = <0 0 0 1 &pcie_intc0 0>, > + <0 0 0 2 &pcie_intc0 1>, > + <0 0 0 3 &pcie_intc0 2>, > + <0 0 0 4 &pcie_intc0 3>; > + pcie_intc0: interrupt-controller { > + #address-cells = <0>; > + #interrupt-cells = <1>; > + interrupt-controller; > + }; > + }; > + > + pcie1: pcie@11310000 { > + compatible = "mediatek,mt7988-pcie", > + "mediatek,mt7986-pcie", > + "mediatek,mt8192-pcie"; > + device_type = "pci"; > + #address-cells = <3>; > + #size-cells = <2>; > + reg = <0 0x11310000 0 0x2000>; > + reg-names = "pcie-mac"; > + linux,pci-domain = <1>; > + interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>; > + bus-range = <0x00 0xff>; > + ranges = <0x82000000 0 0x38200000 0 0x38200000 0 0x07e00000>; > + clocks = <&infracfg_ao_cgs CK_INFRA_PCIE_PIPE_P1>, > + <&infracfg_ao_cgs CK_INFRA_PCIE_GFMUX_TL_P1>, > + <&infracfg_ao_cgs CK_INFRA_PCIE_PERI_26M_CK_P1>, > + <&infracfg_ao_cgs CK_INFRA_133M_PCIE_CK_P1>; > + clock-names = "pl_250m", "tl_26m", "peri_26m", > + "top_133m"; > + use-dedicated-phy; > + > + status = "disabled"; > + > + #interrupt-cells = <1>; > + interrupt-map-mask = <0 0 0 0x7>; > + interrupt-map = <0 0 0 1 &pcie_intc1 0>, > + <0 0 0 2 &pcie_intc1 1>, > + <0 0 0 3 &pcie_intc1 2>, > + <0 0 0 4 &pcie_intc1 3>; > + pcie_intc1: interrupt-controller { > + #address-cells = <0>; > + #interrupt-cells = <1>; > + interrupt-controller; > + }; > + }; > + > usbtphy: usb-phy@11c50000 { > compatible = "mediatek,mt7988", > "mediatek,generic-tphy-v2"; > @@ -219,6 +365,24 @@ > mediatek,usb3-pll-ssc-delta1; > status = "okay"; > }; > + > + }; > + > + xphy: xphy@11e10000 { > + compatible = "mediatek,mt7988", > + "mediatek,xsphy"; > + #address-cells = <2>; > + #size-cells = <2>; > + ranges; > + status = "disabled"; > + > + xphyu3port0: usb-phy@11e13000 { > + reg = <0 0x11e13400 0 0x500>; > + clocks = <&dummy_clk>; > + clock-names = "ref"; > + #phy-cells = <1>; > + status = "okay"; > + }; > }; > > xfi_pextp0: syscon@11f20000 { > diff --git a/drivers/clk/mediatek/clk-mt7986.c > b/drivers/clk/mediatek/clk-mt7986.c > index b3fa63fc0ab4..93e02cd23ac1 100644 > --- a/drivers/clk/mediatek/clk-mt7986.c > +++ b/drivers/clk/mediatek/clk-mt7986.c > @@ -504,8 +504,9 @@ static const struct mtk_gate infracfg_ao_gates[] = { > GATE_INFRA2(CK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", CK_INFRA_USB_SYS_CK, > 2), > GATE_INFRA2(CK_INFRA_IUSB_CK, "infra_iusb", CK_INFRA_USB_CK, 3), > - GATE_INFRA2(CK_INFRA_IPCIE_CK, "infra_ipcie", CK_INFRA_PCIE_CK, 13), > - GATE_INFRA2(CK_INFRA_IPCIER_CK, "infra_ipcier", CK_INFRA_F26M_CK0, 15), > + GATE_INFRA2(CK_INFRA_IPCIE_CK, "infra_ipcie", CK_INFRA_PCIE_CK, 12), > + GATE_INFRA2(CK_INFRA_IPCIE_PIPE_CK, "infra_ipcie_pipe", > CK_INFRA_PCIE_CK, 13), > + GATE_INFRA2(CK_INFRA_IPCIER_CK, "infra_ipcier", CK_INFRA_F26M_CK0, 14), > GATE_INFRA2(CK_INFRA_IPCIEB_CK, "infra_ipcieb", CK_INFRA_133M_PHCK, 15), > }; > > diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig > index 463ec47eb92d..f62a9844b1ef 100644 > --- a/drivers/pci/Kconfig > +++ b/drivers/pci/Kconfig > @@ -350,6 +350,13 @@ config PCIE_MEDIATEK > Say Y here if you want to enable Gen2 PCIe controller, > which could be found on MT7623 SoC family. > > +config PCIE_MEDIATEK_GEN3 > + bool "MediaTek PCIe Gen3 controller" > + depends on ARCH_MEDIATEK > + help > + Say Y here if you want to enable Gen3 PCIe controller, > + which could be found on the Mediatek Filogic SoC family. > + > config PCIE_DW_MESON > bool "Amlogic Meson DesignWare based PCIe controller" > depends on ARCH_MESON > diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile > index 72ef8b4bc772..aa254a2f4338 100644 > --- a/drivers/pci/Makefile > +++ b/drivers/pci/Makefile > @@ -42,6 +42,7 @@ obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o > obj-$(CONFIG_PCIE_DW_COMMON) += pcie_dw_common.o > obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o > obj-$(CONFIG_PCIE_MEDIATEK) += pcie_mediatek.o > +obj-$(CONFIG_PCIE_MEDIATEK_GEN3) += pcie_mediatek_gen3.o > obj-$(CONFIG_PCIE_ROCKCHIP) += pcie_rockchip.o > obj-$(CONFIG_PCIE_DW_ROCKCHIP) += pcie_dw_rockchip.o > obj-$(CONFIG_PCIE_DW_MESON) += pcie_dw_meson.o > diff --git a/drivers/pci/pcie_mediatek_gen3.c > b/drivers/pci/pcie_mediatek_gen3.c > new file mode 100644 > index 000000000000..a273ea123aaa > --- /dev/null > +++ b/drivers/pci/pcie_mediatek_gen3.c > @@ -0,0 +1,382 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * MediaTek PCIe host controller driver. > + * > + * Copyright (c) 2023 John Crispin <j...@phrozen.org> > + * Driver is based on u-boot gen1/2 and upstream linux gen3 code > + */ > + > +#include <clk.h> > +#include <dm.h> > +#include <generic-phy.h> > +#include <log.h> > +#include <malloc.h> > +#include <pci.h> > +#include <reset.h> > +#include <asm/io.h> > +#include <dm/devres.h> > +#include <linux/bitops.h> > +#include <linux/iopoll.h> > +#include <linux/list.h> > +#include "pci_internal.h" > + > +/* PCIe shared registers */ > +#define PCIE_CFG_ADDR 0x20 > +#define PCIE_CFG_DATA 0x24 > + > +#define PCIE_SETTING_REG 0x80 > + > +#define PCIE_PCI_IDS_1 0x9c > +#define PCIE_RC_MODE BIT(0) > +#define PCI_CLASS(class) (class << 8) > + > +#define PCIE_CFGNUM_REG 0x140 > +#define PCIE_CFG_DEVFN(devfn) ((devfn) & GENMASK(7, 0)) > +#define PCIE_CFG_BUS(bus) (((bus) << 8) & GENMASK(15, 8)) > +#define PCIE_CFG_BYTE_EN(bytes) (((bytes) << 16) & GENMASK(19, > 16)) > +#define PCIE_CFG_FORCE_BYTE_EN BIT(20) > +#define PCIE_CFG_OFFSET_ADDR 0x1000 > +#define PCIE_CFG_HEADER(bus, devfn) (PCIE_CFG_BUS(bus) | > PCIE_CFG_DEVFN(devfn)) > + > +#define PCIE_RST_CTRL_REG 0x148 > +#define PCIE_MAC_RSTB BIT(0) > +#define PCIE_PHY_RSTB BIT(1) > +#define PCIE_BRG_RSTB BIT(2) > +#define PCIE_PE_RSTB BIT(3) > + > +#define PCIE_LINK_STATUS_REG 0x154 > +#define PCIE_PORT_LINKUP BIT(8) > + > +#define PCIE_INT_ENABLE_REG 0x180 > + > +#define PCIE_MISC_CTRL_REG 0x348 > +#define PCIE_DISABLE_DVFSRC_VLT_REQ BIT(1) > + > +#define PCIE_TRANS_TABLE_BASE_REG 0x800 > +#define PCIE_ATR_SRC_ADDR_MSB_OFFSET 0x4 > +#define PCIE_ATR_TRSL_ADDR_LSB_OFFSET 0x8 > +#define PCIE_ATR_TRSL_ADDR_MSB_OFFSET 0xc > +#define PCIE_ATR_TRSL_PARAM_OFFSET 0x10 > +#define PCIE_ATR_TLB_SET_OFFSET 0x20 > + > +#define PCIE_MAX_TRANS_TABLES 8 > +#define PCIE_ATR_EN BIT(0) > +#define PCIE_ATR_SIZE(size) \ > + (((((size) - 1) << 1) & GENMASK(6, 1)) | PCIE_ATR_EN) > +#define PCIE_ATR_ID(id) ((id) & GENMASK(3, 0)) > +#define PCIE_ATR_TYPE_MEM PCIE_ATR_ID(0) > +#define PCIE_ATR_TYPE_IO PCIE_ATR_ID(1) > +#define PCIE_ATR_TLP_TYPE(type) (((type) << 16) & GENMASK(18, 16)) > +#define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0) > +#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2) > + > +struct mtk_pcie { > + void __iomem *base; > + void *priv; > + struct clk pl_250m_ck; > + struct clk tl_26m_ck; > + struct clk peri_26m_ck; > + struct clk top_133m_ck; > + struct reset_ctl reset_phy; > + struct reset_ctl reset_mac; > + bool use_dedicated_phy; > + struct phy phy; > +}; > + > +static void mtk_pcie_config_tlp_header(const struct udevice *bus, > + pci_dev_t devfn, > + int where, int size) > +{ > + struct mtk_pcie *pcie = dev_get_priv(bus); > + int bytes; > + u32 val; > + > + size = 1 << size; > + bytes = (GENMASK(size - 1, 0) & 0xf) << (where & 0x3); > + > + val = PCIE_CFG_FORCE_BYTE_EN | PCIE_CFG_BYTE_EN(bytes) | > + PCIE_CFG_HEADER(PCI_BUS(devfn), (devfn >> 8)); > + > + writel(val, pcie->base + PCIE_CFGNUM_REG); > +} > + > +static int mtk_pcie_config_address(const struct udevice *udev, pci_dev_t bdf, > + uint offset, void **paddress) > +{ > + struct mtk_pcie *pcie = dev_get_priv(udev); > + > + *paddress = pcie->base + PCIE_CFG_OFFSET_ADDR + offset; > + > + return 0; > +} > + > +static int mtk_pcie_read_config(const struct udevice *bus, pci_dev_t bdf, > + uint offset, ulong *valuep, > + enum pci_size_t size) > +{ > + int ret; > + > + mtk_pcie_config_tlp_header(bus, bdf, offset, size); > + ret = pci_generic_mmap_read_config(bus, mtk_pcie_config_address, > + bdf, offset, valuep, size); > + return ret; > +} > + > +static int mtk_pcie_write_config(struct udevice *bus, pci_dev_t bdf, > + uint offset, ulong value, > + enum pci_size_t size) > +{ > + mtk_pcie_config_tlp_header(bus, bdf, offset, size); > + > + switch (size) { > + case PCI_SIZE_8: > + case PCI_SIZE_16: > + value <<= (offset & 0x3) * 8; > + case PCI_SIZE_32: > + break; > + default: > + return -EINVAL; > + } > + > + return pci_generic_mmap_write_config(bus, mtk_pcie_config_address, > + bdf, (offset & ~0x3), value, > PCI_SIZE_32); > +} > + > +static const struct dm_pci_ops mtk_pcie_ops = { > + .read_config = mtk_pcie_read_config, > + .write_config = mtk_pcie_write_config, > +}; > + > +static int mtk_pcie_set_trans_table(struct mtk_pcie *pcie, u64 cpu_addr, > + u64 pci_addr, u64 size, > + unsigned long type, int num) > +{ > + void __iomem *table; > + u32 val; > + > + if (num >= PCIE_MAX_TRANS_TABLES) { > + printf("not enough translate table for addr: %#llx, limited to > [%d]\n", > + (unsigned long long)cpu_addr, PCIE_MAX_TRANS_TABLES); > + return -ENODEV; > + } > + > + table = pcie->base + PCIE_TRANS_TABLE_BASE_REG + > + num * PCIE_ATR_TLB_SET_OFFSET; > + > + writel(lower_32_bits(cpu_addr) | PCIE_ATR_SIZE(fls(size) - 1), table); > + writel(upper_32_bits(cpu_addr), table + PCIE_ATR_SRC_ADDR_MSB_OFFSET); > + writel(lower_32_bits(pci_addr), table + PCIE_ATR_TRSL_ADDR_LSB_OFFSET); > + writel(upper_32_bits(pci_addr), table + PCIE_ATR_TRSL_ADDR_MSB_OFFSET); > + > + if (type == PCI_REGION_IO) > + val = PCIE_ATR_TYPE_IO | PCIE_ATR_TLP_TYPE_IO; > + else > + val = PCIE_ATR_TYPE_MEM | PCIE_ATR_TLP_TYPE_MEM; > + writel(val, table + PCIE_ATR_TRSL_PARAM_OFFSET); > + > + return 0; > +} > + > +static int mtk_pcie_startup_port(struct udevice *dev) > +{ > + struct mtk_pcie *pcie = dev_get_priv(dev); > + struct udevice *ctlr = pci_get_controller(dev); > + struct pci_controller *hose = dev_get_uclass_priv(ctlr); > + u32 val; > + int i, err; > + > + /* Set as RC mode */ > + val = readl(pcie->base + PCIE_SETTING_REG); > + val |= PCIE_RC_MODE; > + writel(val, pcie->base + PCIE_SETTING_REG); > + > + /* setup RC BARs */ > + writel(PCI_BASE_ADDRESS_MEM_TYPE_64, > + pcie->base + PCI_BASE_ADDRESS_0); > + writel(0x0, pcie->base + PCI_BASE_ADDRESS_1); > + > + /* setup interrupt pins */ > + clrsetbits_le32(pcie->base + PCI_INTERRUPT_LINE, > + 0xff00, 0x100); > + > + /* setup bus numbers */ > + clrsetbits_le32(pcie->base + PCI_PRIMARY_BUS, > + 0xffffff, 0x00ff0100); > + > + /* setup command register */ > + clrsetbits_le32(pcie->base + PCI_PRIMARY_BUS, > + 0xffff, > + PCI_COMMAND_IO | PCI_COMMAND_MEMORY | > + PCI_COMMAND_MASTER | PCI_COMMAND_SERR); > + > + /* Set class code */ > + val = readl(pcie->base + PCIE_PCI_IDS_1); > + val &= ~GENMASK(31, 8); > + val |= PCI_CLASS(PCI_CLASS_BRIDGE_PCI << 8); > + writel(val, pcie->base + PCIE_PCI_IDS_1); > + > + /* Mask all INTx interrupts */ > + val = readl(pcie->base + PCIE_INT_ENABLE_REG); > + val &= ~0xFF000000; > + writel(val, pcie->base + PCIE_INT_ENABLE_REG); > + > + /* Disable DVFSRC voltage request */ > + val = readl(pcie->base + PCIE_MISC_CTRL_REG); > + val |= PCIE_DISABLE_DVFSRC_VLT_REQ; > + writel(val, pcie->base + PCIE_MISC_CTRL_REG); > + > + /* Assert all reset signals */ > + val = readl(pcie->base + PCIE_RST_CTRL_REG); > + val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB; > + writel(val, pcie->base + PCIE_RST_CTRL_REG); > + > + /* > + * 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. > + */ > + mdelay(100); > + > + /* De-assert reset signals */ > + val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB); > + writel(val, pcie->base + PCIE_RST_CTRL_REG); > + > + mdelay(100); > + > + /* De-assert PERST# signals */ > + val &= ~(PCIE_PE_RSTB); > + writel(val, pcie->base + PCIE_RST_CTRL_REG); > + > + /* 100ms timeout value should be enough for Gen1/2 training */ > + err = readl_poll_timeout(pcie->base + PCIE_LINK_STATUS_REG, val, > + !!(val & PCIE_PORT_LINKUP), > + 100 * 1000); > + if (err) { > + printf("no card detected at 0x%08lx\n", (unsigned > long)pcie->base); > + return -ETIMEDOUT; > + } > + printf("detected a card at 0x%08lx\n", (unsigned long)pcie->base); > + > + for (i = 0; i < hose->region_count; i++) { > + struct pci_region *reg = &hose->regions[i]; > + > + if (reg->flags != PCI_REGION_MEM) > + continue; > + > + mtk_pcie_set_trans_table(pcie, reg->bus_start, reg->phys_start, > + reg->size, reg->flags, 0); > + } > + > + return 0; > +} > + > +static int mtk_pcie_power_on(struct udevice *dev) > +{ > + struct mtk_pcie *pcie = dev_get_priv(dev); > + int err; > + > + pcie->base = dev_remap_addr_name(dev, "pcie-mac"); > + if (!pcie->base) > + return -ENOENT; > + > + pcie->priv = dev; > + > + pcie->use_dedicated_phy = dev_read_bool(dev, "use-dedicated-phy"); > + > + if (!pcie->use_dedicated_phy) { > + err = generic_phy_get_by_name(dev, "pcie-phy", &pcie->phy); > + if (err) > + return err; > + } > + > + err = clk_get_by_name(dev, "pl_250m", &pcie->pl_250m_ck); > + if (err) > + return err; > + > + err = clk_get_by_name(dev, "tl_26m", &pcie->tl_26m_ck); > + if (err) > + return err; > + > + err = clk_get_by_name(dev, "peri_26m", &pcie->peri_26m_ck); > + if (err) > + return err; > + > + err = clk_get_by_name(dev, "top_133m", &pcie->top_133m_ck); > + if (err) > + return err; > + > + err = generic_phy_init(&pcie->phy); > + if (err) > + return err; > + > + if (!pcie->use_dedicated_phy) { > + err = generic_phy_power_on(&pcie->phy); > + if (err) > + goto err_phy_on; > + } > + > + err = clk_enable(&pcie->pl_250m_ck); > + if (err) > + goto err_clk_pl_250m; > + > + err = clk_enable(&pcie->tl_26m_ck); > + if (err) > + goto err_clk_tl_26m; > + > + err = clk_enable(&pcie->peri_26m_ck); > + if (err) > + goto err_clk_peri_26m; > + > + err = clk_enable(&pcie->top_133m_ck); > + if (err) > + goto err_clk_top_133m; > + > + err = mtk_pcie_startup_port(dev); > + if (err) > + goto err_startup; > + > + return 0; > + > +err_startup: > +err_clk_top_133m: > + clk_disable(&pcie->top_133m_ck); > +err_clk_peri_26m: > + clk_disable(&pcie->peri_26m_ck); > +err_clk_tl_26m: > + clk_disable(&pcie->tl_26m_ck); > +err_clk_pl_250m: > + clk_disable(&pcie->pl_250m_ck); > +err_phy_on: > + generic_phy_exit(&pcie->phy); > + > + return err; > +} > + > +static int mtk_pcie_probe(struct udevice *dev) > +{ > + struct mtk_pcie *pcie = dev_get_priv(dev); > + int err; > + > + pcie->priv = dev; > + > + err = mtk_pcie_power_on(dev); > + if (err) > + return err; > + > + return 0; > +} > + > +static const struct udevice_id mtk_pcie_ids[] = { > + { .compatible = "mediatek,mt8192-pcie" }, > + { } > +}; > + > +U_BOOT_DRIVER(pcie_mediatek_gen3) = { > + .name = "pcie_mediatek_gen3", > + .id = UCLASS_PCI, > + .of_match = mtk_pcie_ids, > + .ops = &mtk_pcie_ops, > + .probe = mtk_pcie_probe, > + .priv_auto = sizeof(struct mtk_pcie), > +}; > diff --git a/include/dt-bindings/clock/mt7981-clk.h > b/include/dt-bindings/clock/mt7981-clk.h > index e24c759e4992..1c2781cd765c 100644 > --- a/include/dt-bindings/clock/mt7981-clk.h > +++ b/include/dt-bindings/clock/mt7981-clk.h > @@ -226,7 +226,8 @@ > #define CK_INFRA_IPCIE_CK (54 - INFRACFG_AO_OFFSET) > #define CK_INFRA_IPCIER_CK (55 - INFRACFG_AO_OFFSET) > #define CK_INFRA_IPCIEB_CK (56 - INFRACFG_AO_OFFSET) > -#define CLK_INFRA_AO_NR_CLK (57 - INFRACFG_AO_OFFSET) > +#define CK_INFRA_IPCIE_PIPE_CK (57 - INFRACFG_AO_OFFSET) > +#define CLK_INFRA_AO_NR_CLK (58 - INFRACFG_AO_OFFSET) > > /* APMIXEDSYS */ > > diff --git a/include/dt-bindings/clock/mt7986-clk.h > b/include/dt-bindings/clock/mt7986-clk.h > index 820f86318316..fdf705921700 100644 > --- a/include/dt-bindings/clock/mt7986-clk.h > +++ b/include/dt-bindings/clock/mt7986-clk.h > @@ -205,7 +205,8 @@ > #define CK_INFRA_IPCIE_CK 42 > #define CK_INFRA_IPCIER_CK 43 > #define CK_INFRA_IPCIEB_CK 44 > -#define CLK_INFRA_AO_NR_CLK 45 > +#define CK_INFRA_IPCIE_PIPE_CK 45 > +#define CLK_INFRA_AO_NR_CLK 46 > > /* APMIXEDSYS */ > > -- > 2.34.1 > >