* [RFC] pci: mediatek: add PCIe controller support for Filogic @ 2024-04-12 14:10 Frank Wunderlich 2024-05-10 11:57 ` Aw: " Frank Wunderlich 0 siblings, 1 reply; 5+ messages in thread From: Frank Wunderlich @ 2024-04-12 14:10 UTC (permalink / raw) To: Tom Rini, Lukasz Majewski, Sean Anderson, Ryder Lee, Weijie Gao, Chunfeng Yun, GSS_MTK_Uboot_upstream, John Crispin Cc: Frank Wunderlich, u-boot 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 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Aw: [RFC] pci: mediatek: add PCIe controller support for Filogic 2024-04-12 14:10 [RFC] pci: mediatek: add PCIe controller support for Filogic Frank Wunderlich @ 2024-05-10 11:57 ` Frank Wunderlich 2024-05-10 13:08 ` Tom Rini 0 siblings, 1 reply; 5+ messages in thread From: Frank Wunderlich @ 2024-05-10 11:57 UTC (permalink / raw) To: Frank Wunderlich Cc: Tom Rini, Lukasz Majewski, Sean Anderson, Ryder Lee, Weijie Gao, Chunfeng Yun, GSS_MTK_Uboot_upstream, John Crispin, u-boot 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 > > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC] pci: mediatek: add PCIe controller support for Filogic 2024-05-10 11:57 ` Aw: " Frank Wunderlich @ 2024-05-10 13:08 ` Tom Rini 2024-05-10 14:07 ` Frank Wunderlich 0 siblings, 1 reply; 5+ messages in thread From: Tom Rini @ 2024-05-10 13:08 UTC (permalink / raw) To: Frank Wunderlich Cc: Frank Wunderlich, Lukasz Majewski, Sean Anderson, Ryder Lee, Weijie Gao, Chunfeng Yun, GSS_MTK_Uboot_upstream, John Crispin, u-boot [-- Attachment #1: Type: text/plain, Size: 173 bytes --] 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? -- Tom [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 659 bytes --] ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC] pci: mediatek: add PCIe controller support for Filogic 2024-05-10 13:08 ` Tom Rini @ 2024-05-10 14:07 ` Frank Wunderlich 2024-05-10 14:23 ` Tom Rini 0 siblings, 1 reply; 5+ messages in thread From: Frank Wunderlich @ 2024-05-10 14:07 UTC (permalink / raw) To: Tom Rini Cc: Frank Wunderlich, Lukasz Majewski, Sean Anderson, Ryder Lee, Weijie Gao, Chunfeng Yun, GSS_MTK_Uboot_upstream, John Crispin, u-boot 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 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC] pci: mediatek: add PCIe controller support for Filogic 2024-05-10 14:07 ` Frank Wunderlich @ 2024-05-10 14:23 ` Tom Rini 0 siblings, 0 replies; 5+ messages in thread From: Tom Rini @ 2024-05-10 14:23 UTC (permalink / raw) To: Frank Wunderlich Cc: Frank Wunderlich, Lukasz Majewski, Sean Anderson, Ryder Lee, Weijie Gao, Chunfeng Yun, GSS_MTK_Uboot_upstream, John Crispin, u-boot [-- Attachment #1: Type: text/plain, Size: 633 bytes --] 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. -- Tom [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 659 bytes --] ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-05-10 14:23 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-04-12 14:10 [RFC] pci: mediatek: add PCIe controller support for Filogic Frank Wunderlich 2024-05-10 11:57 ` Aw: " Frank Wunderlich 2024-05-10 13:08 ` Tom Rini 2024-05-10 14:07 ` Frank Wunderlich 2024-05-10 14:23 ` Tom Rini
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox