Aw: [RFC] pci: mediatek: add PCIe controller support for Filogic
Frank Wunderlich
frank-w at public-files.de
Fri May 10 13:57:26 CEST 2024
a gentle ping...any comments?
regards Frank
> Gesendet: Freitag, 12. April 2024 um 16:10 Uhr
> Von: "Frank Wunderlich" <linux at fw-web.de>
> An: "Tom Rini" <trini at konsulko.com>, "Lukasz Majewski" <lukma at denx.de>, "Sean Anderson" <seanga2 at gmail.com>, "Ryder Lee" <ryder.lee at mediatek.com>, "Weijie Gao" <weijie.gao at mediatek.com>, "Chunfeng Yun" <chunfeng.yun at mediatek.com>, "GSS_MTK_Uboot_upstream" <GSS_MTK_Uboot_upstream at mediatek.com>, "John Crispin" <john at phrozen.org>
> Cc: "Frank Wunderlich" <frank-w at public-files.de>, u-boot at lists.denx.de
> Betreff: [RFC] pci: mediatek: add PCIe controller support for Filogic
>
> From: John Crispin <john at phrozen.org>
>
> This adds PCIe controller support for the MediaTek Filogic family..
>
> Signed-off-by: John Crispin <john at phrozen.org>
> Signed-off-by: Frank Wunderlich <frank-w at 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 at 11c00000 {
> + reg = <0x11c00000 0x20000>;
> + clocks = <&dummy_clk>;
> + clock-names = "ref";
> + #phy-cells = <1>;
> + status = "okay";
> + };
> + };
> +
> + pcie: pcie at 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 at 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 at 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 at 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 at 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 at 11c50000 {
> compatible = "mediatek,mt7988",
> "mediatek,generic-tphy-v2";
> @@ -219,6 +365,24 @@
> mediatek,usb3-pll-ssc-delta1;
> status = "okay";
> };
> +
> + };
> +
> + xphy: xphy at 11e10000 {
> + compatible = "mediatek,mt7988",
> + "mediatek,xsphy";
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> + status = "disabled";
> +
> + xphyu3port0: usb-phy at 11e13000 {
> + reg = <0 0x11e13400 0 0x500>;
> + clocks = <&dummy_clk>;
> + clock-names = "ref";
> + #phy-cells = <1>;
> + status = "okay";
> + };
> };
>
> xfi_pextp0: syscon at 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 at 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
>
>
More information about the U-Boot
mailing list