All of lore.kernel.org
 help / color / mirror / Atom feed
From: Douglas Anderson <dianders@chromium.org>
To: ulf.hansson@linaro.org, kishon@ti.com,
	Heiko Stuebner <heiko@sntech.de>,
	robh+dt@kernel.org
Cc: shawn.lin@rock-chips.com, xzy.xu@rock-chips.com,
	briannorris@chromium.org, adrian.hunter@intel.com,
	linux-rockchip@lists.infradead.org, linux-mmc@vger.kernel.org,
	devicetree@vger.kernel.org,
	Douglas Anderson <dianders@chromium.org>,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Subject: [PATCH 09/11] phy: rockchip-emmc: Set phyctrl_frqsel based on card clock
Date: Tue,  7 Jun 2016 15:44:42 -0700	[thread overview]
Message-ID: <1465339484-969-10-git-send-email-dianders@chromium.org> (raw)
In-Reply-To: <1465339484-969-1-git-send-email-dianders@chromium.org>

The "phyctrl_frqsel" is described in the Arasan datasheet [1] as "the
frequency range of DLL operation".  Although the Rockchip variant of
this PHY has different ranges than the reference Arasan PHY it appears
as if the functionality is similar.  We should set this phyctrl field
properly.

Note: as per Rockchip engineers, apparently the "phyctrl_frqsel" is
actually only useful in HS200 / HS400 modes even though the DLL itself
it used for some purposes in all modes.  See the discussion in the
earlier change in this series: ("mmc: sdhci-of-arasan: Always power the
PHY off/on when clock changes").  In any case, it shouldn't hurt to set
this always.

Note that this change should allow boards to run at HS200 / HS400 speed
modes while running at 100 MHz or 150 MHz.  In fact, running HS400 at
150 MHz (giving 300 MB/s) is the main motivation of this series, since
performance is still good but signal integrity problems are less
prevelant at 150 MHz.

[1]: https://arasan.com/wp-content/media/eMMC-5-1-Total-Solution_Rev-1-3.pdf

Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
 drivers/phy/phy-rockchip-emmc.c | 74 +++++++++++++++++++++++++++++++----------
 1 file changed, 57 insertions(+), 17 deletions(-)

diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c
index 8336053aea5c..0fce7359d468 100644
--- a/drivers/phy/phy-rockchip-emmc.c
+++ b/drivers/phy/phy-rockchip-emmc.c
@@ -14,6 +14,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
@@ -78,16 +79,61 @@
 struct rockchip_emmc_phy {
 	unsigned int	reg_offset;
 	struct regmap	*reg_base;
+	struct clk	*emmcclk;
 };
 
-static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,
-				   bool on_off)
+static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
 {
+	struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
 	unsigned int caldone;
 	unsigned int dllrdy;
+	unsigned int freqsel = PHYCTRL_FREQSEL_200M;
 	unsigned long timeout;
 
 	/*
+	 * We purposely get the clock here and not in probe to avoid the
+	 * circular dependency problem.  We expect:
+	 * - PHY driver to probe
+	 * - USB driver to start probe
+	 * - USB driver to register it's clock
+	 * - USB driver to get the PHY
+	 * - USB driver to power on the PHY
+	 */
+	if (!rk_phy->emmcclk) {
+		rk_phy->emmcclk = devm_clk_get(&phy->dev, "emmcclk");
+
+		/* Don't expect defer at this point; try next time */
+		if (PTR_ERR(rk_phy->emmcclk) == -EPROBE_DEFER) {
+			dev_warn(&phy->dev, "Unexpected emmcclk defer\n");
+			rk_phy->emmcclk = NULL;
+		}
+	}
+
+	if (!IS_ERR_OR_NULL(rk_phy->emmcclk)) {
+		unsigned long rate = clk_get_rate(rk_phy->emmcclk);
+
+		switch (rate) {
+		case 0 ... 74999999:
+			/* Nominal  50 MHz */
+			freqsel = PHYCTRL_FREQSEL_50M;
+			break;
+		case 75000000 ... 124999999:
+			/* Nominal 100 MHz */
+			freqsel = PHYCTRL_FREQSEL_100M;
+			break;
+		case 125000000 ... 174999999:
+			/* Nominal 150 MHz */
+			freqsel = PHYCTRL_FREQSEL_150M;
+			break;
+		default:
+			if (rate > 200000000)
+				dev_warn(&phy->dev, "Unsupported rate: %lu\n",
+					 rate);
+			break;
+		};
+	}
+
+	/*
 	 * Keep phyctrl_pdb and phyctrl_endll low to allow
 	 * initialization of CALIO state M/C DFFs
 	 */
@@ -132,6 +178,13 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,
 		return -ETIMEDOUT;
 	}
 
+	/* Set the frequency of the DLL operation */
+	regmap_write(rk_phy->reg_base,
+		     rk_phy->reg_offset + GRF_EMMCPHY_CON0,
+		     HIWORD_UPDATE(freqsel, PHYCTRL_FREQSEL_MASK,
+				   PHYCTRL_FREQSEL_SHIFT));
+
+	/* Turn on the DLL */
 	regmap_write(rk_phy->reg_base,
 		     rk_phy->reg_offset + GRF_EMMCPHY_CON6,
 		     HIWORD_UPDATE(PHYCTRL_ENDLL_ENABLE,
@@ -167,15 +220,8 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,
 
 static int rockchip_emmc_phy_power_off(struct phy *phy)
 {
-	struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
-	int ret = 0;
-
 	/* Power down emmc phy analog blocks */
-	ret = rockchip_emmc_phy_power(rk_phy, PHYCTRL_PDB_PWR_OFF);
-	if (ret)
-		return ret;
-
-	return 0;
+	return rockchip_emmc_phy_power(phy, PHYCTRL_PDB_PWR_OFF);
 }
 
 static int rockchip_emmc_phy_power_on(struct phy *phy)
@@ -183,12 +229,6 @@ static int rockchip_emmc_phy_power_on(struct phy *phy)
 	struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
 	int ret = 0;
 
-	/* DLL operation: 200 MHz */
-	regmap_write(rk_phy->reg_base,
-		     rk_phy->reg_offset + GRF_EMMCPHY_CON0,
-		     HIWORD_UPDATE(PHYCTRL_FREQSEL_200M,
-				   PHYCTRL_FREQSEL_MASK,
-				   PHYCTRL_FREQSEL_SHIFT));
 
 	/* Drive impedance: 50 Ohm */
 	regmap_write(rk_phy->reg_base,
@@ -212,7 +252,7 @@ static int rockchip_emmc_phy_power_on(struct phy *phy)
 				   PHYCTRL_OTAPDLYSEL_SHIFT));
 
 	/* Power up emmc phy analog blocks */
-	ret = rockchip_emmc_phy_power(rk_phy, PHYCTRL_PDB_PWR_ON);
+	ret = rockchip_emmc_phy_power(phy, PHYCTRL_PDB_PWR_ON);
 	if (ret)
 		return ret;
 
-- 
2.8.0.rc3.226.g39d4020

WARNING: multiple messages have this Message-ID (diff)
From: dianders@chromium.org (Douglas Anderson)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 09/11] phy: rockchip-emmc: Set phyctrl_frqsel based on card clock
Date: Tue,  7 Jun 2016 15:44:42 -0700	[thread overview]
Message-ID: <1465339484-969-10-git-send-email-dianders@chromium.org> (raw)
In-Reply-To: <1465339484-969-1-git-send-email-dianders@chromium.org>

The "phyctrl_frqsel" is described in the Arasan datasheet [1] as "the
frequency range of DLL operation".  Although the Rockchip variant of
this PHY has different ranges than the reference Arasan PHY it appears
as if the functionality is similar.  We should set this phyctrl field
properly.

Note: as per Rockchip engineers, apparently the "phyctrl_frqsel" is
actually only useful in HS200 / HS400 modes even though the DLL itself
it used for some purposes in all modes.  See the discussion in the
earlier change in this series: ("mmc: sdhci-of-arasan: Always power the
PHY off/on when clock changes").  In any case, it shouldn't hurt to set
this always.

Note that this change should allow boards to run at HS200 / HS400 speed
modes while running at 100 MHz or 150 MHz.  In fact, running HS400 at
150 MHz (giving 300 MB/s) is the main motivation of this series, since
performance is still good but signal integrity problems are less
prevelant at 150 MHz.

[1]: https://arasan.com/wp-content/media/eMMC-5-1-Total-Solution_Rev-1-3.pdf

Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
 drivers/phy/phy-rockchip-emmc.c | 74 +++++++++++++++++++++++++++++++----------
 1 file changed, 57 insertions(+), 17 deletions(-)

diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c
index 8336053aea5c..0fce7359d468 100644
--- a/drivers/phy/phy-rockchip-emmc.c
+++ b/drivers/phy/phy-rockchip-emmc.c
@@ -14,6 +14,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
@@ -78,16 +79,61 @@
 struct rockchip_emmc_phy {
 	unsigned int	reg_offset;
 	struct regmap	*reg_base;
+	struct clk	*emmcclk;
 };
 
-static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,
-				   bool on_off)
+static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
 {
+	struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
 	unsigned int caldone;
 	unsigned int dllrdy;
+	unsigned int freqsel = PHYCTRL_FREQSEL_200M;
 	unsigned long timeout;
 
 	/*
+	 * We purposely get the clock here and not in probe to avoid the
+	 * circular dependency problem.  We expect:
+	 * - PHY driver to probe
+	 * - USB driver to start probe
+	 * - USB driver to register it's clock
+	 * - USB driver to get the PHY
+	 * - USB driver to power on the PHY
+	 */
+	if (!rk_phy->emmcclk) {
+		rk_phy->emmcclk = devm_clk_get(&phy->dev, "emmcclk");
+
+		/* Don't expect defer at this point; try next time */
+		if (PTR_ERR(rk_phy->emmcclk) == -EPROBE_DEFER) {
+			dev_warn(&phy->dev, "Unexpected emmcclk defer\n");
+			rk_phy->emmcclk = NULL;
+		}
+	}
+
+	if (!IS_ERR_OR_NULL(rk_phy->emmcclk)) {
+		unsigned long rate = clk_get_rate(rk_phy->emmcclk);
+
+		switch (rate) {
+		case 0 ... 74999999:
+			/* Nominal  50 MHz */
+			freqsel = PHYCTRL_FREQSEL_50M;
+			break;
+		case 75000000 ... 124999999:
+			/* Nominal 100 MHz */
+			freqsel = PHYCTRL_FREQSEL_100M;
+			break;
+		case 125000000 ... 174999999:
+			/* Nominal 150 MHz */
+			freqsel = PHYCTRL_FREQSEL_150M;
+			break;
+		default:
+			if (rate > 200000000)
+				dev_warn(&phy->dev, "Unsupported rate: %lu\n",
+					 rate);
+			break;
+		};
+	}
+
+	/*
 	 * Keep phyctrl_pdb and phyctrl_endll low to allow
 	 * initialization of CALIO state M/C DFFs
 	 */
@@ -132,6 +178,13 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,
 		return -ETIMEDOUT;
 	}
 
+	/* Set the frequency of the DLL operation */
+	regmap_write(rk_phy->reg_base,
+		     rk_phy->reg_offset + GRF_EMMCPHY_CON0,
+		     HIWORD_UPDATE(freqsel, PHYCTRL_FREQSEL_MASK,
+				   PHYCTRL_FREQSEL_SHIFT));
+
+	/* Turn on the DLL */
 	regmap_write(rk_phy->reg_base,
 		     rk_phy->reg_offset + GRF_EMMCPHY_CON6,
 		     HIWORD_UPDATE(PHYCTRL_ENDLL_ENABLE,
@@ -167,15 +220,8 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,
 
 static int rockchip_emmc_phy_power_off(struct phy *phy)
 {
-	struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
-	int ret = 0;
-
 	/* Power down emmc phy analog blocks */
-	ret = rockchip_emmc_phy_power(rk_phy, PHYCTRL_PDB_PWR_OFF);
-	if (ret)
-		return ret;
-
-	return 0;
+	return rockchip_emmc_phy_power(phy, PHYCTRL_PDB_PWR_OFF);
 }
 
 static int rockchip_emmc_phy_power_on(struct phy *phy)
@@ -183,12 +229,6 @@ static int rockchip_emmc_phy_power_on(struct phy *phy)
 	struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
 	int ret = 0;
 
-	/* DLL operation: 200 MHz */
-	regmap_write(rk_phy->reg_base,
-		     rk_phy->reg_offset + GRF_EMMCPHY_CON0,
-		     HIWORD_UPDATE(PHYCTRL_FREQSEL_200M,
-				   PHYCTRL_FREQSEL_MASK,
-				   PHYCTRL_FREQSEL_SHIFT));
 
 	/* Drive impedance: 50 Ohm */
 	regmap_write(rk_phy->reg_base,
@@ -212,7 +252,7 @@ static int rockchip_emmc_phy_power_on(struct phy *phy)
 				   PHYCTRL_OTAPDLYSEL_SHIFT));
 
 	/* Power up emmc phy analog blocks */
-	ret = rockchip_emmc_phy_power(rk_phy, PHYCTRL_PDB_PWR_ON);
+	ret = rockchip_emmc_phy_power(phy, PHYCTRL_PDB_PWR_ON);
 	if (ret)
 		return ret;
 
-- 
2.8.0.rc3.226.g39d4020

  parent reply	other threads:[~2016-06-07 22:46 UTC|newest]

Thread overview: 94+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-07 22:44 [PATCH 0/11] Changes to support 150 MHz eMMC on rk3399 Douglas Anderson
2016-06-07 22:44 ` Douglas Anderson
2016-06-07 22:44 ` [PATCH 01/11] phy: rockchip-emmc: Increase lock time allowance Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-13  7:58   ` Shawn Lin
2016-06-13  7:58     ` Shawn Lin
2016-06-13  7:58     ` Shawn Lin
2016-06-13 23:07     ` Doug Anderson
2016-06-13 23:07       ` Doug Anderson
2016-06-13 23:07       ` Doug Anderson
2016-06-07 22:44 ` [PATCH 02/11] mmc: sdhci-of-arasan: Always power the PHY off/on when clock changes Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-13  8:08   ` Shawn Lin
2016-06-13  8:08     ` Shawn Lin
2016-06-13  8:08     ` Shawn Lin
2016-06-13 23:06     ` Doug Anderson
2016-06-13 23:06       ` Doug Anderson
2016-06-13 23:06       ` Doug Anderson
2016-06-07 22:44 ` [PATCH 03/11] Documentation: mmc: sdhci-of-arasan: Add soc-ctl-syscon for corecfg regs Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-08 20:17   ` Rob Herring
2016-06-13  8:18   ` Shawn Lin
2016-06-13  9:32     ` Heiko Stübner
2016-06-13  9:32       ` Heiko Stübner
2016-06-13 23:07     ` Doug Anderson
2016-06-07 22:44 ` [PATCH 04/11] mmc: sdhci-of-arasan: Properly set corecfg_baseclkfreq on rk3399 Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-13  8:36   ` Shawn Lin
2016-06-13  8:36     ` Shawn Lin
2016-06-13 23:06     ` Doug Anderson
2016-06-13 23:06       ` Doug Anderson
2016-06-13 23:06       ` Doug Anderson
2016-06-14  0:14       ` Shawn Lin
2016-06-14  0:14         ` Shawn Lin
2016-06-14  0:14         ` Shawn Lin
2016-06-14  0:43         ` Doug Anderson
2016-06-14  0:43           ` Doug Anderson
2016-06-14  0:43           ` Doug Anderson
2016-06-14  0:59           ` Shawn Lin
2016-06-14  0:59             ` Shawn Lin
2016-06-14  0:59             ` Shawn Lin
2016-06-14  2:13             ` Doug Anderson
2016-06-14  2:13               ` Doug Anderson
2016-06-14  2:13               ` Doug Anderson
2016-06-16  1:06               ` Shawn Lin
2016-06-16  1:06                 ` Shawn Lin
2016-06-16  1:06                 ` Shawn Lin
2016-06-07 22:44 ` [PATCH 05/11] arm64: dts: rockchip: Add soc-ctl-syscon to sdhci for rk3399 Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-07 22:44 ` [PATCH 06/11] Documentation: mmc: sdhci-of-arasan: Add ability to export card clock Douglas Anderson
2016-06-08 20:19   ` Rob Herring
2016-06-08 20:52     ` Doug Anderson
2016-06-08 20:52       ` Doug Anderson
2016-06-10 13:10       ` Rob Herring
2016-06-13 23:05         ` Doug Anderson
2016-06-07 22:44 ` [PATCH 07/11] " Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-07 22:44 ` [PATCH 08/11] Documentation: phy: Let the rockchip eMMC PHY get an exported " Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-10 13:36   ` Rob Herring
2016-06-10 13:36     ` Rob Herring
2016-06-13 23:05     ` Doug Anderson
2016-06-13 23:05       ` Doug Anderson
2016-06-13 23:05       ` Doug Anderson
2016-06-07 22:44 ` Douglas Anderson [this message]
2016-06-07 22:44   ` [PATCH 09/11] phy: rockchip-emmc: Set phyctrl_frqsel based on " Douglas Anderson
2016-06-13  8:54   ` Shawn Lin
2016-06-13  8:54     ` Shawn Lin
2016-06-13  8:54     ` Shawn Lin
2016-06-13 23:05     ` Doug Anderson
2016-06-13 23:05       ` Doug Anderson
2016-06-13 23:05       ` Doug Anderson
2016-06-13 23:05       ` Doug Anderson
2016-06-14  0:24       ` Shawn Lin
2016-06-14  0:24         ` Shawn Lin
2016-06-14  0:24         ` Shawn Lin
2016-06-14  0:45         ` Doug Anderson
2016-06-14  0:45           ` Doug Anderson
2016-06-14  0:45           ` Doug Anderson
2016-06-07 22:44 ` [PATCH 10/11] phy: rockchip-emmc: Minor code cleanup in rockchip_emmc_phy_power_off() Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson
2016-06-13  8:56   ` Shawn Lin
2016-06-13  8:56     ` Shawn Lin
2016-06-13 23:05     ` Doug Anderson
2016-06-13 23:05       ` Doug Anderson
2016-06-13 23:05       ` Doug Anderson
2016-06-07 22:44 ` [PATCH 11/11] arm64: dts: rockchip: Provide emmcclk to PHY for rk3399 Douglas Anderson
2016-06-07 22:44   ` Douglas Anderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1465339484-969-10-git-send-email-dianders@chromium.org \
    --to=dianders@chromium.org \
    --cc=adrian.hunter@intel.com \
    --cc=briannorris@chromium.org \
    --cc=devicetree@vger.kernel.org \
    --cc=heiko@sntech.de \
    --cc=kishon@ti.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=robh+dt@kernel.org \
    --cc=shawn.lin@rock-chips.com \
    --cc=ulf.hansson@linaro.org \
    --cc=xzy.xu@rock-chips.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.