diff options
Diffstat (limited to 'drivers/pci')
49 files changed, 502 insertions, 77 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 8d02ab82ad9..22a56f4ca38 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 2927c519129..5b2d2969802 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/pci-aardvark.c b/drivers/pci/pci-aardvark.c index af0e55cd2f2..f5db4bdb760 100644 --- a/drivers/pci/pci-aardvark.c +++ b/drivers/pci/pci-aardvark.c @@ -25,7 +25,6 @@ * */ -#include <common.h> #include <dm.h> #include <pci.h> #include <asm/io.h> diff --git a/drivers/pci/pci-emul-uclass.c b/drivers/pci/pci-emul-uclass.c index a0b8afb87a0..166ee9fcd43 100644 --- a/drivers/pci/pci-emul-uclass.c +++ b/drivers/pci/pci-emul-uclass.c @@ -4,7 +4,6 @@ * Written by Simon Glass <sjg@chromium.org> */ -#include <common.h> #include <dm.h> #include <fdtdec.h> #include <log.h> diff --git a/drivers/pci/pci-rcar-gen2.c b/drivers/pci/pci-rcar-gen2.c index b81eb353689..12c31e74087 100644 --- a/drivers/pci/pci-rcar-gen2.c +++ b/drivers/pci/pci-rcar-gen2.c @@ -5,7 +5,7 @@ * Copyright (C) 2018 Marek Vasut <marek.vasut@gmail.com> */ -#include <common.h> +#include <config.h> #include <asm/io.h> #include <clk.h> #include <dm.h> diff --git a/drivers/pci/pci-rcar-gen3.c b/drivers/pci/pci-rcar-gen3.c index 1252ef74c58..76878246f1e 100644 --- a/drivers/pci/pci-rcar-gen3.c +++ b/drivers/pci/pci-rcar-gen3.c @@ -15,7 +15,6 @@ * Author: Phil Edworthy <phil.edworthy@renesas.com> */ -#include <common.h> #include <asm/io.h> #include <clk.h> #include <dm.h> diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 1a48256de03..6571e653049 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -6,7 +6,6 @@ #define LOG_CATEGORY UCLASS_PCI -#include <common.h> #include <dm.h> #include <errno.h> #include <init.h> diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index 01230360bad..90f81886445 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -8,7 +8,7 @@ * Copyright (c) 2021 Maciej W. Rozycki <macro@orcam.me.uk> */ -#include <common.h> +#include <config.h> #include <dm.h> #include <errno.h> #include <log.h> diff --git a/drivers/pci/pci_auto_common.c b/drivers/pci/pci_auto_common.c index 2f4aff01049..141166e59b7 100644 --- a/drivers/pci/pci_auto_common.c +++ b/drivers/pci/pci_auto_common.c @@ -11,7 +11,6 @@ * Written by Simon Glass <sjg@chromium.org> */ -#include <common.h> #include <dm.h> #include <errno.h> #include <log.h> @@ -109,7 +108,6 @@ void pciauto_config_init(struct pci_controller *hose) } } - if (hose->pci_mem) pciauto_show_region("Memory", hose->pci_mem); if (hose->pci_prefetch) diff --git a/drivers/pci/pci_common.c b/drivers/pci/pci_common.c index a18251297fd..a57cf11cc53 100644 --- a/drivers/pci/pci_common.c +++ b/drivers/pci/pci_common.c @@ -9,7 +9,6 @@ * Wolfgang Denk, DENX Software Engineering, wd@denx.de. */ -#include <common.h> #include <dm.h> #include <env.h> #include <errno.h> diff --git a/drivers/pci/pci_compat.c b/drivers/pci/pci_compat.c index 9dddca8efe0..8233925e525 100644 --- a/drivers/pci/pci_compat.c +++ b/drivers/pci/pci_compat.c @@ -4,7 +4,6 @@ * * Copyright (C) 2014 Google, Inc */ -#include <common.h> #include <dm.h> #include <errno.h> #include <log.h> diff --git a/drivers/pci/pci_ftpci100.c b/drivers/pci/pci_ftpci100.c index a1775445005..43275b3d6a2 100644 --- a/drivers/pci/pci_ftpci100.c +++ b/drivers/pci/pci_ftpci100.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include <common.h> #include <pci.h> #include <dm.h> #include <asm/io.h> diff --git a/drivers/pci/pci_mpc85xx.c b/drivers/pci/pci_mpc85xx.c index 249cfe66466..c07feba7976 100644 --- a/drivers/pci/pci_mpc85xx.c +++ b/drivers/pci/pci_mpc85xx.c @@ -4,7 +4,6 @@ * Heiko Schocher, DENX Software Engineering, hs@denx.de. * */ -#include <common.h> #include <asm/bitops.h> #include <pci.h> #include <dm.h> diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c index 83559550e6f..77815513b76 100644 --- a/drivers/pci/pci_mvebu.c +++ b/drivers/pci/pci_mvebu.c @@ -10,7 +10,6 @@ * Pali Rohár <pali@kernel.org> */ -#include <common.h> #include <dm.h> #include <log.h> #include <malloc.h> diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 438583aa017..78e5de937cd 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -24,7 +24,6 @@ #define LOG_CATEGORY UCLASS_PCI -#include <common.h> #include <bios_emul.h> #include <bloblist.h> #include <bootstage.h> @@ -36,6 +35,7 @@ #include <pci.h> #include <pci_rom.h> #include <spl.h> +#include <time.h> #include <vesa.h> #include <video.h> #include <acpi/acpi_s3.h> diff --git a/drivers/pci/pci_sandbox.c b/drivers/pci/pci_sandbox.c index ca44d002371..fed0850458d 100644 --- a/drivers/pci/pci_sandbox.c +++ b/drivers/pci/pci_sandbox.c @@ -4,7 +4,6 @@ * Written by Simon Glass <sjg@chromium.org> */ -#include <common.h> #include <dm.h> #include <fdtdec.h> #include <log.h> diff --git a/drivers/pci/pci_sh7751.c b/drivers/pci/pci_sh7751.c index c1be56ce7a0..3cd01e9b94a 100644 --- a/drivers/pci/pci_sh7751.c +++ b/drivers/pci/pci_sh7751.c @@ -5,7 +5,7 @@ * (C) 2007,2008 Nobuhiro Iwamatsu <iwamatsu@nigauri.org> */ -#include <common.h> +#include <config.h> #include <dm.h> #include <pci.h> #include <asm/processor.h> diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index d6374a58e33..bb8832c6ab9 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -11,7 +11,6 @@ #define pr_fmt(fmt) "tegra-pcie: " fmt -#include <common.h> #include <clk.h> #include <dm.h> #include <errno.h> diff --git a/drivers/pci/pci_x86.c b/drivers/pci/pci_x86.c index 8d036930e73..ab76166451c 100644 --- a/drivers/pci/pci_x86.c +++ b/drivers/pci/pci_x86.c @@ -3,7 +3,6 @@ * Copyright (c) 2015 Google, Inc */ -#include <common.h> #include <dm.h> #include <pci.h> #include <asm/pci.h> diff --git a/drivers/pci/pcie_apple.c b/drivers/pci/pcie_apple.c index 21bafba3b0e..6a8e715d4b6 100644 --- a/drivers/pci/pcie_apple.c +++ b/drivers/pci/pcie_apple.c @@ -16,7 +16,6 @@ * Author: Marc Zyngier <maz@kernel.org> */ -#include <common.h> #include <dm.h> #include <dm/device_compat.h> #include <dm/devres.h> diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c index cd45f0bee9b..f978c64365c 100644 --- a/drivers/pci/pcie_brcmstb.c +++ b/drivers/pci/pcie_brcmstb.c @@ -12,7 +12,6 @@ * Copyright (C) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de> */ -#include <common.h> #include <errno.h> #include <dm.h> #include <dm/ofnode.h> diff --git a/drivers/pci/pcie_dw_common.c b/drivers/pci/pcie_dw_common.c index 74fb6df412c..0673e516c6f 100644 --- a/drivers/pci/pcie_dw_common.c +++ b/drivers/pci/pcie_dw_common.c @@ -8,7 +8,6 @@ * Copyright (C) 2018 Texas Instruments, Inc */ -#include <common.h> #include <dm.h> #include <log.h> #include <pci.h> diff --git a/drivers/pci/pcie_dw_meson.c b/drivers/pci/pcie_dw_meson.c index f953797908b..bb78e7874b1 100644 --- a/drivers/pci/pcie_dw_meson.c +++ b/drivers/pci/pcie_dw_meson.c @@ -9,7 +9,6 @@ * Copyright (c) 2021 Rockchip, Inc. */ -#include <common.h> #include <clk.h> #include <dm.h> #include <generic-phy.h> diff --git a/drivers/pci/pcie_dw_mvebu.c b/drivers/pci/pcie_dw_mvebu.c index c41f3f15304..43b919175c9 100644 --- a/drivers/pci/pcie_dw_mvebu.c +++ b/drivers/pci/pcie_dw_mvebu.c @@ -10,10 +10,11 @@ * - drivers/pci/pcie_xilinx.c */ -#include <common.h> +#include <config.h> #include <dm.h> #include <log.h> #include <pci.h> +#include <time.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm-generic/gpio.h> diff --git a/drivers/pci/pcie_dw_rockchip.c b/drivers/pci/pcie_dw_rockchip.c index bc4635f6713..ac7faa4cc19 100644 --- a/drivers/pci/pcie_dw_rockchip.c +++ b/drivers/pci/pcie_dw_rockchip.c @@ -5,7 +5,6 @@ * Copyright (c) 2021 Rockchip, Inc. */ -#include <common.h> #include <clk.h> #include <dm.h> #include <generic-phy.h> @@ -507,7 +506,6 @@ static int rockchip_pcie_probe(struct udevice *dev) pcie_dw_get_link_width(&priv->dw), hose->first_busno); - ret = pcie_dw_prog_outbound_atu_unroll(&priv->dw, PCIE_ATU_REGION_INDEX0, PCIE_ATU_TYPE_MEM, diff --git a/drivers/pci/pcie_dw_sifive.c b/drivers/pci/pcie_dw_sifive.c index fac3f182372..6285edf4b03 100644 --- a/drivers/pci/pcie_dw_sifive.c +++ b/drivers/pci/pcie_dw_sifive.c @@ -14,7 +14,6 @@ #include <asm/io.h> #include <asm-generic/gpio.h> #include <clk.h> -#include <common.h> #include <dm.h> #include <dm/device_compat.h> #include <generic-phy.h> diff --git a/drivers/pci/pcie_dw_ti.c b/drivers/pci/pcie_dw_ti.c index 4195a02de39..dc6e65273b7 100644 --- a/drivers/pci/pcie_dw_ti.c +++ b/drivers/pci/pcie_dw_ti.c @@ -3,7 +3,6 @@ * Copyright (C) 2018 Texas Instruments, Inc */ -#include <common.h> #include <dm.h> #include <log.h> #include <pci.h> @@ -47,7 +46,6 @@ DECLARE_GLOBAL_DATA_PTR; #define PCIE_CMD_STATUS 0x04 #define LTSSM_EN_VAL BIT(0) - #define AM654_PCIE_DEV_TYPE_MASK 0x3 #define EP 0x0 #define LEG_EP 0x1 diff --git a/drivers/pci/pcie_ecam_generic.c b/drivers/pci/pcie_ecam_generic.c index f5bc6e3d92d..3cb2bbbccb4 100644 --- a/drivers/pci/pcie_ecam_generic.c +++ b/drivers/pci/pcie_ecam_generic.c @@ -7,7 +7,6 @@ * Copyright (C) 2016 Imagination Technologies */ -#include <common.h> #include <dm.h> #include <pci.h> #include <linux/ioport.h> diff --git a/drivers/pci/pcie_ecam_synquacer.c b/drivers/pci/pcie_ecam_synquacer.c index e3e22891088..fc855dfca4e 100644 --- a/drivers/pci/pcie_ecam_synquacer.c +++ b/drivers/pci/pcie_ecam_synquacer.c @@ -8,7 +8,6 @@ * Copyright (C) 2021 Linaro Ltd. */ -#include <common.h> #include <dm.h> #include <pci.h> #include <log.h> diff --git a/drivers/pci/pcie_fsl.c b/drivers/pci/pcie_fsl.c index ec917ee7d5b..18af23c9504 100644 --- a/drivers/pci/pcie_fsl.c +++ b/drivers/pci/pcie_fsl.c @@ -6,7 +6,7 @@ * Author: Hou Zhiqiang <Zhiqiang.Hou@nxp.com> */ -#include <common.h> +#include <config.h> #include <dm.h> #include <malloc.h> #include <mapmem.h> diff --git a/drivers/pci/pcie_fsl_fixup.c b/drivers/pci/pcie_fsl_fixup.c index f4e227895d1..9187e7af746 100644 --- a/drivers/pci/pcie_fsl_fixup.c +++ b/drivers/pci/pcie_fsl_fixup.c @@ -6,7 +6,6 @@ * Author: Hou Zhiqiang <Zhiqiang.Hou@nxp.com> */ -#include <common.h> #ifdef CONFIG_OF_BOARD_SETUP #include <dm.h> #include <fdt_support.h> diff --git a/drivers/pci/pcie_imx.c b/drivers/pci/pcie_imx.c index 78f2c7d6bcd..11c4ccbfc55 100644 --- a/drivers/pci/pcie_imx.c +++ b/drivers/pci/pcie_imx.c @@ -17,7 +17,6 @@ * those too in order to have a single modern PCIe iMX driver. */ -#include <common.h> #include <init.h> #include <log.h> #include <malloc.h> diff --git a/drivers/pci/pcie_intel_fpga.c b/drivers/pci/pcie_intel_fpga.c index 60195cfe1b6..959fd369086 100644 --- a/drivers/pci/pcie_intel_fpga.c +++ b/drivers/pci/pcie_intel_fpga.c @@ -6,7 +6,6 @@ * */ -#include <common.h> #include <dm.h> #include <pci.h> #include <asm/global_data.h> diff --git a/drivers/pci/pcie_iproc.c b/drivers/pci/pcie_iproc.c index d6d3a9e2025..360ef1b011f 100644 --- a/drivers/pci/pcie_iproc.c +++ b/drivers/pci/pcie_iproc.c @@ -4,7 +4,6 @@ * */ -#include <common.h> #include <dm.h> #include <errno.h> #include <generic-phy.h> diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c index 3c7c4ca18e8..1be33095b9c 100644 --- a/drivers/pci/pcie_layerscape.c +++ b/drivers/pci/pcie_layerscape.c @@ -5,7 +5,6 @@ * Layerscape PCIe driver */ -#include <common.h> #include <log.h> #include <asm/global_data.h> #include <asm/io.h> diff --git a/drivers/pci/pcie_layerscape_ep.c b/drivers/pci/pcie_layerscape_ep.c index 83f7eebd627..3520488b345 100644 --- a/drivers/pci/pcie_layerscape_ep.c +++ b/drivers/pci/pcie_layerscape_ep.c @@ -4,7 +4,7 @@ * Layerscape PCIe EP driver */ -#include <common.h> +#include <config.h> #include <asm/arch/fsl_serdes.h> #include <dm.h> #include <asm/global_data.h> diff --git a/drivers/pci/pcie_layerscape_fixup.c b/drivers/pci/pcie_layerscape_fixup.c index c5198353957..97c38c0bfa7 100644 --- a/drivers/pci/pcie_layerscape_fixup.c +++ b/drivers/pci/pcie_layerscape_fixup.c @@ -5,7 +5,6 @@ * Layerscape PCIe driver */ -#include <common.h> #include <dm.h> #include <init.h> #include <log.h> @@ -504,7 +503,6 @@ static void fdt_fixup_pcie_ls(void *blob) struct extra_iommu_entry *entries; int i, cnt, nodeoffset; - /* Scan all known buses */ for (pci_find_first_device(&dev); dev; diff --git a/drivers/pci/pcie_layerscape_fixup_common.c b/drivers/pci/pcie_layerscape_fixup_common.c index 095874a9276..f37e37f6b15 100644 --- a/drivers/pci/pcie_layerscape_fixup_common.c +++ b/drivers/pci/pcie_layerscape_fixup_common.c @@ -7,10 +7,10 @@ * */ -#include <common.h> #include <init.h> #include <asm/arch/clock.h> #include <asm/arch/soc.h> +#include <linux/errno.h> #include <linux/libfdt.h> #include <fdt_support.h> #include "pcie_layerscape_fixup_common.h" diff --git a/drivers/pci/pcie_layerscape_gen4.c b/drivers/pci/pcie_layerscape_gen4.c index 021c975869f..57dc91f2fae 100644 --- a/drivers/pci/pcie_layerscape_gen4.c +++ b/drivers/pci/pcie_layerscape_gen4.c @@ -6,7 +6,7 @@ * Author: Hou Zhiqiang <Minder.Hou@gmail.com> */ -#include <common.h> +#include <config.h> #include <log.h> #include <asm/arch/fsl_serdes.h> #include <pci.h> diff --git a/drivers/pci/pcie_layerscape_gen4_fixup.c b/drivers/pci/pcie_layerscape_gen4_fixup.c index b2a45bf105c..60c4338bcdb 100644 --- a/drivers/pci/pcie_layerscape_gen4_fixup.c +++ b/drivers/pci/pcie_layerscape_gen4_fixup.c @@ -7,7 +7,6 @@ * */ -#include <common.h> #include <dm.h> #include <log.h> #include <pci.h> diff --git a/drivers/pci/pcie_layerscape_rc.c b/drivers/pci/pcie_layerscape_rc.c index 6a5bf88da23..e7913d43a8b 100644 --- a/drivers/pci/pcie_layerscape_rc.c +++ b/drivers/pci/pcie_layerscape_rc.c @@ -4,7 +4,6 @@ * Layerscape PCIe driver */ -#include <common.h> #include <asm/arch/fsl_serdes.h> #include <pci.h> #include <asm/global_data.h> diff --git a/drivers/pci/pcie_mediatek.c b/drivers/pci/pcie_mediatek.c index f0f34b5d119..d88d850924c 100644 --- a/drivers/pci/pcie_mediatek.c +++ b/drivers/pci/pcie_mediatek.c @@ -7,7 +7,6 @@ * Honghui Zhang <honghui.zhang@mediatek.com> */ -#include <common.h> #include <clk.h> #include <dm.h> #include <generic-phy.h> @@ -525,7 +524,7 @@ exit: mtk_pcie_port_free(port); } -static int mtk_pcie_parse_port(struct udevice *dev, u32 slot) +static int mtk_pcie_parse_port(struct udevice *dev, u32 slot, int index) { struct mtk_pcie *pcie = dev_get_priv(dev); struct mtk_pcie_port *port; @@ -546,11 +545,11 @@ static int mtk_pcie_parse_port(struct udevice *dev, u32 slot) if (err) return err; - err = reset_get_by_index(dev, slot, &port->reset); + err = reset_get_by_index(dev, index, &port->reset); if (err) return err; - err = generic_phy_get_by_index(dev, slot, &port->phy); + err = generic_phy_get_by_index(dev, index, &port->phy); if (err) return err; @@ -632,18 +631,58 @@ static int mtk_pcie_parse_port_v2(struct udevice *dev, u32 slot) return 0; } +static int mtk_pcie_subsys_get(struct udevice *dev) +{ + struct mtk_pcie *pcie = dev_get_priv(dev); + ofnode cfg_node; + fdt_addr_t addr; + + cfg_node = ofnode_by_compatible(ofnode_null(), + "mediatek,generic-pciecfg"); + if (!ofnode_valid(cfg_node)) + return -ENOENT; + + addr = ofnode_get_addr(cfg_node); + if (addr == FDT_ADDR_T_NONE) + return -ENODEV; + + pcie->base = map_physmem(addr, 0, MAP_NOCACHE); + if (!pcie->base) + return -ENOENT; + + return 0; +} + static int mtk_pcie_probe(struct udevice *dev) { struct mtk_pcie *pcie = dev_get_priv(dev); struct mtk_pcie_port *port, *tmp; + bool split_pcie_node = false; ofnode subnode; + unsigned int slot; int err; INIT_LIST_HEAD(&pcie->ports); - pcie->base = dev_remap_addr_name(dev, "subsys"); - if (!pcie->base) - return -ENOENT; + /* Check if upstream implementation is used */ + err = mtk_pcie_subsys_get(dev); + if (!err) { + /* + * Assume split port node implementation with "mediatek,generic-pciecfg" + * found. We check reg-names and check if the node is for port0 or port1. + */ + split_pcie_node = true; + if (!strcmp(dev_read_string(dev, "reg-names"), "port0")) + slot = 0; + else if (!strcmp(dev_read_string(dev, "reg-names"), "port1")) + slot = 1; + else + return -EINVAL; + } else { + pcie->base = dev_remap_addr_name(dev, "subsys"); + if (!pcie->base) + return -ENOENT; + } err = clk_get_by_name(dev, "free_ck", &pcie->free_ck); if (err) @@ -654,20 +693,27 @@ static int mtk_pcie_probe(struct udevice *dev) if (err) return err; - dev_for_each_subnode(subnode, dev) { - struct fdt_pci_addr addr; - u32 slot = 0; + if (!split_pcie_node) { + dev_for_each_subnode(subnode, dev) { + struct fdt_pci_addr addr; - if (!ofnode_is_enabled(subnode)) - continue; + slot = 0; - err = ofnode_read_pci_addr(subnode, 0, "reg", &addr, NULL); - if (err) - return err; + if (!ofnode_is_enabled(subnode)) + continue; - slot = PCI_DEV(addr.phys_hi); + err = ofnode_read_pci_addr(subnode, 0, "reg", &addr, NULL); + if (err) + return err; - err = mtk_pcie_parse_port(dev, slot); + slot = PCI_DEV(addr.phys_hi); + + err = mtk_pcie_parse_port(dev, slot, slot); + if (err) + return err; + } + } else { + err = mtk_pcie_parse_port(dev, slot, 0); if (err) return err; } @@ -683,28 +729,54 @@ static int mtk_pcie_probe_v2(struct udevice *dev) { struct mtk_pcie *pcie = dev_get_priv(dev); struct mtk_pcie_port *port, *tmp; - struct fdt_pci_addr addr; + bool split_pcie_node = false; ofnode subnode; unsigned int slot; int err; INIT_LIST_HEAD(&pcie->ports); - pcie->base = dev_remap_addr_name(dev, "subsys"); - if (!pcie->base) - return -ENOENT; + /* Check if upstream implementation is used */ + err = mtk_pcie_subsys_get(dev); + if (!err) { + /* + * Assume split port node implementation with "mediatek,generic-pciecfg" + * found. We check reg-names and check if the node is for port0 or port1. + */ + split_pcie_node = true; + if (!strcmp(dev_read_string(dev, "reg-names"), "port0")) + slot = 0; + else if (!strcmp(dev_read_string(dev, "reg-names"), "port1")) + slot = 1; + else + return -EINVAL; + } else { + pcie->base = dev_remap_addr_name(dev, "subsys"); + if (!pcie->base) + return -ENOENT; + } pcie->priv = dev; - dev_for_each_subnode(subnode, dev) { - if (!ofnode_is_enabled(subnode)) - continue; + if (!split_pcie_node) { + dev_for_each_subnode(subnode, dev) { + struct fdt_pci_addr addr; - err = ofnode_read_pci_addr(subnode, 0, "reg", &addr, NULL); - if (err) - return err; + slot = 0; - slot = PCI_DEV(addr.phys_hi); + if (!ofnode_is_enabled(subnode)) + continue; + + err = ofnode_read_pci_addr(subnode, 0, "reg", &addr, NULL); + if (err) + return err; + + slot = PCI_DEV(addr.phys_hi); + err = mtk_pcie_parse_port_v2(dev, slot); + if (err) + return err; + } + } else { err = mtk_pcie_parse_port_v2(dev, slot); if (err) return err; diff --git a/drivers/pci/pcie_mediatek_gen3.c b/drivers/pci/pcie_mediatek_gen3.c new file mode 100644 index 00000000000..0149edae0bf --- /dev/null +++ b/drivers/pci/pcie_mediatek_gen3.c @@ -0,0 +1,384 @@ +// 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/device_compat.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; + 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 udevice *dev, 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) { + dev_err(dev, "not enough translate table for addr: %#llx, limited to [%d]\n", + (unsigned long long)cpu_addr, PCIE_MAX_TRANS_TABLES); + return -ENODEV; + } + + dev_dbg(dev, "set trans table %d: %#llx %#llx, %#llx\n", num, cpu_addr, + pci_addr, size); + 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) { + dev_dbg(dev, "no card detected\n"); + return -ETIMEDOUT; + } + dev_dbg(dev, "detected a card\n"); + + 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(dev, 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-phy is optional (mt7988 doesn't need it) */ + generic_phy_get_by_name(dev, "pcie-phy", &pcie->phy); + + /* + * Upstream linux kernel devine these clock without clock-names + * and use clk bulk API to enable them all. + */ + err = clk_get_by_index(dev, 0, &pcie->pl_250m_ck); + if (err) + return err; + + err = clk_get_by_index(dev, 1, &pcie->tl_26m_ck); + if (err) + return err; + + err = clk_get_by_index(dev, 2, &pcie->peri_26m_ck); + if (err) + return err; + + err = clk_get_by_index(dev, 3, &pcie->top_133m_ck); + if (err) + return err; + + if (pcie->phy.dev) { + err = generic_phy_init(&pcie->phy); + if (err) + return err; + + 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: + if (pcie->phy.dev) + 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/drivers/pci/pcie_phytium.c b/drivers/pci/pcie_phytium.c index 3bd1f5cd6d9..94de89bcad7 100644 --- a/drivers/pci/pcie_phytium.c +++ b/drivers/pci/pcie_phytium.c @@ -7,7 +7,6 @@ * Copyright (C) 2019 */ -#include <common.h> #include <dm.h> #include <pci.h> #include <asm/global_data.h> diff --git a/drivers/pci/pcie_plda_common.c b/drivers/pci/pcie_plda_common.c index cd74bb47116..622a5cee109 100644 --- a/drivers/pci/pcie_plda_common.c +++ b/drivers/pci/pcie_plda_common.c @@ -6,7 +6,6 @@ * */ -#include <common.h> #include <clk.h> #include <dm.h> #include <pci.h> diff --git a/drivers/pci/pcie_rockchip.c b/drivers/pci/pcie_rockchip.c index 624841e9d8b..19f9e58a640 100644 --- a/drivers/pci/pcie_rockchip.c +++ b/drivers/pci/pcie_rockchip.c @@ -11,7 +11,6 @@ * Bits taken from Linux Rockchip PCIe host controller. */ -#include <common.h> #include <dm.h> #include <dm/device_compat.h> #include <generic-phy.h> diff --git a/drivers/pci/pcie_starfive_jh7110.c b/drivers/pci/pcie_starfive_jh7110.c index 903a544d37f..569fbfd35c8 100644 --- a/drivers/pci/pcie_starfive_jh7110.c +++ b/drivers/pci/pcie_starfive_jh7110.c @@ -7,7 +7,6 @@ * */ -#include <common.h> #include <clk.h> #include <dm.h> #include <pci.h> diff --git a/drivers/pci/pcie_uniphier.c b/drivers/pci/pcie_uniphier.c index f2edea9899a..d1170b576bc 100644 --- a/drivers/pci/pcie_uniphier.c +++ b/drivers/pci/pcie_uniphier.c @@ -5,7 +5,6 @@ */ #include <clk.h> -#include <common.h> #include <dm.h> #include <dm/device_compat.h> #include <generic-phy.h> diff --git a/drivers/pci/pcie_xilinx.c b/drivers/pci/pcie_xilinx.c index 3db460b5f93..a674ab04bee 100644 --- a/drivers/pci/pcie_xilinx.c +++ b/drivers/pci/pcie_xilinx.c @@ -5,7 +5,6 @@ * Copyright (C) 2016 Imagination Technologies */ -#include <common.h> #include <dm.h> #include <pci.h> #include <linux/bitops.h> |