[RFC] pci: mediatek: add PCIe controller support for Filogic

From: John Crispin john@phrozen.org
This adds PCIe controller support for the MediaTek Filogic family..
Signed-off-by: John Crispin john@phrozen.org Signed-off-by: Frank Wunderlich frank-w@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 john@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 */

a gentle ping...any comments?
regards Frank
Gesendet: Freitag, 12. April 2024 um 16:10 Uhr Von: "Frank Wunderlich" linux@fw-web.de An: "Tom Rini" trini@konsulko.com, "Lukasz Majewski" lukma@denx.de, "Sean Anderson" seanga2@gmail.com, "Ryder Lee" ryder.lee@mediatek.com, "Weijie Gao" weijie.gao@mediatek.com, "Chunfeng Yun" chunfeng.yun@mediatek.com, "GSS_MTK_Uboot_upstream" GSS_MTK_Uboot_upstream@mediatek.com, "John Crispin" john@phrozen.org Cc: "Frank Wunderlich" frank-w@public-files.de, u-boot@lists.denx.de Betreff: [RFC] pci: mediatek: add PCIe controller support for Filogic
From: John Crispin john@phrozen.org
This adds PCIe controller support for the MediaTek Filogic family..
Signed-off-by: John Crispin john@phrozen.org Signed-off-by: Frank Wunderlich frank-w@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 john@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

Am 10. Mai 2024 15:08:19 MESZ schrieb Tom Rini trini@konsulko.com:
On Fri, May 10, 2024 at 01:57:26PM +0200, Frank Wunderlich wrote:
a gentle ping...any comments?
Seems fine?
Can we switch to OF_UPSTREAM first however?
Pulling mediatek devicetrees from linux will afaik break network in uboot for mt7622,7623,mt7986 and mt7988 bananapi boards because switch (mt753x) binding is different to linux.
regards Frank

On Fri, May 10, 2024 at 04:07:07PM +0200, Frank Wunderlich wrote:
Am 10. Mai 2024 15:08:19 MESZ schrieb Tom Rini trini@konsulko.com:
On Fri, May 10, 2024 at 01:57:26PM +0200, Frank Wunderlich wrote:
a gentle ping...any comments?
Seems fine?
Can we switch to OF_UPSTREAM first however?
Pulling mediatek devicetrees from linux will afaik break network in uboot for mt7622,7623,mt7986 and mt7988 bananapi boards because switch (mt753x) binding is different to linux.
That needs to be fixed, in U-Boot then. We should not forever diverge here, that was not the intent.
participants (3)
-
Frank Wunderlich
-
Frank Wunderlich
-
Tom Rini