From patchwork Wed Aug 28 06:37:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?V2VpamllIEdhbyAo6auY5oOf5p2wKQ==?= X-Patchwork-Id: 1154230 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=mediatek.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46JGcW2vMgz9sN6 for ; Wed, 28 Aug 2019 16:51:39 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id E8984C21EBE; Wed, 28 Aug 2019 06:40:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: * X-Spam-Status: No, score=1.3 required=5.0 tests=RDNS_NONE, UNPARSEABLE_RELAY autolearn=no autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id AE038C21F1A; Wed, 28 Aug 2019 06:39:49 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 83C38C21E7E; Wed, 28 Aug 2019 06:39:22 +0000 (UTC) Received: from mailgw02.mediatek.com (unknown [1.203.163.81]) by lists.denx.de (Postfix) with ESMTP id 9CB42C21EC2 for ; Wed, 28 Aug 2019 06:39:18 +0000 (UTC) X-UUID: 6bbcb9e658ca4a708e2cff4d11f1263f-20190828 X-UUID: 6bbcb9e658ca4a708e2cff4d11f1263f-20190828 Received: from mtkcas32.mediatek.inc [(172.27.4.253)] by mailgw02.mediatek.com (envelope-from ) (mailgw01.mediatek.com ESMTP with TLS) with ESMTP id 30058769; Wed, 28 Aug 2019 14:39:17 +0800 Received: from MTKCAS36.mediatek.inc (172.27.4.186) by MTKMBS31DR.mediatek.inc (172.27.6.102) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Wed, 28 Aug 2019 14:39:16 +0800 Received: from mcddlt001.mediatek.inc (172.27.4.253) by MTKCAS36.mediatek.inc (172.27.4.170) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Wed, 28 Aug 2019 14:39:15 +0800 From: Weijie Gao To: Date: Wed, 28 Aug 2019 14:37:59 +0800 Message-ID: <1566974291-11750-15-git-send-email-weijie.gao@mediatek.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1566974291-11750-1-git-send-email-weijie.gao@mediatek.com> References: <1566974291-11750-1-git-send-email-weijie.gao@mediatek.com> MIME-Version: 1.0 X-TM-SNTS-SMTP: F1D33C8F4DCD50590E0E2C1BC47B05A3E3E3D436C99EB24B7A6B19BF0CE843242000:8 X-MTK: N Cc: Tom Rini , Joe Hershberger , Stefan Roese , GSS_MTK_Uboot_upstream Subject: [U-Boot] [PATCH 14/26] phy: mt76x8-usb-phy: add slew rate calibration and remove non-mt7628 part X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch adds slew rate calibration for mt76x8-usb-phy, removes code which belongs to mt7620, and gets rid of using syscon and regmap by using clock driver and reset controller. Signed-off-by: Weijie Gao --- drivers/phy/Kconfig | 2 + drivers/phy/mt76x8-usb-phy.c | 225 ++++++++++++++++++++++++----------- 2 files changed, 159 insertions(+), 68 deletions(-) diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 02312273e2..5c7b221431 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -200,6 +200,8 @@ config KEYSTONE_USB_PHY config MT76X8_USB_PHY bool "MediaTek MT76x8 (7628/88) USB PHY support" depends on PHY + select CLK + select DM_RESET help Support the USB PHY in MT76x8 SoCs diff --git a/drivers/phy/mt76x8-usb-phy.c b/drivers/phy/mt76x8-usb-phy.c index 268da8ef6c..1e7c5f334b 100644 --- a/drivers/phy/mt76x8-usb-phy.c +++ b/drivers/phy/mt76x8-usb-phy.c @@ -6,93 +6,185 @@ * Copyright (C) 2017 John Crispin */ +#include #include #include #include -#include -#include -#include +#include #include - -#define RT_SYSC_REG_SYSCFG1 0x014 -#define RT_SYSC_REG_CLKCFG1 0x030 -#define RT_SYSC_REG_USB_PHY_CFG 0x05c +#include #define OFS_U2_PHY_AC0 0x800 +#define USBPLL_FBDIV_S 16 +#define USBPLL_FBDIV_M GENMASK(22, 16) +#define BG_TRIM_S 8 +#define BG_TRIM_M GENMASK(11, 8) +#define BG_RBSEL_S 6 +#define BG_RBSEL_M GENMASK(7, 6) +#define BG_RASEL_S 4 +#define BG_RASEL_M GENMASK(5, 4) +#define BGR_DIV_S 2 +#define BGR_DIV_M GENMASK(3, 2) +#define CHP_EN BIT(1) + #define OFS_U2_PHY_AC1 0x804 +#define VRT_VREF_SEL_S 28 +#define VRT_VREF_SEL_M GENMASK(30, 28) +#define TERM_VREF_SEL_S 24 +#define TERM_VREF_SEL_M GENMASK(26, 24) +#define USBPLL_RSVD BIT(4) +#define USBPLL_ACCEN BIT(3) +#define USBPLL_LF BIT(2) + #define OFS_U2_PHY_AC2 0x808 + #define OFS_U2_PHY_ACR0 0x810 -#define OFS_U2_PHY_ACR1 0x814 -#define OFS_U2_PHY_ACR2 0x818 +#define HSTX_SRCAL_EN BIT(23) +#define HSTX_SRCTRL_S 16 +#define HSTX_SRCTRL_M GENMASK(18, 16) + #define OFS_U2_PHY_ACR3 0x81C -#define OFS_U2_PHY_ACR4 0x820 -#define OFS_U2_PHY_AMON0 0x824 +#define HSTX_DBIST_S 28 +#define HSTX_DBIST_M GENMASK(31, 28) +#define HSRX_BIAS_EN_SEL_S 20 +#define HSRX_BIAS_EN_SEL_M GENMASK(21, 20) + #define OFS_U2_PHY_DCR0 0x860 -#define OFS_U2_PHY_DCR1 0x864 +#define PHYD_RESERVE_S 8 +#define PHYD_RESERVE_M GENMASK(23, 8) +#define CDR_FILT_S 0 +#define CDR_FILT_M GENMASK(3, 0) + #define OFS_U2_PHY_DTM0 0x868 -#define OFS_U2_PHY_DTM1 0x86C +#define FORCE_USB_CLKEN BIT(25) + +#define OFS_FM_CR0 0xf00 +#define FREQDET_EN BIT(24) +#define CYCLECNT_S 0 +#define CYCLECNT_M GENMASK(23, 0) -#define RT_RSTCTRL_UDEV BIT(25) -#define RT_RSTCTRL_UHST BIT(22) -#define RT_SYSCFG1_USB0_HOST_MODE BIT(10) +#define OFS_FM_MONR0 0xf0c -#define MT7620_CLKCFG1_UPHY0_CLK_EN BIT(25) -#define MT7620_CLKCFG1_UPHY1_CLK_EN BIT(22) -#define RT_CLKCFG1_UPHY1_CLK_EN BIT(20) -#define RT_CLKCFG1_UPHY0_CLK_EN BIT(18) +#define OFS_FM_MONR1 0xf10 +#define FRCK_EN BIT(8) -#define USB_PHY_UTMI_8B60M BIT(1) -#define UDEV_WAKEUP BIT(0) +#define U2_SR_COEF_7628 32 struct mt76x8_usb_phy { - u32 clk; void __iomem *base; - struct regmap *sysctl; + struct clk cg; /* for clock gating */ + struct reset_ctl rst_phy; }; -static void u2_phy_w32(struct mt76x8_usb_phy *phy, u32 val, u32 reg) +static void phy_w32(struct mt76x8_usb_phy *phy, u32 reg, u32 val) { writel(val, phy->base + reg); } -static u32 u2_phy_r32(struct mt76x8_usb_phy *phy, u32 reg) +static u32 phy_r32(struct mt76x8_usb_phy *phy, u32 reg) { return readl(phy->base + reg); } +static void phy_rmw32(struct mt76x8_usb_phy *phy, u32 reg, u32 clr, u32 set) +{ + clrsetbits_32(phy->base + reg, clr, set); +} + static void mt76x8_usb_phy_init(struct mt76x8_usb_phy *phy) { - u2_phy_r32(phy, OFS_U2_PHY_AC2); - u2_phy_r32(phy, OFS_U2_PHY_ACR0); - u2_phy_r32(phy, OFS_U2_PHY_DCR0); - - u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0); - u2_phy_r32(phy, OFS_U2_PHY_DCR0); - u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0); - u2_phy_r32(phy, OFS_U2_PHY_DCR0); - u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0); - u2_phy_r32(phy, OFS_U2_PHY_DCR0); - u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0); - u2_phy_r32(phy, OFS_U2_PHY_DCR0); - u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0); - u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1); - u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3); - u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0); + phy_r32(phy, OFS_U2_PHY_AC2); + phy_r32(phy, OFS_U2_PHY_ACR0); + phy_r32(phy, OFS_U2_PHY_DCR0); + + phy_w32(phy, OFS_U2_PHY_DCR0, + (0xffff << PHYD_RESERVE_S) | (2 << CDR_FILT_S)); + phy_r32(phy, OFS_U2_PHY_DCR0); + + phy_w32(phy, OFS_U2_PHY_DCR0, + (0x5555 << PHYD_RESERVE_S) | (2 << CDR_FILT_S)); + phy_r32(phy, OFS_U2_PHY_DCR0); + + phy_w32(phy, OFS_U2_PHY_DCR0, + (0xaaaa << PHYD_RESERVE_S) | (2 << CDR_FILT_S)); + phy_r32(phy, OFS_U2_PHY_DCR0); + + phy_w32(phy, OFS_U2_PHY_DCR0, + (4 << PHYD_RESERVE_S) | (2 << CDR_FILT_S)); + phy_r32(phy, OFS_U2_PHY_DCR0); + + phy_w32(phy, OFS_U2_PHY_AC0, + (0x48 << USBPLL_FBDIV_S) | (8 << BG_TRIM_S) | + (1 << BG_RBSEL_S) | (2 << BG_RASEL_S) | (2 << BGR_DIV_S) | + CHP_EN); + + phy_w32(phy, OFS_U2_PHY_AC1, + (4 << VRT_VREF_SEL_S) | (4 << TERM_VREF_SEL_S) | USBPLL_RSVD | + USBPLL_ACCEN | USBPLL_LF); + + phy_w32(phy, OFS_U2_PHY_ACR3, + (12 << HSTX_DBIST_S) | (2 << HSRX_BIAS_EN_SEL_S)); + + phy_w32(phy, OFS_U2_PHY_DTM0, FORCE_USB_CLKEN); +} + +static void mt76x8_usb_phy_sr_calibrate(struct mt76x8_usb_phy *phy) +{ + u32 fmout, tmp = 4; + int i; + + /* Enable HS TX SR calibration */ + phy_rmw32(phy, OFS_U2_PHY_ACR0, 0, HSTX_SRCAL_EN); + mdelay(1); + + /* Enable free run clock */ + phy_rmw32(phy, OFS_FM_MONR1, 0, FRCK_EN); + + /* Set cycle count = 0x400 */ + phy_rmw32(phy, OFS_FM_CR0, CYCLECNT_M, 0x400 << CYCLECNT_S); + + /* Enable frequency meter */ + phy_rmw32(phy, OFS_FM_CR0, 0, FREQDET_EN); + + /* Wait for FM detection done, set timeout to 10ms */ + for (i = 0; i < 10; i++) { + fmout = phy_r32(phy, OFS_FM_MONR0); + + if (fmout) + break; + + mdelay(1); + } + + /* Disable frequency meter */ + phy_rmw32(phy, OFS_FM_CR0, FREQDET_EN, 0); + + /* Disable free run clock */ + phy_rmw32(phy, OFS_FM_MONR1, FRCK_EN, 0); + + /* Disable HS TX SR calibration */ + phy_rmw32(phy, OFS_U2_PHY_ACR0, HSTX_SRCAL_EN, 0); + mdelay(1); + + if (fmout) { + /* + * set reg = (1024 / FM_OUT) * 25 * 0.028 + * (round to the nearest digits) + */ + tmp = (((1024 * 25 * U2_SR_COEF_7628) / fmout) + 500) / 1000; + } + + phy_rmw32(phy, OFS_U2_PHY_ACR0, HSTX_SRCTRL_M, + (tmp << HSTX_SRCTRL_S) & HSTX_SRCTRL_M); } static int mt76x8_usb_phy_power_on(struct phy *_phy) { struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev); - u32 t; - /* enable the phy */ - regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1, - phy->clk, phy->clk); + clk_enable(&phy->cg); - /* setup host mode */ - regmap_update_bits(phy->sysctl, RT_SYSC_REG_SYSCFG1, - RT_SYSCFG1_USB0_HOST_MODE, - RT_SYSCFG1_USB0_HOST_MODE); + reset_deassert(&phy->rst_phy); /* * The SDK kernel had a delay of 100ms. however on device @@ -100,17 +192,8 @@ static int mt76x8_usb_phy_power_on(struct phy *_phy) */ mdelay(10); - if (phy->base) - mt76x8_usb_phy_init(phy); - - /* print some status info */ - regmap_read(phy->sysctl, RT_SYSC_REG_USB_PHY_CFG, &t); - printf("remote usb device wakeup %s\n", - (t & UDEV_WAKEUP) ? "enabled" : "disabled"); - if (t & USB_PHY_UTMI_8B60M) - printf("UTMI 8bit 60MHz\n"); - else - printf("UTMI 16bit 30MHz\n"); + mt76x8_usb_phy_init(phy); + mt76x8_usb_phy_sr_calibrate(phy); return 0; } @@ -119,9 +202,9 @@ static int mt76x8_usb_phy_power_off(struct phy *_phy) { struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev); - /* disable the phy */ - regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1, - phy->clk, 0); + clk_disable(&phy->cg); + + reset_assert(&phy->rst_phy); return 0; } @@ -129,15 +212,21 @@ static int mt76x8_usb_phy_power_off(struct phy *_phy) static int mt76x8_usb_phy_probe(struct udevice *dev) { struct mt76x8_usb_phy *phy = dev_get_priv(dev); - - phy->sysctl = syscon_regmap_lookup_by_phandle(dev, "ralink,sysctl"); - if (IS_ERR(phy->sysctl)) - return PTR_ERR(phy->sysctl); + int ret; phy->base = dev_read_addr_ptr(dev); if (!phy->base) return -EINVAL; + /* clock gate */ + ret = clk_get_by_name(dev, "cg", &phy->cg); + if (ret) + return ret; + + ret = reset_get_by_name(dev, "phy", &phy->rst_phy); + if (ret) + return ret; + return 0; }