diff options
Diffstat (limited to 'drivers/phy/mediatek')
-rw-r--r-- | drivers/phy/mediatek/Makefile | 1 | ||||
-rw-r--r-- | drivers/phy/mediatek/phy-mtk-tphy.c | 85 |
2 files changed, 77 insertions, 9 deletions
diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile index e5074b607d3d..ee49edc97ee9 100644 --- a/drivers/phy/mediatek/Makefile +++ b/drivers/phy/mediatek/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Makefile for the phy drivers. # diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c index 38c281b5abbb..3eb8e1bd7b78 100644 --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2015 MediaTek Inc. * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <dt-bindings/phy/phy.h> @@ -50,6 +42,12 @@ #define PA0_RG_U2PLL_FORCE_ON BIT(15) #define PA0_RG_USB20_INTR_EN BIT(5) +#define U3P_USBPHYACR1 0x004 +#define PA1_RG_VRT_SEL GENMASK(14, 12) +#define PA1_RG_VRT_SEL_VAL(x) ((0x7 & (x)) << 12) +#define PA1_RG_TERM_SEL GENMASK(10, 8) +#define PA1_RG_TERM_SEL_VAL(x) ((0x7 & (x)) << 8) + #define U3P_USBPHYACR2 0x008 #define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18) @@ -103,6 +101,9 @@ #define P2C_RG_AVALID BIT(2) #define P2C_RG_IDDIG BIT(1) +#define U3P_U2PHYBC12C 0x080 +#define P2C_RG_CHGDT_EN BIT(0) + #define U3P_U3_CHIP_GPIO_CTLD 0x0c #define P3C_REG_IP_SW_RST BIT(31) #define P3C_MCU_BUS_CK_GATE_EN BIT(30) @@ -296,6 +297,10 @@ struct mtk_phy_instance { struct clk *ref_clk; /* reference clock of anolog phy */ u32 index; u8 type; + int eye_src; + int eye_vrt; + int eye_term; + bool bc12_en; }; struct mtk_tphy { @@ -320,6 +325,10 @@ static void hs_slew_rate_calibrate(struct mtk_tphy *tphy, int fm_out; u32 tmp; + /* use force value */ + if (instance->eye_src) + return; + /* enable USB ring oscillator */ tmp = readl(com + U3P_USBPHYACR5); tmp |= PA5_RG_U2_HSTX_SRCAL_EN; @@ -826,6 +835,61 @@ static void phy_v2_banks_init(struct mtk_tphy *tphy, } } +static void phy_parse_property(struct mtk_tphy *tphy, + struct mtk_phy_instance *instance) +{ + struct device *dev = &instance->phy->dev; + + if (instance->type != PHY_TYPE_USB2) + return; + + instance->bc12_en = device_property_read_bool(dev, "mediatek,bc12"); + device_property_read_u32(dev, "mediatek,eye-src", + &instance->eye_src); + device_property_read_u32(dev, "mediatek,eye-vrt", + &instance->eye_vrt); + device_property_read_u32(dev, "mediatek,eye-term", + &instance->eye_term); + dev_dbg(dev, "bc12:%d, src:%d, vrt:%d, term:%d\n", + instance->bc12_en, instance->eye_src, + instance->eye_vrt, instance->eye_term); +} + +static void u2_phy_props_set(struct mtk_tphy *tphy, + struct mtk_phy_instance *instance) +{ + struct u2phy_banks *u2_banks = &instance->u2_banks; + void __iomem *com = u2_banks->com; + u32 tmp; + + if (instance->bc12_en) { + tmp = readl(com + U3P_U2PHYBC12C); + tmp |= P2C_RG_CHGDT_EN; /* BC1.2 path Enable */ + writel(tmp, com + U3P_U2PHYBC12C); + } + + if (instance->eye_src) { + tmp = readl(com + U3P_USBPHYACR5); + tmp &= ~PA5_RG_U2_HSTX_SRCTRL; + tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(instance->eye_src); + writel(tmp, com + U3P_USBPHYACR5); + } + + if (instance->eye_vrt) { + tmp = readl(com + U3P_USBPHYACR1); + tmp &= ~PA1_RG_VRT_SEL; + tmp |= PA1_RG_VRT_SEL_VAL(instance->eye_vrt); + writel(tmp, com + U3P_USBPHYACR1); + } + + if (instance->eye_term) { + tmp = readl(com + U3P_USBPHYACR1); + tmp &= ~PA1_RG_TERM_SEL; + tmp |= PA1_RG_TERM_SEL_VAL(instance->eye_term); + writel(tmp, com + U3P_USBPHYACR1); + } +} + static int mtk_phy_init(struct phy *phy) { struct mtk_phy_instance *instance = phy_get_drvdata(phy); @@ -847,6 +911,7 @@ static int mtk_phy_init(struct phy *phy) switch (instance->type) { case PHY_TYPE_USB2: u2_phy_instance_init(tphy, instance); + u2_phy_props_set(tphy, instance); break; case PHY_TYPE_USB3: u3_phy_instance_init(tphy, instance); @@ -959,6 +1024,8 @@ static struct phy *mtk_phy_xlate(struct device *dev, return ERR_PTR(-EINVAL); } + phy_parse_property(tphy, instance); + return instance->phy; } |