From patchwork Wed Apr 5 11:21:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Zink X-Patchwork-Id: 13201644 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 204D2C7619A for ; Wed, 5 Apr 2023 11:22:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=BwPWwoJ5PFLH7nA8Ee8AnIuKtv3DMj7uuEvzs1oSp8I=; b=SFoxT+gmv9e25h slTnxyxYeWX3/WDzciZn3CQb3Vc/gns10QmADBIOBkRkdBrHKZoFR3lK1pE8yoi/ofKhCc0s3COkd LFugzuPHfW/3+Eh21GTjDNebzx+K0n+iCQ4VwzgLG3Mx1vHjX9vHguEPexISEPacJe45VFxn4zcud RkK8ObeadsVd4R4f6YGbiDsWHC26PLjTSccZl1yq6CIKaEDFh/E0CjrNcrcbaooH/ZvInKmkxnSYJ 9xLhzzpdpFGtbYG9OhPgbxXcQ7tyHL84ilsjda8VOYDssXu7biyQ7tn7vp6O064mcnyDJgtpUJgeN Z4X8MPe1++w26cg8k3Hw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1pk1Cu-004FWS-3B; Wed, 05 Apr 2023 11:21:41 +0000 Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1pk1Cr-004FVQ-2C for linux-arm-kernel@lists.infradead.org; Wed, 05 Apr 2023 11:21:39 +0000 Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pk1Ce-0004S2-00; Wed, 05 Apr 2023 13:21:24 +0200 Received: from [2a0a:edc0:0:1101:1d::39] (helo=dude03.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1pk1Cc-0098SJ-2v; Wed, 05 Apr 2023 13:21:22 +0200 Received: from jzi by dude03.red.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1pk1Cb-005Gtt-BZ; Wed, 05 Apr 2023 13:21:21 +0200 From: Johannes Zink To: vkoul@kernel.org, kishon@kernel.org, shawnguo@kernel.org, s.hauer@pengutronix.de, kernel@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, jun.li@nxp.com, haibo.chen@nxp.com, linux-phy@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Cc: j.zink@pengutronix.de Subject: [PATCH 2/2] phy: fsl-imx8mp-usb: add support for phy tuning Date: Wed, 5 Apr 2023 13:21:18 +0200 Message-Id: <20230405112118.1256151-3-j.zink@pengutronix.de> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230405112118.1256151-1-j.zink@pengutronix.de> References: <20230405112118.1256151-1-j.zink@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: jzi@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-arm-kernel@lists.infradead.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230405_042137_721441_1853AA65 X-CRM114-Status: GOOD ( 15.74 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Li Jun Add USB PHY parameter tuning for USB certifications. Reviewed-by: Haibo Chen Signed-off-by: Li Jun [j.zink: ported to v6.3-rc1 from NXP downstream repo + cleanups] Signed-off-by: Johannes Zink --- drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 124 +++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c index a29b4a6f7c24..ee1975aaab7e 100644 --- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c @@ -27,17 +27,137 @@ #define PHY_CTRL2_TXENABLEN0 BIT(8) #define PHY_CTRL2_OTG_DISABLE BIT(9) +#define PHY_CTRL3 0xc +#define PHY_CTRL3_COMPDISTUNE_MASK GENMASK(2, 0) +#define PHY_CTRL3_TXPREEMP_TUNE_MASK GENMASK(16, 15) +#define PHY_CTRL3_TXRISE_TUNE_MASK GENMASK(21, 20) +#define PHY_CTRL3_TXVREF_TUNE_MASK GENMASK(25, 22) +#define PHY_CTRL3_TX_VBOOST_LEVEL_MASK GENMASK(31, 29) + +#define PHY_CTRL4 0x10 +#define PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(20, 15) + +#define PHY_CTRL5 0x14 +#define PHY_CTRL5_DMPWD_OVERRIDE_SEL BIT(23) +#define PHY_CTRL5_DMPWD_OVERRIDE BIT(22) +#define PHY_CTRL5_DPPWD_OVERRIDE_SEL BIT(21) +#define PHY_CTRL5_DPPWD_OVERRIDE BIT(20) +#define PHY_CTRL5_PCS_TX_SWING_FULL_MASK GENMASK(6, 0) + #define PHY_CTRL6 0x18 #define PHY_CTRL6_ALT_CLK_EN BIT(1) #define PHY_CTRL6_ALT_CLK_SEL BIT(0) +#define PHY_TUNE_DEFAULT 0xffffffff + struct imx8mq_usb_phy { struct phy *phy; struct clk *clk; void __iomem *base; struct regulator *vbus; + u32 pcs_tx_swing_full; + u32 pcs_tx_deemph_3p5db; + u32 tx_vref_tune; + u32 tx_rise_tune; + u32 tx_preemp_amp_tune; + u32 tx_vboost_level; + u32 comp_dis_tune; }; +static void imx8m_get_phy_tuning_data(struct imx8mq_usb_phy *imx_phy) +{ + struct device *dev = imx_phy->phy->dev.parent; + + if (device_property_read_u32(dev, "fsl,phy-tx-vref-tune", + &imx_phy->tx_vref_tune)) + imx_phy->tx_vref_tune = PHY_TUNE_DEFAULT; + + if (device_property_read_u32(dev, "fsl,phy-tx-rise-tune", + &imx_phy->tx_rise_tune)) + imx_phy->tx_rise_tune = PHY_TUNE_DEFAULT; + + if (device_property_read_u32(dev, "fsl,phy-tx-preemp-amp-tune", + &imx_phy->tx_preemp_amp_tune)) + imx_phy->tx_preemp_amp_tune = PHY_TUNE_DEFAULT; + + if (device_property_read_u32(dev, "fsl,phy-tx-vboost-level", + &imx_phy->tx_vboost_level)) + imx_phy->tx_vboost_level = PHY_TUNE_DEFAULT; + + if (device_property_read_u32(dev, "fsl,phy-comp-dis-tune", + &imx_phy->comp_dis_tune)) + imx_phy->comp_dis_tune = PHY_TUNE_DEFAULT; + + if (device_property_read_u32(dev, "fsl,pcs-tx-deemph-3p5db", + &imx_phy->pcs_tx_deemph_3p5db)) + imx_phy->pcs_tx_deemph_3p5db = PHY_TUNE_DEFAULT; + + if (device_property_read_u32(dev, "fsl,phy-pcs-tx-swing-full", + &imx_phy->pcs_tx_swing_full)) + imx_phy->pcs_tx_swing_full = PHY_TUNE_DEFAULT; +} + +static void imx8m_phy_tune(struct imx8mq_usb_phy *imx_phy) +{ + u32 value; + + /* PHY tuning */ + if (imx_phy->pcs_tx_deemph_3p5db != PHY_TUNE_DEFAULT) { + value = readl(imx_phy->base + PHY_CTRL4); + value &= ~PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK; + value |= FIELD_PREP(PHY_CTRL4_PCS_TX_DEEMPH_3P5DB_MASK, + imx_phy->pcs_tx_deemph_3p5db); + writel(value, imx_phy->base + PHY_CTRL4); + } + + if (imx_phy->pcs_tx_swing_full != PHY_TUNE_DEFAULT) { + value = readl(imx_phy->base + PHY_CTRL5); + value |= FIELD_PREP(PHY_CTRL5_PCS_TX_SWING_FULL_MASK, + imx_phy->pcs_tx_swing_full); + writel(value, imx_phy->base + PHY_CTRL5); + } + + if ((imx_phy->tx_vref_tune & imx_phy->tx_rise_tune & + imx_phy->tx_preemp_amp_tune & imx_phy->comp_dis_tune & + imx_phy->tx_vboost_level) == PHY_TUNE_DEFAULT) + /* If all are the default values, no need update. */ + return; + + value = readl(imx_phy->base + PHY_CTRL3); + + if (imx_phy->tx_vref_tune != PHY_TUNE_DEFAULT) { + value &= ~PHY_CTRL3_TXVREF_TUNE_MASK; + value |= FIELD_PREP(PHY_CTRL3_TXVREF_TUNE_MASK, + imx_phy->tx_vref_tune); + } + + if (imx_phy->tx_rise_tune != PHY_TUNE_DEFAULT) { + value &= ~PHY_CTRL3_TXRISE_TUNE_MASK; + value |= FIELD_PREP(PHY_CTRL3_TXRISE_TUNE_MASK, + imx_phy->tx_rise_tune); + } + + if (imx_phy->tx_preemp_amp_tune != PHY_TUNE_DEFAULT) { + value &= ~PHY_CTRL3_TXPREEMP_TUNE_MASK; + value |= FIELD_PREP(PHY_CTRL3_TXPREEMP_TUNE_MASK, + imx_phy->tx_preemp_amp_tune); + } + + if (imx_phy->comp_dis_tune != PHY_TUNE_DEFAULT) { + value &= ~PHY_CTRL3_COMPDISTUNE_MASK; + value |= FIELD_PREP(PHY_CTRL3_COMPDISTUNE_MASK, + imx_phy->comp_dis_tune); + } + + if (imx_phy->tx_vboost_level != PHY_TUNE_DEFAULT) { + value &= ~PHY_CTRL3_TX_VBOOST_LEVEL_MASK; + value |= FIELD_PREP(PHY_CTRL3_TX_VBOOST_LEVEL_MASK, + imx_phy->tx_vboost_level); + } + + writel(value, imx_phy->base + PHY_CTRL3); +} + static int imx8mq_usb_phy_init(struct phy *phy) { struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); @@ -99,6 +219,8 @@ static int imx8mp_usb_phy_init(struct phy *phy) value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET); writel(value, imx_phy->base + PHY_CTRL1); + imx8m_phy_tune(imx_phy); + return 0; } @@ -182,6 +304,8 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev) phy_set_drvdata(imx_phy->phy, imx_phy); + imx8m_get_phy_tuning_data(imx_phy); + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); return PTR_ERR_OR_ZERO(phy_provider);