diff options
author | Tom Rini | 2024-07-08 11:56:59 -0600 |
---|---|---|
committer | Tom Rini | 2024-07-08 11:56:59 -0600 |
commit | 475aa8345a78396d39b42f96eccecd37ebe24e99 (patch) | |
tree | c788908a4d8b32a0624c59c4ad60ebbb82998674 | |
parent | e13fcae3fce8b2c4db86339c9e8bafdd403f22b5 (diff) | |
parent | 4b45082bf710097c8aa6f3ec25c3f34c54c7398c (diff) |
Merge patch series "mediatek: cumulative trivial fix for OF_UPSTREAM support"
Christian Marangi <ansuelsmth@gmail.com> says:
This is an initial series that have all the initial trivial
fixes required for usage of OF_UPSTREAM for the mediatek SoC
This also contains the pcie-gen3 driver and the required tphy
support driver to make it work.
Subsequent series will follow with conversion of the mtk-clk
to permit usage of OF_UPSTREAM and upstream clk ID.
MT7981, MT7986 and MT7988 migration to upstream clock ID
is complete and working on MT7623.
Series CI tested with PR: https://github.com/u-boot/u-boot/pull/590
-rw-r--r-- | drivers/clk/mediatek/clk-mt7981.c | 1 | ||||
-rw-r--r-- | drivers/clk/mediatek/clk-mt7986.c | 1 | ||||
-rw-r--r-- | drivers/clk/mediatek/clk-mt7988.c | 1 | ||||
-rw-r--r-- | drivers/i2c/mtk_i2c.c | 30 | ||||
-rw-r--r-- | drivers/mmc/mtk-sd.c | 35 | ||||
-rw-r--r-- | drivers/net/mtk_eth.c | 4 | ||||
-rw-r--r-- | drivers/pci/Kconfig | 7 | ||||
-rw-r--r-- | drivers/pci/Makefile | 1 | ||||
-rw-r--r-- | drivers/pci/pcie_mediatek_gen3.c | 384 | ||||
-rw-r--r-- | drivers/phy/Kconfig | 2 | ||||
-rw-r--r-- | drivers/phy/phy-mtk-tphy.c | 80 | ||||
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-mt7981.c | 1 | ||||
-rw-r--r-- | drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 10 | ||||
-rw-r--r-- | drivers/serial/serial_mtk.c | 20 | ||||
-rw-r--r-- | drivers/spi/mtk_spim.c | 45 |
15 files changed, 614 insertions, 8 deletions
diff --git a/drivers/clk/mediatek/clk-mt7981.c b/drivers/clk/mediatek/clk-mt7981.c index 7fcb81419cd..13dc3df0e9e 100644 --- a/drivers/clk/mediatek/clk-mt7981.c +++ b/drivers/clk/mediatek/clk-mt7981.c @@ -543,6 +543,7 @@ static const struct mtk_clk_tree mt7981_infracfg_clk_tree = { static const struct udevice_id mt7981_fixed_pll_compat[] = { { .compatible = "mediatek,mt7981-fixed-plls" }, + { .compatible = "mediatek,mt7981-apmixedsys" }, {} }; diff --git a/drivers/clk/mediatek/clk-mt7986.c b/drivers/clk/mediatek/clk-mt7986.c index b3fa63fc0ab..efc3d4120b7 100644 --- a/drivers/clk/mediatek/clk-mt7986.c +++ b/drivers/clk/mediatek/clk-mt7986.c @@ -533,6 +533,7 @@ static const struct mtk_clk_tree mt7986_infracfg_clk_tree = { static const struct udevice_id mt7986_fixed_pll_compat[] = { { .compatible = "mediatek,mt7986-fixed-plls" }, + { .compatible = "mediatek,mt7986-apmixedsys" }, {} }; diff --git a/drivers/clk/mediatek/clk-mt7988.c b/drivers/clk/mediatek/clk-mt7988.c index 34e7b2d734c..32b04511781 100644 --- a/drivers/clk/mediatek/clk-mt7988.c +++ b/drivers/clk/mediatek/clk-mt7988.c @@ -833,6 +833,7 @@ static const struct mtk_clk_tree mt7988_infracfg_clk_tree = { static const struct udevice_id mt7988_fixed_pll_compat[] = { { .compatible = "mediatek,mt7988-fixed-plls" }, + { .compatible = "mediatek,mt7988-apmixedsys" }, {} }; diff --git a/drivers/i2c/mtk_i2c.c b/drivers/i2c/mtk_i2c.c index 5592fe91817..3450177741a 100644 --- a/drivers/i2c/mtk_i2c.c +++ b/drivers/i2c/mtk_i2c.c @@ -221,6 +221,8 @@ struct mtk_i2c_priv { void __iomem *pdmabase; /* dma base address*/ struct clk clk_main; /* main clock for i2c bus */ struct clk clk_dma; /* DMA clock for i2c via DMA */ + struct clk clk_arb; /* DMA clock for i2c ARB */ + struct clk clk_pmic; /* DMA clock for i2c PMIC */ const struct mtk_i2c_soc_data *soc_data; /* Compatible data for different IC */ int op; /* operation mode */ bool zero_len; /* Only transfer slave address, no data */ @@ -255,6 +257,18 @@ static int mtk_i2c_clk_enable(struct mtk_i2c_priv *priv) if (ret) return log_msg_ret("enable clk_dma", ret); + if (priv->clk_arb.dev) { + ret = clk_enable(&priv->clk_arb); + if (ret) + return log_msg_ret("enable clk_arb", ret); + } + + if (priv->clk_pmic.dev) { + ret = clk_enable(&priv->clk_pmic); + if (ret) + return log_msg_ret("enable clk_pmic", ret); + } + return 0; } @@ -262,6 +276,18 @@ static int mtk_i2c_clk_disable(struct mtk_i2c_priv *priv) { int ret; + if (priv->clk_pmic.dev) { + ret = clk_disable(&priv->clk_pmic); + if (ret) + return log_msg_ret("disable clk_pmic", ret); + } + + if (priv->clk_arb.dev) { + ret = clk_disable(&priv->clk_arb); + if (ret) + return log_msg_ret("disable clk_arb", ret); + } + ret = clk_disable(&priv->clk_dma); if (ret) return log_msg_ret("disable clk_dma", ret); @@ -748,6 +774,10 @@ static int mtk_i2c_of_to_plat(struct udevice *dev) ret = clk_get_by_index(dev, 1, &priv->clk_dma); + /* optional i2c clock */ + clk_get_by_name(dev, "arb", &priv->clk_arb); + clk_get_by_name(dev, "pmic", &priv->clk_pmic); + return ret; } diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c index 3a9258255a7..ebd72178b59 100644 --- a/drivers/mmc/mtk-sd.c +++ b/drivers/mmc/mtk-sd.c @@ -335,6 +335,7 @@ struct msdc_compatible { bool enhance_rx; bool builtin_pad_ctrl; bool default_pad_dly; + bool use_internal_cd; }; struct msdc_delay_phase { @@ -365,6 +366,10 @@ struct msdc_host { struct clk src_clk_cg; /* optional, MSDC source clock control gate */ struct clk h_clk; /* MSDC core clock */ + /* upstream linux clock */ + struct clk axi_cg_clk; /* optional, AXI clock */ + struct clk ahb_cg_clk; /* optional, AHB clock */ + u32 src_clk_freq; /* source clock */ u32 mclk; /* mmc framework required bus clock */ u32 sclk; /* actual calculated bus clock */ @@ -1637,6 +1642,11 @@ static void msdc_ungate_clock(struct msdc_host *host) clk_enable(&host->h_clk); if (host->src_clk_cg.dev) clk_enable(&host->src_clk_cg); + + if (host->axi_cg_clk.dev) + clk_enable(&host->axi_cg_clk); + if (host->ahb_cg_clk.dev) + clk_enable(&host->ahb_cg_clk); } static int msdc_drv_probe(struct udevice *dev) @@ -1650,6 +1660,9 @@ static int msdc_drv_probe(struct udevice *dev) host->dev_comp = (struct msdc_compatible *)dev_get_driver_data(dev); + if (host->dev_comp->use_internal_cd) + host->builtin_cd = 1; + host->src_clk_freq = clk_get_rate(&host->src_clk); if (host->dev_comp->clk_div_bits == 8) @@ -1715,18 +1728,31 @@ static int msdc_of_to_plat(struct udevice *dev) clk_get_by_name(dev, "source_cg", &host->src_clk_cg); /* optional */ + /* upstream linux clock */ + clk_get_by_name(dev, "axi_cg", &host->axi_cg_clk); /* optional */ + clk_get_by_name(dev, "ahb_cg", &host->ahb_cg_clk); /* optional */ + #if CONFIG_IS_ENABLED(DM_GPIO) gpio_request_by_name(dev, "wp-gpios", 0, &host->gpio_wp, GPIOD_IS_IN); gpio_request_by_name(dev, "cd-gpios", 0, &host->gpio_cd, GPIOD_IS_IN); #endif host->hs400_ds_delay = dev_read_u32_default(dev, "hs400-ds-delay", 0); - host->hs200_cmd_int_delay = - dev_read_u32_default(dev, "cmd_int_delay", 0); + if (dev_read_u32(dev, "mediatek,hs200-cmd-int-delay", + &host->hs200_cmd_int_delay)) + host->hs200_cmd_int_delay = + dev_read_u32_default(dev, "cmd_int_delay", 0); + host->hs200_write_int_delay = dev_read_u32_default(dev, "write_int_delay", 0); - host->latch_ck = dev_read_u32_default(dev, "latch-ck", 0); + + if (dev_read_u32(dev, "mediatek,latch-ck", &host->latch_ck)) + host->latch_ck = dev_read_u32_default(dev, "latch-ck", 0); + host->r_smpl = dev_read_u32_default(dev, "r_smpl", 0); + if (dev_read_bool(dev, "mediatek,hs400-cmd-resp-sel-rising")) + host->r_smpl = 1; + host->builtin_cd = dev_read_u32_default(dev, "builtin-cd", 0); host->cd_active_high = dev_read_bool(dev, "cd-active-high"); @@ -1775,6 +1801,7 @@ static const struct msdc_compatible mt7620_compat = { .enhance_rx = false, .builtin_pad_ctrl = true, .default_pad_dly = true, + .use_internal_cd = true, }; static const struct msdc_compatible mt7621_compat = { @@ -1805,7 +1832,7 @@ static const struct msdc_compatible mt7623_compat = { .data_tune = true, .busy_check = false, .stop_clk_fix = false, - .enhance_rx = false + .enhance_rx = false, }; static const struct msdc_compatible mt7986_compat = { diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c index 94f17a97fe0..5098afef8a8 100644 --- a/drivers/net/mtk_eth.c +++ b/drivers/net/mtk_eth.c @@ -1964,7 +1964,9 @@ static int mtk_eth_of_to_plat(struct udevice *dev) return -ENODEV; } - priv->pn_swap = ofnode_read_bool(args.node, "pn_swap"); + /* Upstream linux use mediatek,pnswap instead of pn_swap */ + priv->pn_swap = ofnode_read_bool(args.node, "pn_swap") || + ofnode_read_bool(args.node, "mediatek,pnswap"); } else if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII) { /* get corresponding usxgmii phandle */ ret = dev_read_phandle_with_args(dev, "mediatek,usxgmiisys", 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/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/phy/Kconfig b/drivers/phy/Kconfig index 8f767877e73..e12347e8a03 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -263,6 +263,8 @@ config PHY_MTK_TPHY bool "MediaTek T-PHY Driver" depends on PHY depends on ARCH_MEDIATEK || SOC_MT7621 + select REGMAP + select SYSCON help MediaTek T-PHY driver supports usb2.0, usb3.0 ports, PCIe and SATA, and meanwhile supports two version T-PHY which have diff --git a/drivers/phy/phy-mtk-tphy.c b/drivers/phy/phy-mtk-tphy.c index 6f9ac1528e8..0a45dc58629 100644 --- a/drivers/phy/phy-mtk-tphy.c +++ b/drivers/phy/phy-mtk-tphy.c @@ -10,6 +10,8 @@ #include <generic-phy.h> #include <malloc.h> #include <mapmem.h> +#include <regmap.h> +#include <syscon.h> #include <asm/io.h> #include <dm/device_compat.h> #include <dm/devres.h> @@ -215,6 +217,14 @@ #define ANA_EQ_EYE_CTRL_SIGNAL5 0xdc #define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0) +/* PHY switch between pcie/usb3/sgmii/sata */ +#define USB_PHY_SWITCH_CTRL 0x0 +#define RG_PHY_SW_TYPE GENMASK(3, 0) +#define RG_PHY_SW_PCIE 0x0 +#define RG_PHY_SW_USB3 0x1 +#define RG_PHY_SW_SGMII 0x2 +#define RG_PHY_SW_SATA 0x3 + enum mtk_phy_version { MTK_TPHY_V1 = 1, MTK_TPHY_V2, @@ -257,6 +267,10 @@ struct mtk_phy_instance { u32 index; u32 type; + struct regmap *type_sw; + u32 type_sw_reg; + u32 type_sw_index; + u32 eye_vrt; u32 eye_term; u32 discth; @@ -616,6 +630,67 @@ static void u2_phy_props_set(struct mtk_tphy *tphy, FIELD_PREP(PA6_RG_U2_PRE_EMP, instance->pre_emphasis)); } +/* type switch for usb3/pcie/sgmii/sata */ +static int phy_type_syscon_get(struct udevice *dev, struct mtk_phy_instance *instance, + ofnode dn) +{ + struct ofnode_phandle_args args; + int err; + + if (!ofnode_read_bool(dn, "mediatek,syscon-type")) + return 0; + + err = ofnode_parse_phandle_with_args(dn, "mediatek,syscon-type", + NULL, 2, 0, &args); + if (err) + return err; + + instance->type_sw_reg = args.args[0]; + instance->type_sw_index = args.args[1] & 0x3; /* <=3 */ + instance->type_sw = syscon_node_to_regmap(args.node); + if (IS_ERR(instance->type_sw)) + return PTR_ERR(instance->type_sw); + + debug("phy-%s.%d: type_sw - reg %#x, index %d\n", + dev->name, instance->index, instance->type_sw_reg, + instance->type_sw_index); + + return 0; +} + +static int phy_type_set(struct mtk_phy_instance *instance) +{ + int type; + u32 offset; + + if (!instance->type_sw) + return 0; + + switch (instance->type) { + case PHY_TYPE_USB3: + type = RG_PHY_SW_USB3; + break; + case PHY_TYPE_PCIE: + type = RG_PHY_SW_PCIE; + break; + case PHY_TYPE_SGMII: + type = RG_PHY_SW_SGMII; + break; + case PHY_TYPE_SATA: + type = RG_PHY_SW_SATA; + break; + case PHY_TYPE_USB2: + default: + return 0; + } + + offset = instance->type_sw_index * BITS_PER_BYTE; + regmap_update_bits(instance->type_sw, instance->type_sw_reg, + RG_PHY_SW_TYPE << offset, type << offset); + + return 0; +} + static int mtk_phy_init(struct phy *phy) { struct mtk_tphy *tphy = dev_get_priv(phy->dev); @@ -746,6 +821,7 @@ static int mtk_phy_xlate(struct phy *phy, } phy_parse_property(tphy, instance); + phy_type_set(instance); return 0; } @@ -807,6 +883,10 @@ static int mtk_tphy_probe(struct udevice *dev) &instance->da_ref_clk); if (err) return err; + + err = phy_type_syscon_get(dev, instance, subnode); + if (err) + return err; } return 0; diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7981.c b/drivers/pinctrl/mediatek/pinctrl-mt7981.c index 3fa198ed79c..4bc4abe6518 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt7981.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt7981.c @@ -1050,4 +1050,5 @@ U_BOOT_DRIVER(mt7981_pinctrl) = { .ops = &mtk_pinctrl_ops, .probe = mtk_pinctrl_mt7981_probe, .priv_auto = sizeof(struct mtk_pinctrl_priv), + .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 37fc28bb779..ede3959c94f 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -761,6 +761,15 @@ static int mtk_gpiochip_register(struct udevice *parent) if (!drv) return -ENOENT; + /* + * Support upstream linux DTSI that define gpio-controller + * in the root node (instead of a dedicated subnode) + */ + if (dev_read_bool(parent, "gpio-controller")) { + node = dev_ofnode(parent); + goto bind; + } + ret = -ENOENT; dev_for_each_subnode(node, parent) if (ofnode_read_bool(node, "gpio-controller")) { @@ -771,6 +780,7 @@ static int mtk_gpiochip_register(struct udevice *parent) if (ret) return ret; +bind: ret = device_bind_with_driver_data(parent, &mtk_gpio_driver, "mediatek_gpio", 0, node, &dev); diff --git a/drivers/serial/serial_mtk.c b/drivers/serial/serial_mtk.c index 3f569c68f22..becf9317076 100644 --- a/drivers/serial/serial_mtk.c +++ b/drivers/serial/serial_mtk.c @@ -10,6 +10,7 @@ #include <config.h> #include <div64.h> #include <dm.h> +#include <dm/device.h> #include <dm/device_compat.h> #include <errno.h> #include <log.h> @@ -76,15 +77,19 @@ struct mtk_serial_regs { * driver * @regs: Register base of the serial port * @clk: The baud clock device + * @clk_bus: The bus clock device * @fixed_clk_rate: Fallback fixed baud clock rate if baud clock * device is not specified * @force_highspeed: Force using high-speed mode + * @upstream_highspeed_logic: Apply upstream high-speed logic */ struct mtk_serial_priv { struct mtk_serial_regs __iomem *regs; struct clk clk; + struct clk clk_bus; u32 fixed_clk_rate; bool force_highspeed; + bool upstream_highspeed_logic; }; static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud, @@ -111,7 +116,12 @@ static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud, goto set_baud; } - if (priv->force_highspeed) + /* + * Upstream linux use highspeed for anything >= 115200 and lowspeed + * for < 115200. Simulate this if we are using the upstream compatible. + */ + if (priv->force_highspeed || + (priv->upstream_highspeed_logic && baud >= 115200)) goto use_hs3; if (baud <= 115200) { @@ -220,6 +230,10 @@ static int mtk_serial_probe(struct udevice *dev) writel(UART_MCRVAL, &priv->regs->mcr); writel(UART_FCRVAL, &priv->regs->fcr); + clk_enable(&priv->clk); + if (priv->clk_bus.dev) + clk_enable(&priv->clk_bus); + return 0; } @@ -250,7 +264,11 @@ static int mtk_serial_of_to_plat(struct udevice *dev) } } + clk_get_by_name(dev, "bus", &priv->clk_bus); + priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed"); + priv->upstream_highspeed_logic = + device_is_compatible(dev, "mediatek,mt6577-uart"); return 0; } diff --git a/drivers/spi/mtk_spim.c b/drivers/spi/mtk_spim.c index 90f4c3cecb9..b360eca2b91 100644 --- a/drivers/spi/mtk_spim.c +++ b/drivers/spi/mtk_spim.c @@ -137,6 +137,8 @@ struct mtk_spim_capability { * @state: Controller state * @sel_clk: Pad clock * @spi_clk: Core clock + * @parent_clk: Parent clock (needed for mediatek,spi-ipm, upstream DTSI) + * @hclk: HCLK clock (needed for mediatek,spi-ipm, upstream DTSI) * @pll_clk_rate: Controller's PLL source clock rate, which is different * from SPI bus clock rate * @xfer_len: Current length of data for transfer @@ -151,6 +153,7 @@ struct mtk_spim_priv { void __iomem *base; u32 state; struct clk sel_clk, spi_clk; + struct clk parent_clk, hclk; u32 pll_clk_rate; u32 xfer_len; struct mtk_spim_capability hw_cap; @@ -650,7 +653,21 @@ static int mtk_spim_probe(struct udevice *dev) if (!priv->base) return -EINVAL; - mtk_spim_get_attr(priv, dev); + /* + * Upstream linux driver for ipm design enable all the modes + * and setup the calibrarion values directly in the driver with + * standard values. + */ + if (device_is_compatible(dev, "mediatek,spi-ipm")) { + priv->hw_cap.enhance_timing = true; + priv->hw_cap.dma_ext = true; + priv->hw_cap.ipm_design = true; + priv->hw_cap.support_quad = true; + priv->sample_sel = 0; + priv->tick_dly = 2; + } else { + mtk_spim_get_attr(priv, dev); + } ret = clk_get_by_name(dev, "sel-clk", &priv->sel_clk); if (ret < 0) { @@ -664,8 +681,31 @@ static int mtk_spim_probe(struct udevice *dev) return ret; } - clk_enable(&priv->sel_clk); + /* + * Upstream DTSI use a different compatible that provide additional + * clock instead of the assigned-clock implementation. + */ + if (device_is_compatible(dev, "mediatek,spi-ipm")) { + ret = clk_get_by_name(dev, "parent-clk", &priv->parent_clk); + if (ret < 0) { + dev_err(dev, "failed to get parent-clk\n"); + return ret; + } + + ret = clk_get_by_name(dev, "hclk", &priv->hclk); + if (ret < 0) { + dev_err(dev, "failed to get hclk\n"); + return ret; + } + + clk_enable(&priv->parent_clk); + clk_set_parent(&priv->sel_clk, &priv->parent_clk); + + clk_enable(&priv->hclk); + } + clk_enable(&priv->spi_clk); + clk_enable(&priv->sel_clk); priv->pll_clk_rate = clk_get_rate(&priv->spi_clk); if (priv->pll_clk_rate == 0) @@ -698,6 +738,7 @@ static const struct dm_spi_ops mtk_spim_ops = { static const struct udevice_id mtk_spim_ids[] = { { .compatible = "mediatek,ipm-spi" }, + { .compatible = "mediatek,spi-ipm", }, {} }; |