From: Douglas Anderson <dianders@chromium.org> Date: 2016-06-13 23:04:52
The theme of this series of patches is to try to allow running the eMMC
at 150 MHz on the rk3399 SoC, though the changes should still be correct
and have merit on their own. The motivation for running at 150 MHz is
that doing so improves signal integrity and (with some eMMC devices)
doesn't affect throughput.
These patches have been structured to keep things as separate as
possible, but nevertheless there are still some dependencies between
patches. It probably makes the most sense for all of the non-device
tree patches to go through a single tree. If others agree, perhaps the
most sane would be to get Acks from PHY maintainers and then to land the
patches in the MMC tree. Device tree patches should be able to be
landed separately and the worst what would happen is a warning in the
kernel log if you have the code without the device tree.
The code patches are based on Ulf's mmc-next, then 4 patches that are
outstanding / ready to land. Specifically:
- https://patchwork.kernel.org/patch/9086501/
phy: rockchip-emmc: give DLL some extra time to be ready
- https://patchwork.kernel.org/patch/9093681/
phy: rockchip-emmc: configure frequency range and drive impedance
- https://patchwork.kernel.org/patch/9086511/
phy: rockchip-emmc: configure default output tap delay
- https://patchwork.kernel.org/patch/9086531/
phy: rockchip-emmc: reindent the register definitions
The device tree patches are based on Heiko's v4.8-armsoc/dts64.
If requested, I could repost my series with the outstanding code patches
or I could try folding those patches into mine. Since those patches
aren't in 4.7-rc1 presumably they would also make sense to take through
the MMC tree if others agree.
Changes in v2:
- Indicate that 5.1 ms is calculated (Shawn).
- Clean up description of rk3399 PHY (Shawn)
- Add Rob Herring's Ack.
- Reorder includes (Shawn)
- Adjust commit message wording (Rob)
- List out clocks and clock names (Rob)
- Move code cleanup before set phyctrl_frqsel based on card clock (Shawn)
- Warn if we're more than 15 MHz from ideal rate (Shawn)
- Fix typo USB => SDHCI (Shawn)
Douglas Anderson (11):
phy: rockchip-emmc: Increase lock time allowance
mmc: sdhci-of-arasan: Always power the PHY off/on when clock changes
Documentation: mmc: sdhci-of-arasan: Add soc-ctl-syscon for corecfg
regs
mmc: sdhci-of-arasan: Properly set corecfg_baseclkfreq on rk3399
arm64: dts: rockchip: Add soc-ctl-syscon to sdhci for rk3399
Documentation: mmc: sdhci-of-arasan: Add ability to export card clock
mmc: sdhci-of-arasan: Add ability to export card clock
Documentation: phy: Let the rockchip eMMC PHY get an exported card
clock
phy: rockchip-emmc: Minor code cleanup in
rockchip_emmc_phy_power_on/off()
phy: rockchip-emmc: Set phyctrl_frqsel based on card clock
arm64: dts: rockchip: Provide emmcclk to PHY for rk3399
.../devicetree/bindings/mmc/arasan,sdhci.txt | 35 ++-
.../devicetree/bindings/phy/rockchip-emmc-phy.txt | 9 +
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 5 +
drivers/mmc/host/sdhci-of-arasan.c | 333 +++++++++++++++++++--
drivers/phy/phy-rockchip-emmc.c | 120 ++++++--
5 files changed, 442 insertions(+), 60 deletions(-)
--
2.8.0.rc3.226.g39d4020
From: Douglas Anderson <dianders@chromium.org> Date: 2016-06-13 23:04:56
In commit 802ac39a5566 ("mmc: sdhci-of-arasan: fix set_clock when a phy
is supported") we added code to power the PHY off and on whenever the
clock was changed but we avoided doing the power cycle code when the
clock was low speed. Let's now do it always.
Although there may be other reasons for power cycling the PHY when the
clock changes, one of the main reasons is that we need to give the DLL a
chance to re-lock with the new clock.
One of the things that the DLL is for is tuning the Receive Clock in
HS200 mode and STRB in HS400 mode. Thus it is clear that we should make
sure we power cycle the PHY (and wait for the DLL to lock) when we know
we'll be in one of these two speed modes. That's what the original code
did, though it used the clock rate rather than the speed mode. However,
even in speed modes other than HS200,/HS400 the DLL is used for
something since it can be clearly observed that the PHY doesn't function
properly if you leave the DLL off.
Although it appears less important to power cycle the PHY and wait for
the DLL to lock when not in HS200/HS400 modes (no bugs were reported),
it still seems wise to let the locking always happen nevertheless.
Note: as part of this, we make sure that we never try to turn the PHY on
when the clock is off (when the clock rate is 0). The PHY cannot work
when the clock is off since its DLL can't lock.
This change requires ("phy: rockchip-emmc: Increase lock time
allowance") and will cause problems if picked without that change.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2: None
drivers/mmc/host/sdhci-of-arasan.c | 23 ++++++++---------------
1 file changed, 8 insertions(+), 15 deletions(-)
From: Douglas Anderson <dianders@chromium.org> Date: 2016-06-13 23:05:01
In the the earlier change in this series ("Documentation: mmc:
sdhci-of-arasan: Add soc-ctl-syscon for corecfg regs") we can see the
mechansim for specifying a syscon to properly set corecfg registers in
sdhci-of-arasan. Now let's use this mechanism to properly set
corecfg_baseclkfreq on rk3399.
From [1] the corecfg_baseclkfreq is supposed to be set to:
Base Clock Frequency for SD Clock.
This is the frequency of the xin_clk.
This is a relatively easy thing to do. Note that we assume that xin_clk
is not dynamic and we can check the clock at probe time. If any real
devices have a dynamic xin_clk future patches could register for
notifiers for the clock.
At the moment, setting corecfg_baseclkfreq is only supported for rk3399
since we need a specific map for each implementation. The code is
written in a generic way that should make this easy to extend to other
SoCs. Note that a specific compatible string for rk3399 is already in
use and so we add that to the table to match rk3399.
[1]: https://arasan.com/wp-content/media/eMMC-5-1-Total-Solution_Rev-1-3.pdf
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2:
- Reorder includes (Shawn)
drivers/mmc/host/sdhci-of-arasan.c | 189 ++++++++++++++++++++++++++++++++++---
1 file changed, 178 insertions(+), 11 deletions(-)
@@ -191,9 +290,66 @@ static int sdhci_arasan_resume(struct device *dev)staticSIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops,sdhci_arasan_suspend,sdhci_arasan_resume);+staticconststructof_device_idsdhci_arasan_of_match[]={+/* SoC-specific compatible strings w/ soc_ctl_map */+{+.compatible="rockchip,rk3399-sdhci-5.1",+.data=&rk3399_soc_ctl_map,+},++/* Generic compatible below here */+{.compatible="arasan,sdhci-8.9a"},+{.compatible="arasan,sdhci-5.1"},+{.compatible="arasan,sdhci-4.9a"},++{/* sentinel */}+};+MODULE_DEVICE_TABLE(of,sdhci_arasan_of_match);++/**+*sdhci_arasan_update_baseclkfreq-Setcorecfg_baseclkfreq+*+*Thecorecfg_baseclkfreqissupposedtocontaintheMHzofclk_xin.This+*functioncanbeusedtomakethathappen.+*+*NOTES:+*-Manyexistingdevicesdon'tseemtodothisandworkfine.Tokeep+*compatibilityforoldhardwarewherethedevicetreedoesn'tprovidea+*registermap,thisfunctionisanoopifasoc_ctl_maphasn'tbeenprovided+*forthisplatform.+*-It'sassumedthatclk_xinisnotdynamicandthatweusetheSDHCIdivider+*toachievelowerclockrates.Thatmeansthatthisfunctioniscalledonce+*atprobetimeandnevercalledagain.+*+*@host:Thesdhci_host+*/+staticvoidsdhci_arasan_update_baseclkfreq(structsdhci_host*host)+{+structsdhci_pltfm_host*pltfm_host=sdhci_priv(host);+structsdhci_arasan_data*sdhci_arasan=sdhci_pltfm_priv(pltfm_host);+conststructsdhci_arasan_soc_ctl_map*soc_ctl_map=+sdhci_arasan->soc_ctl_map;+u32mhz=DIV_ROUND_CLOSEST(clk_get_rate(pltfm_host->clk),1000000);++/* Having a map is optional */+if(!soc_ctl_map)+return;++/* If we have a map, we expect to have a syscon */+if(!sdhci_arasan->soc_ctl_base){+pr_warn("%s: Have regmap, but no soc-ctl-syscon\n",+mmc_hostname(host->mmc));+return;+}++sdhci_arasan_syscon_write(host,&soc_ctl_map->baseclkfreq,mhz);+}+staticintsdhci_arasan_probe(structplatform_device*pdev){intret;+conststructof_device_id*match;+structdevice_node*node;structclk*clk_xin;structsdhci_host*host;structsdhci_pltfm_host*pltfm_host;
@@ -207,6 +363,23 @@ static int sdhci_arasan_probe(struct platform_device *pdev)pltfm_host=sdhci_priv(host);sdhci_arasan=sdhci_pltfm_priv(pltfm_host);+match=of_match_node(sdhci_arasan_of_match,pdev->dev.of_node);+sdhci_arasan->soc_ctl_map=match->data;++node=of_parse_phandle(pdev->dev.of_node,"arasan,soc-ctl-syscon",0);+if(node){+sdhci_arasan->soc_ctl_base=syscon_node_to_regmap(node);+of_node_put(node);++if(IS_ERR(sdhci_arasan->soc_ctl_base)){+ret=PTR_ERR(sdhci_arasan->soc_ctl_base);+if(ret!=-EPROBE_DEFER)+dev_err(&pdev->dev,"Can't get syscon: %d\n",+ret);+gotoerr_pltfm_free;+}+}+sdhci_arasan->clk_ahb=devm_clk_get(&pdev->dev,"clk_ahb");if(IS_ERR(sdhci_arasan->clk_ahb)){dev_err(&pdev->dev,"clk_ahb clock not found.\n");
From: Douglas Anderson <dianders@chromium.org> Date: 2016-06-13 23:05:10
There's no reason to store the return value of rockchip_emmc_phy_power()
in a variable nor to check it. Just return it.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2:
- Move code cleanup before set phyctrl_frqsel based on card clock (Shawn)
drivers/phy/phy-rockchip-emmc.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
@@ -169,20 +169,14 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,staticintrockchip_emmc_phy_power_off(structphy*phy){structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);-intret=0;/* Power down emmc phy analog blocks */-ret=rockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_OFF);-if(ret)-returnret;--return0;+returnrockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_OFF);}staticintrockchip_emmc_phy_power_on(structphy*phy){structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);-intret=0;/* DLL operation: 200 MHz */regmap_write(rk_phy->reg_base,
@@ -213,11 +207,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);-if(ret)-returnret;--return0;+returnrockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_ON);}staticconststructphy_opsops={
From: Douglas Anderson <dianders@chromium.org> Date: 2016-06-13 23:05:12
As of an earlier change in this series ("Documentation: mmc:
sdhci-of-arasan: Add ability to export card clock") the SDHCI driver
used on Rockchip SoCs can now expose its clock. Let's now specify that
the PHY can use it.
Letting the PHY get access to this clock means it can adjust
phyctrl_frqsel field appropriately. Although the Rockchip PHY appears
slightly different than the reference Arasan one, you can see that the
Arasan datasheet [1] had it defined as:
Select the frequency range of DLL operation:
3b'000 => 200MHz to 170 MHz
3b'001 => 170MHz to 140 MHz
3b'010 => 140MHz to 110 MHz
3b'011 => 110MHz to 80MHz
3b'100 => 80MHz to 50 MHz
3b'101 => 275Mhz to 250MHz
3b'110 => 250MHz to 225MHz
3b'111 => 225MHz to 200MHz
On the Rockchip version of the PHY we have less granularity but the idea
is the same.
[1]: https://arasan.com/wp-content/media/eMMC-5-1-Total-Solution_Rev-1-3.pdf
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2:
- List out clocks and clock names (Rob)
Documentation/devicetree/bindings/phy/rockchip-emmc-phy.txt | 9 +++++++++
1 file changed, 9 insertions(+)
@@ -7,6 +7,13 @@ Required properties: - reg: PHY register address offset and length in "general register files"+Optional clocks using the clock bindings (see ../clock/clock-bindings.txt),+specified by name:+ - clock-names: Should contain "emmcclk". Although this is listed as optional+ (because most boards can get basic functionality without having+ access to it), it is strongly suggested.+ - clocks: Should have a phandle to the card clock exported by the SDHCI driver.+ Example:
From: Douglas Anderson <dianders@chromium.org> Date: 2016-06-13 23:05:14
Some SD/eMMC PHYs (like the PHY from Arasan that is designed to work
with arasan,sdhci-5.1) need to know the card clock in order to function
properly. Let's add the ability to expose this clock. Any PHY that
needs to know the clock rate can add a reference and query the clock
rate.
At the moment we register a CLK_GET_RATE_NOCACHE clock that simply
allows querying the clock. This allows us to be less intrusive with
regards to the main SDHCI driver, which has complex logic for adjusting
the SD clock. Right now we always fully power cycle the PHY when the
clock changes and that gives the PHY a good chance to query our clock.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2: None
drivers/mmc/host/sdhci-of-arasan.c | 125 ++++++++++++++++++++++++++++++++++++-
1 file changed, 122 insertions(+), 3 deletions(-)
@@ -345,6 +378,83 @@ static void sdhci_arasan_update_baseclkfreq(struct sdhci_host *host)sdhci_arasan_syscon_write(host,&soc_ctl_map->baseclkfreq,mhz);}+/**+*sdhci_arasan_register_sdclk-RegisterthesdclkforaPHYtouse+*+*SomePHYdevicesneedtoknowwhattheactualcardclockis.Inorderfor+*themtofindout,we'llprovideaclockthroughthecommonclockframework+*forthemtoquery.+*+*Note:withoutseriouslyre-architectingSDHCI'sclockcodeandtestingon+*allplatforms,there'snowaytocreateatotallybeautifulclockhere+*withallclockopsimplemented.Instead,we'lljustcreateaclockthatcan+*bequeriedandsettheCLK_GET_RATE_NOCACHEattributetotellcommonclock+*frameworkthatwe'redoingthingsbehinditsback.Thisshouldbesufficient+*tocreatenicecleandevicetreebindingsandlater(ifneeded)wecantry+*re-architectingSDHCIifweseesomebenefittoit.+*+*@sdhci_arasan:Ourprivatedatastructure.+*@clk_xin:Pointertothefunctionalclock+*@dev:Pointertoourstructdevice.+*Returns0onsuccessanderrorvalueonerror+*/+staticintsdhci_arasan_register_sdclk(structsdhci_arasan_data*sdhci_arasan,+structclk*clk_xin,+structdevice*dev)+{+structdevice_node*np=dev->of_node;+structclk_init_datasdcardclk_init;+constchar*parent_clk_name;+intret;++/* Providing a clock to the PHY is optional; no error if missing */+if(!of_find_property(np,"#clock-cells",NULL))+return0;++ret=of_property_read_string_index(np,"clock-output-names",0,+&sdcardclk_init.name);+if(ret){+dev_err(dev,"DT has #clock-cells but no clock-output-names\n");+returnret;+}++parent_clk_name=__clk_get_name(clk_xin);+sdcardclk_init.parent_names=&parent_clk_name;+sdcardclk_init.num_parents=1;+sdcardclk_init.flags=CLK_GET_RATE_NOCACHE;+sdcardclk_init.ops=&arasan_sdcardclk_ops;++sdhci_arasan->sdcardclk_hw.init=&sdcardclk_init;+sdhci_arasan->sdcardclk=+devm_clk_register(dev,&sdhci_arasan->sdcardclk_hw);+sdhci_arasan->sdcardclk_hw.init=NULL;++ret=of_clk_add_provider(np,of_clk_src_simple_get,+sdhci_arasan->sdcardclk);+if(ret)+dev_err(dev,"Failed to add clock provider\n");++returnret;+}++/**+*sdhci_arasan_unregister_sdclk-Undoessdhci_arasan_register_sdclk()+*+*Shouldbecalledanytimewe'reexitingandsdhci_arasan_register_sdclk()+*returnedsuccess.+*+*@dev:Pointertoourstructdevice.+*/+staticvoidsdhci_arasan_unregister_sdclk(structdevice*dev)+{+structdevice_node*np=dev->of_node;++if(!of_find_property(np,"#clock-cells",NULL))+return;++of_clk_del_provider(dev->of_node);+}+staticintsdhci_arasan_probe(structplatform_device*pdev){intret;
@@ -362,6 +472,7 @@ static int sdhci_arasan_probe(struct platform_device *pdev)pltfm_host=sdhci_priv(host);sdhci_arasan=sdhci_pltfm_priv(pltfm_host);+sdhci_arasan->host=host;match=of_match_node(sdhci_arasan_of_match,pdev->dev.of_node);sdhci_arasan->soc_ctl_map=match->data;
From: Douglas Anderson <dianders@chromium.org> Date: 2016-06-13 23:08:26
On rk3399 we'd like to be able to properly set corecfg registers in the
Arasan SDHCI component. Specify the syscon to enable that.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2: None
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 1 +
1 file changed, 1 insertion(+)
From: Douglas Anderson <dianders@chromium.org> Date: 2016-06-13 23:08:43
Previous changes in this series allowed exposing the card clock from the
rk3399 SDHCI device and allowed consuming the card clock in the rk3399
eMMC PHY. Hook things up in the main rk3399 dtsi file.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2: None
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 4 ++++
1 file changed, 4 insertions(+)
From: Douglas Anderson <dianders@chromium.org> Date: 2016-06-13 23:09:04
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>
---
Changes in v2:
- Warn if we're more than 15 MHz from ideal rate (Shawn)
- Move code cleanup before set phyctrl_frqsel based on card clock (Shawn)
- Fix typo USB => SDHCI (Shawn)
drivers/phy/phy-rockchip-emmc.c | 82 ++++++++++++++++++++++++++++++++++-------
1 file changed, 69 insertions(+), 13 deletions(-)
@@ -78,16 +79,73 @@structrockchip_emmc_phy{unsignedintreg_offset;structregmap*reg_base;+structclk*emmcclk;};-staticintrockchip_emmc_phy_power(structrockchip_emmc_phy*rk_phy,-boolon_off)+staticintrockchip_emmc_phy_power(structphy*phy,boolon_off){+structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);unsignedintcaldone;unsignedintdllrdy;+unsignedintfreqsel=PHYCTRL_FREQSEL_200M;unsignedlongtimeout;/*+*Wepurposelygettheclockhereandnotinprobetoavoidthe+*circulardependencyproblem.Weexpect:+*-PHYdrivertoprobe+*-SDHCIdrivertostartprobe+*-SDHCIdrivertoregisterit'sclock+*-SDHCIdrivertogetthePHY+*-SDHCIdrivertopoweronthePHY+*/+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)){+unsignedlongrate=clk_get_rate(rk_phy->emmcclk);+unsignedlongideal_rate;+unsignedlongdiff;++switch(rate){+case0...74999999:+ideal_rate=50000000;+freqsel=PHYCTRL_FREQSEL_50M;+break;+case75000000...124999999:+ideal_rate=100000000;+freqsel=PHYCTRL_FREQSEL_100M;+break;+case125000000...174999999:+ideal_rate=150000000;+freqsel=PHYCTRL_FREQSEL_150M;+break;+default:+ideal_rate=200000000;+break;+};++diff=(rate>ideal_rate)?+rate-ideal_rate:ideal_rate-rate;++/*+*Inorderfortuningdelaystobeaccurateweneedtobe+*prettyspotonfortheDLLrange,sowarnifwe'retoo+*faroff.Alsowarnifwe'reabovethe200MHzmax.Don't+*warnforreallyslowratessincewewon'tbetuningthen.+*/+if((rate>50000000&&diff>15000000)||(rate>200000000))+dev_warn(&phy->dev,"Unsupported rate: %lu\n",rate);+}++/**Keepphyctrl_pdbandphyctrl_endlllowtoallow*initializationofCALIOstateM/CDFFs*/
@@ -132,6 +190,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,
@@ -168,23 +233,14 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,staticintrockchip_emmc_phy_power_off(structphy*phy){-structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);-/* Power down emmc phy analog blocks */-returnrockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_OFF);+returnrockchip_emmc_phy_power(phy,PHYCTRL_PDB_PWR_OFF);}staticintrockchip_emmc_phy_power_on(structphy*phy){structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);-/* 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,rk_phy->reg_offset+GRF_EMMCPHY_CON6,
@@ -207,7 +263,7 @@ static int rockchip_emmc_phy_power_on(struct phy *phy)PHYCTRL_OTAPDLYSEL_SHIFT));/* Power up emmc phy analog blocks */-returnrockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_ON);+returnrockchip_emmc_phy_power(phy,PHYCTRL_PDB_PWR_ON);}staticconststructphy_opsops={
From: Douglas Anderson <dianders@chromium.org> Date: 2016-06-13 23:10:41
Previous PHY code waited a fixed amount of time for the DLL to lock at
power on time. Unfortunately, the time for the DLL to lock is actually
a bit more dynamic and can be longer if the card clock is slower.
Instead of waiting a fixed 30 us, let's now dynamically wait until the
lock bit gets set. We'll wait up to 10 ms which should be OK even if
the card clock is at the super slow 100 kHz.
On its own, this change makes the PHY power on code a little more
robust. Before this change the PHY was relying on the eMMC code to make
sure the PHY was only powered on when the card clock was set to at least
50 MHz before, though this reliance wasn't documented anywhere.
This change will be even more useful in future changes where we actually
need to be able to wait for a DLL lock at slower clock speeds.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2:
- Indicate that 5.1 ms is calculated (Shawn).
drivers/phy/phy-rockchip-emmc.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
From: Shawn Lin <shawn.lin@rock-chips.com> Date: 2016-06-14 00:28:57
? 2016/6/14 7:04, Douglas Anderson ??:
Previous PHY code waited a fixed amount of time for the DLL to lock at
power on time. Unfortunately, the time for the DLL to lock is actually
a bit more dynamic and can be longer if the card clock is slower.
Instead of waiting a fixed 30 us, let's now dynamically wait until the
lock bit gets set. We'll wait up to 10 ms which should be OK even if
the card clock is at the super slow 100 kHz.
On its own, this change makes the PHY power on code a little more
robust. Before this change the PHY was relying on the eMMC code to make
sure the PHY was only powered on when the card clock was set to at least
50 MHz before, though this reliance wasn't documented anywhere.
This change will be even more useful in future changes where we actually
need to be able to wait for a DLL lock at slower clock speeds.
Looks good to me.
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
quoted hunk
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2:
- Indicate that 5.1 ms is calculated (Shawn).
drivers/phy/phy-rockchip-emmc.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
From: Shawn Lin <shawn.lin@rock-chips.com> Date: 2016-06-14 00:30:36
? 2016/6/14 7:04, Douglas Anderson ??:
In commit 802ac39a5566 ("mmc: sdhci-of-arasan: fix set_clock when a phy
is supported") we added code to power the PHY off and on whenever the
clock was changed but we avoided doing the power cycle code when the
clock was low speed. Let's now do it always.
Although there may be other reasons for power cycling the PHY when the
clock changes, one of the main reasons is that we need to give the DLL a
chance to re-lock with the new clock.
One of the things that the DLL is for is tuning the Receive Clock in
HS200 mode and STRB in HS400 mode. Thus it is clear that we should make
sure we power cycle the PHY (and wait for the DLL to lock) when we know
we'll be in one of these two speed modes. That's what the original code
did, though it used the clock rate rather than the speed mode. However,
even in speed modes other than HS200,/HS400 the DLL is used for
something since it can be clearly observed that the PHY doesn't function
properly if you leave the DLL off.
Although it appears less important to power cycle the PHY and wait for
the DLL to lock when not in HS200/HS400 modes (no bugs were reported),
it still seems wise to let the locking always happen nevertheless.
Note: as part of this, we make sure that we never try to turn the PHY on
when the clock is off (when the clock rate is 0). The PHY cannot work
when the clock is off since its DLL can't lock.
This change requires ("phy: rockchip-emmc: Increase lock time
allowance") and will cause problems if picked without that change.
Thanks for doint it.
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
quoted hunk
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2: None
drivers/mmc/host/sdhci-of-arasan.c | 23 ++++++++---------------
1 file changed, 8 insertions(+), 15 deletions(-)
From: Shawn Lin <shawn.lin@rock-chips.com> Date: 2016-06-14 00:36:22
? 2016/6/14 7:04, Douglas Anderson ??:
There's no reason to store the return value of rockchip_emmc_phy_power()
in a variable nor to check it. Just return it.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2:
- Move code cleanup before set phyctrl_frqsel based on card clock (Shawn)
Looks good to me.
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
@@ -169,20 +169,14 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,staticintrockchip_emmc_phy_power_off(structphy*phy){structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);-intret=0;/* Power down emmc phy analog blocks */-ret=rockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_OFF);-if(ret)-returnret;--return0;+returnrockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_OFF);}staticintrockchip_emmc_phy_power_on(structphy*phy){structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);-intret=0;/* DLL operation: 200 MHz */regmap_write(rk_phy->reg_base,
@@ -213,11 +207,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);-if(ret)-returnret;--return0;+returnrockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_ON);}staticconststructphy_opsops={
From: Doug Anderson <dianders@chromium.org> Date: 2016-06-15 16:40:46
Hi,
On Mon, Jun 13, 2016 at 4:04 PM, Douglas Anderson [off-list ref] wrote:
Some SD/eMMC PHYs (like the PHY from Arasan that is designed to work
with arasan,sdhci-5.1) need to know the card clock in order to function
properly. Let's add the ability to expose this clock. Any PHY that
needs to know the clock rate can add a reference and query the clock
rate.
At the moment we register a CLK_GET_RATE_NOCACHE clock that simply
allows querying the clock. This allows us to be less intrusive with
regards to the main SDHCI driver, which has complex logic for adjusting
the SD clock. Right now we always fully power cycle the PHY when the
clock changes and that gives the PHY a good chance to query our clock.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2: None
drivers/mmc/host/sdhci-of-arasan.c | 125 ++++++++++++++++++++++++++++++++++++-
1 file changed, 122 insertions(+), 3 deletions(-)
I've sent out a new version of just this patch as "version 2.1" to
address a problem found by Guenter Roeck. Please see
<https://patchwork.kernel.org/patch/9178951/>. If it's handy for me
to send out a whole new v3 series, please let me know.
-Doug
From: Rob Herring <robh@kernel.org> Date: 2016-06-16 18:42:34
On Mon, Jun 13, 2016 at 04:04:32PM -0700, Douglas Anderson wrote:
As of an earlier change in this series ("Documentation: mmc:
sdhci-of-arasan: Add ability to export card clock") the SDHCI driver
used on Rockchip SoCs can now expose its clock. Let's now specify that
the PHY can use it.
Letting the PHY get access to this clock means it can adjust
phyctrl_frqsel field appropriately. Although the Rockchip PHY appears
slightly different than the reference Arasan one, you can see that the
Arasan datasheet [1] had it defined as:
Select the frequency range of DLL operation:
3b'000 => 200MHz to 170 MHz
3b'001 => 170MHz to 140 MHz
3b'010 => 140MHz to 110 MHz
3b'011 => 110MHz to 80MHz
3b'100 => 80MHz to 50 MHz
3b'101 => 275Mhz to 250MHz
3b'110 => 250MHz to 225MHz
3b'111 => 225MHz to 200MHz
On the Rockchip version of the PHY we have less granularity but the idea
is the same.
[1]: https://arasan.com/wp-content/media/eMMC-5-1-Total-Solution_Rev-1-3.pdf
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Changes in v2:
- List out clocks and clock names (Rob)
Documentation/devicetree/bindings/phy/rockchip-emmc-phy.txt | 9 +++++++++
1 file changed, 9 insertions(+)
Am Montag, 13. Juni 2016, 16:04:24 schrieb Douglas Anderson:
The theme of this series of patches is to try to allow running the eMMC
at 150 MHz on the rk3399 SoC, though the changes should still be correct
and have merit on their own. The motivation for running at 150 MHz is
that doing so improves signal integrity and (with some eMMC devices)
doesn't affect throughput.
These patches have been structured to keep things as separate as
possible, but nevertheless there are still some dependencies between
patches. It probably makes the most sense for all of the non-device
tree patches to go through a single tree. If others agree, perhaps the
most sane would be to get Acks from PHY maintainers and then to land the
patches in the MMC tree. Device tree patches should be able to be
landed separately and the worst what would happen is a warning in the
kernel log if you have the code without the device tree.
while my evaluation board does not seem to have an enhanced strobe emmc, it
nevertheless still runs fine with these patches applied, for the series
(including the separate v2.1) on a rk3399-evb:
Tested-by: Heiko Stuebner <heiko@sntech.de>
From: Kishon Vijay Abraham I <hidden> Date: 2016-06-17 12:40:07
Hi,
On Tuesday 14 June 2016 04:34 AM, Douglas Anderson wrote:
The theme of this series of patches is to try to allow running the eMMC
at 150 MHz on the rk3399 SoC, though the changes should still be correct
and have merit on their own. The motivation for running at 150 MHz is
that doing so improves signal integrity and (with some eMMC devices)
doesn't affect throughput.
These patches have been structured to keep things as separate as
possible, but nevertheless there are still some dependencies between
patches. It probably makes the most sense for all of the non-device
tree patches to go through a single tree. If others agree, perhaps the
most sane would be to get Acks from PHY maintainers and then to land the
patches in the MMC tree. Device tree patches should be able to be
landed separately and the worst what would happen is a warning in the
kernel log if you have the code without the device tree.
The code patches are based on Ulf's mmc-next, then 4 patches that are
outstanding / ready to land. Specifically:
- https://patchwork.kernel.org/patch/9086501/
phy: rockchip-emmc: give DLL some extra time to be ready
- https://patchwork.kernel.org/patch/9093681/
phy: rockchip-emmc: configure frequency range and drive impedance
- https://patchwork.kernel.org/patch/9086511/
phy: rockchip-emmc: configure default output tap delay
- https://patchwork.kernel.org/patch/9086531/
phy: rockchip-emmc: reindent the register definitions
Do you want all these "phy: rockchip-emmc:" along with the patch in this series
to go in MMC tree? Or I can take all the phy part in my linux-phy -next branch?
Thanks
Kishon
The device tree patches are based on Heiko's v4.8-armsoc/dts64.
If requested, I could repost my series with the outstanding code patches
or I could try folding those patches into mine. Since those patches
aren't in 4.7-rc1 presumably they would also make sense to take through
the MMC tree if others agree.
Changes in v2:
- Indicate that 5.1 ms is calculated (Shawn).
- Clean up description of rk3399 PHY (Shawn)
- Add Rob Herring's Ack.
- Reorder includes (Shawn)
- Adjust commit message wording (Rob)
- List out clocks and clock names (Rob)
- Move code cleanup before set phyctrl_frqsel based on card clock (Shawn)
- Warn if we're more than 15 MHz from ideal rate (Shawn)
- Fix typo USB => SDHCI (Shawn)
Douglas Anderson (11):
phy: rockchip-emmc: Increase lock time allowance
mmc: sdhci-of-arasan: Always power the PHY off/on when clock changes
Documentation: mmc: sdhci-of-arasan: Add soc-ctl-syscon for corecfg
regs
mmc: sdhci-of-arasan: Properly set corecfg_baseclkfreq on rk3399
arm64: dts: rockchip: Add soc-ctl-syscon to sdhci for rk3399
Documentation: mmc: sdhci-of-arasan: Add ability to export card clock
mmc: sdhci-of-arasan: Add ability to export card clock
Documentation: phy: Let the rockchip eMMC PHY get an exported card
clock
phy: rockchip-emmc: Minor code cleanup in
rockchip_emmc_phy_power_on/off()
phy: rockchip-emmc: Set phyctrl_frqsel based on card clock
arm64: dts: rockchip: Provide emmcclk to PHY for rk3399
.../devicetree/bindings/mmc/arasan,sdhci.txt | 35 ++-
.../devicetree/bindings/phy/rockchip-emmc-phy.txt | 9 +
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 5 +
drivers/mmc/host/sdhci-of-arasan.c | 333 +++++++++++++++++++--
drivers/phy/phy-rockchip-emmc.c | 120 ++++++--
5 files changed, 442 insertions(+), 60 deletions(-)
From: Doug Anderson <dianders@chromium.org> Date: 2016-06-17 15:37:27
Kishon,
On Fri, Jun 17, 2016 at 5:39 AM, Kishon Vijay Abraham I [off-list ref] wrote:
Hi,
On Tuesday 14 June 2016 04:34 AM, Douglas Anderson wrote:
quoted
The theme of this series of patches is to try to allow running the eMMC
at 150 MHz on the rk3399 SoC, though the changes should still be correct
and have merit on their own. The motivation for running at 150 MHz is
that doing so improves signal integrity and (with some eMMC devices)
doesn't affect throughput.
These patches have been structured to keep things as separate as
possible, but nevertheless there are still some dependencies between
patches. It probably makes the most sense for all of the non-device
tree patches to go through a single tree. If others agree, perhaps the
most sane would be to get Acks from PHY maintainers and then to land the
patches in the MMC tree. Device tree patches should be able to be
landed separately and the worst what would happen is a warning in the
kernel log if you have the code without the device tree.
The code patches are based on Ulf's mmc-next, then 4 patches that are
outstanding / ready to land. Specifically:
- https://patchwork.kernel.org/patch/9086501/
phy: rockchip-emmc: give DLL some extra time to be ready
- https://patchwork.kernel.org/patch/9093681/
phy: rockchip-emmc: configure frequency range and drive impedance
- https://patchwork.kernel.org/patch/9086511/
phy: rockchip-emmc: configure default output tap delay
- https://patchwork.kernel.org/patch/9086531/
phy: rockchip-emmc: reindent the register definitions
Do you want all these "phy: rockchip-emmc:" along with the patch in this series
to go in MMC tree? Or I can take all the phy part in my linux-phy -next branch?
If Ulf is amenable, I was hoping that these could all go through the
MMC tree with your blessing. ...then "dts" patches would go through
Heiko's tree.
-Doug
Am Montag, 13. Juni 2016, 16:04:35 schrieb Douglas Anderson:
Previous changes in this series allowed exposing the card clock from the
rk3399 SDHCI device and allowed consuming the card clock in the rk3399
eMMC PHY. Hook things up in the main rk3399 dtsi file.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
as the whole devicetree-part of the emmc addition is in my queue for 4.8, I'll
pick this patch after everything else has gone into some tree.
Heiko
Am Montag, 13. Juni 2016, 16:04:34 schrieb Douglas Anderson:
quoted hunk
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>
---
Changes in v2:
- Warn if we're more than 15 MHz from ideal rate (Shawn)
- Move code cleanup before set phyctrl_frqsel based on card clock (Shawn)
- Fix typo USB => SDHCI (Shawn)
drivers/phy/phy-rockchip-emmc.c | 82
++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+),
13 deletions(-)
diff --git a/drivers/phy/phy-rockchip-emmc.c
b/drivers/phy/phy-rockchip-emmc.c index 23fe50864526..51ddd543fd04 100644
Doesn't that leave open the unbind / removal case with that same circular
dependency? While true that the clock-framework does some special handling on
clk_unregister, I don't think this would catch multiple unbind/bind actions.
The emmc-phy would still hold on to the old clock-instance with the empty clk-
ops the ccf assigns, even when the rebind of the arasan-sdhci would create a
new clock.
How about using phy-init / phy-exit callbacks for that instead? (Aka clk_get
and clk_put the emmc clock in there instead of using the devm variant)
+ 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)) {
you just made it NULL in the error case above?
Heiko
Am Montag, 13. Juni 2016, 16:04:29 schrieb Douglas Anderson:
On rk3399 we'd like to be able to properly set corecfg registers in the
Arasan SDHCI component. Specify the syscon to enable that.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
as the whole devicetree-part of the emmc addition is in my queue for 4.8, I'll
pick this patch after everything else has gone into some tree.
Heiko
Am Montag, 13. Juni 2016, 16:04:28 schrieb Douglas Anderson:
In the the earlier change in this series ("Documentation: mmc:
sdhci-of-arasan: Add soc-ctl-syscon for corecfg regs") we can see the
mechansim for specifying a syscon to properly set corecfg registers in
sdhci-of-arasan. Now let's use this mechanism to properly set
corecfg_baseclkfreq on rk3399.
From [1] the corecfg_baseclkfreq is supposed to be set to:
Base Clock Frequency for SD Clock.
This is the frequency of the xin_clk.
This is a relatively easy thing to do. Note that we assume that xin_clk
is not dynamic and we can check the clock at probe time. If any real
devices have a dynamic xin_clk future patches could register for
notifiers for the clock.
At the moment, setting corecfg_baseclkfreq is only supported for rk3399
since we need a specific map for each implementation. The code is
written in a generic way that should make this easy to extend to other
SoCs. Note that a specific compatible string for rk3399 is already in
use and so we add that to the table to match rk3399.
[1]:
https://arasan.com/wp-content/media/eMMC-5-1-Total-Solution_Rev-1-3.pdf
Signed-off-by: Douglas Anderson <dianders@chromium.org>
this looks nice and versatile for other socs hopefully using that in the
future.
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Am Montag, 13. Juni 2016, 16:04:32 schrieb Douglas Anderson:
As of an earlier change in this series ("Documentation: mmc:
sdhci-of-arasan: Add ability to export card clock") the SDHCI driver
used on Rockchip SoCs can now expose its clock. Let's now specify that
the PHY can use it.
Letting the PHY get access to this clock means it can adjust
phyctrl_frqsel field appropriately. Although the Rockchip PHY appears
slightly different than the reference Arasan one, you can see that the
Arasan datasheet [1] had it defined as:
Select the frequency range of DLL operation:
3b'000 => 200MHz to 170 MHz
3b'001 => 170MHz to 140 MHz
3b'010 => 140MHz to 110 MHz
3b'011 => 110MHz to 80MHz
3b'100 => 80MHz to 50 MHz
3b'101 => 275Mhz to 250MHz
3b'110 => 250MHz to 225MHz
3b'111 => 225MHz to 200MHz
On the Rockchip version of the PHY we have less granularity but the idea
is the same.
[1]: https://arasan.com/wp-content/media/eMMC-5-1-Total-Solution_Rev-1-3.pdf
Signed-off-by: Douglas Anderson <dianders@chromium.org>
From: Kishon Vijay Abraham I <hidden> Date: 2016-06-20 13:07:35
On Tuesday 14 June 2016 04:34 AM, Douglas Anderson wrote:
As of an earlier change in this series ("Documentation: mmc:
sdhci-of-arasan: Add ability to export card clock") the SDHCI driver
used on Rockchip SoCs can now expose its clock. Let's now specify that
the PHY can use it.
Letting the PHY get access to this clock means it can adjust
phyctrl_frqsel field appropriately. Although the Rockchip PHY appears
slightly different than the reference Arasan one, you can see that the
Arasan datasheet [1] had it defined as:
Select the frequency range of DLL operation:
3b'000 => 200MHz to 170 MHz
3b'001 => 170MHz to 140 MHz
3b'010 => 140MHz to 110 MHz
3b'011 => 110MHz to 80MHz
3b'100 => 80MHz to 50 MHz
3b'101 => 275Mhz to 250MHz
3b'110 => 250MHz to 225MHz
3b'111 => 225MHz to 200MHz
On the Rockchip version of the PHY we have less granularity but the idea
is the same.
[1]: https://arasan.com/wp-content/media/eMMC-5-1-Total-Solution_Rev-1-3.pdf
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Acked-by: Kishon Vijay Abraham I <redacted>
quoted hunk
---
Changes in v2:
- List out clocks and clock names (Rob)
Documentation/devicetree/bindings/phy/rockchip-emmc-phy.txt | 9 +++++++++
1 file changed, 9 insertions(+)
@@ -7,6 +7,13 @@ Required properties: - reg: PHY register address offset and length in "general register files"+Optional clocks using the clock bindings (see ../clock/clock-bindings.txt),+specified by name:+ - clock-names: Should contain "emmcclk". Although this is listed as optional+ (because most boards can get basic functionality without having+ access to it), it is strongly suggested.+ - clocks: Should have a phandle to the card clock exported by the SDHCI driver.+ Example:
From: Kishon Vijay Abraham I <hidden> Date: 2016-06-20 13:07:41
On Tuesday 14 June 2016 04:34 AM, Douglas Anderson wrote:
Previous PHY code waited a fixed amount of time for the DLL to lock at
power on time. Unfortunately, the time for the DLL to lock is actually
a bit more dynamic and can be longer if the card clock is slower.
Instead of waiting a fixed 30 us, let's now dynamically wait until the
lock bit gets set. We'll wait up to 10 ms which should be OK even if
the card clock is at the super slow 100 kHz.
On its own, this change makes the PHY power on code a little more
robust. Before this change the PHY was relying on the eMMC code to make
sure the PHY was only powered on when the card clock was set to at least
50 MHz before, though this reliance wasn't documented anywhere.
This change will be even more useful in future changes where we actually
need to be able to wait for a DLL lock at slower clock speeds.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Acked-by: Kishon Vijay Abraham I <redacted>
quoted hunk
---
Changes in v2:
- Indicate that 5.1 ms is calculated (Shawn).
drivers/phy/phy-rockchip-emmc.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
From: Kishon Vijay Abraham I <hidden> Date: 2016-06-20 13:09:40
On Tuesday 14 June 2016 04:34 AM, Douglas Anderson wrote:
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>
Acked-by: Kishon Vijay Abraham I <redacted>
quoted hunk
---
Changes in v2:
- Warn if we're more than 15 MHz from ideal rate (Shawn)
- Move code cleanup before set phyctrl_frqsel based on card clock (Shawn)
- Fix typo USB => SDHCI (Shawn)
drivers/phy/phy-rockchip-emmc.c | 82 ++++++++++++++++++++++++++++++++++-------
1 file changed, 69 insertions(+), 13 deletions(-)
@@ -78,16 +79,73 @@structrockchip_emmc_phy{unsignedintreg_offset;structregmap*reg_base;+structclk*emmcclk;};-staticintrockchip_emmc_phy_power(structrockchip_emmc_phy*rk_phy,-boolon_off)+staticintrockchip_emmc_phy_power(structphy*phy,boolon_off){+structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);unsignedintcaldone;unsignedintdllrdy;+unsignedintfreqsel=PHYCTRL_FREQSEL_200M;unsignedlongtimeout;/*+*Wepurposelygettheclockhereandnotinprobetoavoidthe+*circulardependencyproblem.Weexpect:+*-PHYdrivertoprobe+*-SDHCIdrivertostartprobe+*-SDHCIdrivertoregisterit'sclock+*-SDHCIdrivertogetthePHY+*-SDHCIdrivertopoweronthePHY+*/+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)){+unsignedlongrate=clk_get_rate(rk_phy->emmcclk);+unsignedlongideal_rate;+unsignedlongdiff;++switch(rate){+case0...74999999:+ideal_rate=50000000;+freqsel=PHYCTRL_FREQSEL_50M;+break;+case75000000...124999999:+ideal_rate=100000000;+freqsel=PHYCTRL_FREQSEL_100M;+break;+case125000000...174999999:+ideal_rate=150000000;+freqsel=PHYCTRL_FREQSEL_150M;+break;+default:+ideal_rate=200000000;+break;+};++diff=(rate>ideal_rate)?+rate-ideal_rate:ideal_rate-rate;++/*+*Inorderfortuningdelaystobeaccurateweneedtobe+*prettyspotonfortheDLLrange,sowarnifwe'retoo+*faroff.Alsowarnifwe'reabovethe200MHzmax.Don't+*warnforreallyslowratessincewewon'tbetuningthen.+*/+if((rate>50000000&&diff>15000000)||(rate>200000000))+dev_warn(&phy->dev,"Unsupported rate: %lu\n",rate);+}++/**Keepphyctrl_pdbandphyctrl_endlllowtoallow*initializationofCALIOstateM/CDFFs*/
@@ -132,6 +190,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,
@@ -168,23 +233,14 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,staticintrockchip_emmc_phy_power_off(structphy*phy){-structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);-/* Power down emmc phy analog blocks */-returnrockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_OFF);+returnrockchip_emmc_phy_power(phy,PHYCTRL_PDB_PWR_OFF);}staticintrockchip_emmc_phy_power_on(structphy*phy){structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);-/* 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,rk_phy->reg_offset+GRF_EMMCPHY_CON6,
@@ -207,7 +263,7 @@ static int rockchip_emmc_phy_power_on(struct phy *phy)PHYCTRL_OTAPDLYSEL_SHIFT));/* Power up emmc phy analog blocks */-returnrockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_ON);+returnrockchip_emmc_phy_power(phy,PHYCTRL_PDB_PWR_ON);}staticconststructphy_opsops={
From: Kishon Vijay Abraham I <hidden> Date: 2016-06-20 13:14:00
On Tuesday 14 June 2016 04:34 AM, Douglas Anderson wrote:
There's no reason to store the return value of rockchip_emmc_phy_power()
in a variable nor to check it. Just return it.
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Acked-by: Kishon Vijay Abraham I <redacted>
quoted hunk
---
Changes in v2:
- Move code cleanup before set phyctrl_frqsel based on card clock (Shawn)
drivers/phy/phy-rockchip-emmc.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
@@ -169,20 +169,14 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,staticintrockchip_emmc_phy_power_off(structphy*phy){structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);-intret=0;/* Power down emmc phy analog blocks */-ret=rockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_OFF);-if(ret)-returnret;--return0;+returnrockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_OFF);}staticintrockchip_emmc_phy_power_on(structphy*phy){structrockchip_emmc_phy*rk_phy=phy_get_drvdata(phy);-intret=0;/* DLL operation: 200 MHz */regmap_write(rk_phy->reg_base,
@@ -213,11 +207,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);-if(ret)-returnret;--return0;+returnrockchip_emmc_phy_power(rk_phy,PHYCTRL_PDB_PWR_ON);}staticconststructphy_opsops={
From: Doug Anderson <dianders@chromium.org> Date: 2016-06-20 16:49:52
Heiko,
On Sat, Jun 18, 2016 at 5:20 AM, Heiko St?bner [off-list ref] wrote:
Am Montag, 13. Juni 2016, 16:04:34 schrieb Douglas Anderson:
quoted
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>
---
Changes in v2:
- Warn if we're more than 15 MHz from ideal rate (Shawn)
- Move code cleanup before set phyctrl_frqsel based on card clock (Shawn)
- Fix typo USB => SDHCI (Shawn)
drivers/phy/phy-rockchip-emmc.c | 82
++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+),
13 deletions(-)
diff --git a/drivers/phy/phy-rockchip-emmc.c
b/drivers/phy/phy-rockchip-emmc.c index 23fe50864526..51ddd543fd04 100644
Doesn't that leave open the unbind / removal case with that same circular
dependency? While true that the clock-framework does some special handling on
clk_unregister, I don't think this would catch multiple unbind/bind actions.
The emmc-phy would still hold on to the old clock-instance with the empty clk-
ops the ccf assigns, even when the rebind of the arasan-sdhci would create a
new clock.
How about using phy-init / phy-exit callbacks for that instead? (Aka clk_get
and clk_put the emmc clock in there instead of using the devm variant)
Using phy-init and phy-exit is perfect. I'll spin shortly.
quoted
+ 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)) {
you just made it NULL in the error case above?
Yeah. The idea was the if we happened to get a EPROBE_DEFER (should
never happen) we would continue on and just skip this part. In any
case, should be a moot point with the new version, which I'll send out
soon.
-Doug