linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: shawn.guo@freescale.com (Shawn Guo)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/2] ahci: imx: software workaround for phy reset issue in resume
Date: Wed, 16 Apr 2014 15:38:24 +0800	[thread overview]
Message-ID: <20140416073823.GJ2523@dragon> (raw)
In-Reply-To: <20140415161018.GN1863@htj.dyndns.org>

On Tue, Apr 15, 2014 at 12:10:18PM -0400, Tejun Heo wrote:
> On Tue, Apr 15, 2014 at 10:41:43AM +0800, Shawn Guo wrote:
> > +static int imx_phy_ack_polling(void __iomem *mmio, bool assert)
> > +{
> > +	int timeout = 100;
> > +	u32 srval;
> > +
> > +	do {
> > +		srval = readl(mmio + IMX_SATA_P0PHYSR);
> > +		if ((assert ? srval : ~srval) & P0PHYSR_CR_ACK)
> > +			break;
> > +		usleep_range(100, 200);
> 
> What's up with usleep_range() these days?  There's no point in polling
> in sub-msec intervals.  Let's please stick to msleep().

The hardware manual suggests that an ACK will normally be given within
100us.  So using msleep() will have it sleep longer than necessary for
normal case.  Basically, we're following the suggestion from
Documentation/timers/timers-howto.txt to use usleep_range() over
msleep().

SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms):
	* Use usleep_range

	- Why not msleep for (1ms - 20ms)?
		Explained originally here:
			http://lkml.org/lkml/2007/8/3/250
		msleep(1~20) may not do what the caller intends, and
		will often sleep longer (~20 ms actual sleep for any
		value given in the 1~20ms range). In many cases this
		is not the desired behavior.

> 
> > +static int imx_phy_reg_addressing(u16 addr, void __iomem *mmio)
> > +{
> > +	u32 crval = addr;
> > +	int ret;
> > +
> > +	/* 1. Supply the address on cr_data_in */
> > +	writel(crval, mmio + IMX_SATA_P0PHYCR);
> > +
> > +	/* 2. Assert the cr_cap_addr signal */
> > +	crval |= P0PHYCR_CR_CAP_ADDR;
> > +	writel(crval, mmio + IMX_SATA_P0PHYCR);
> > +
> > +	/* 3. Wait for the cr_ack signal to be asserted */
> > +	ret = imx_phy_ack_polling(mmio, true);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* 4. Deassert cr_cap_addr */
> > +	crval &= ~P0PHYCR_CR_CAP_ADDR;
> > +	writel(crval, mmio + IMX_SATA_P0PHYCR);
> > +
> > +	/* 5. Wait for cr_ack to be deasserted */
> > +	ret = imx_phy_ack_polling(mmio, false);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return 0;
> > +}
> 
> Wouldn't folding comment 3 and 5 into 2 and 4 respectively make it
> easier on the eyes?  They're single operations anyway.
> 
> > +static int imx_phy_reg_write(u16 val, void __iomem *mmio)
> > +{
> ...
> > +}
> 
> Ditto.  Also, maybe it'd be better to create a wrapper to assert/clear
> and wait for ack?

I was writing the code in the exact steps documented in the hardware
manual.  But your comment makes a lot of sense to me, so I will create
such a wrapper to make it easier on the eyes.

Thanks, Tejun.

Shawn

> 
> ...
> > +static int imx_sata_phy_reset(struct ahci_host_priv *hpriv)
> > +{
> > +	void __iomem *mmio = hpriv->mmio;
> > +	int timeout = 10;
> > +	u16 val;
> > +	int ret;
> > +
> > +	/* Reset SATA PHY by setting RESET bit of PHY register CLOCK_RESET */
> > +	ret = imx_phy_reg_addressing(IMX_PHY_CLOCK_RESET, mmio);
> > +	if (ret)
> > +		return ret;
> > +	/*
> > +	 * For phy reset operation, we skip the timeout checking, because phy
> > +	 * will be unable to acknowledge in this case.
> > +	 */
> > +	imx_phy_reg_write(CLOCK_RESET_RESET, mmio);
> > +
> > +	usleep_range(100, 200);
> > +
> > +	/* Wait for PHY RX_PLL to be stable */
> > +	do {
> > +		ret = imx_phy_reg_addressing(IMX_PHY_LANE0_OUT_STAT, mmio);
> > +		if (ret)
> > +			return ret;
> > +		ret = imx_phy_reg_read(&val, mmio);
> > +		if (ret)
> > +			return ret;
> > +		if (val & LANE0_OUT_STAT_RX_PLL_STATE)
> > +			break;
> > +		usleep_range(100, 200);
> 
> Ditto with above.
> 
> Thanks.
> 
> -- 
> tejun
> 
> 

  reply	other threads:[~2014-04-16  7:38 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-15  2:41 [PATCH 1/2] ahci: imx: use macros to define registers and bits Shawn Guo
2014-04-15  2:41 ` [PATCH 2/2] ahci: imx: software workaround for phy reset issue in resume Shawn Guo
2014-04-15  3:19   ` Fabio Estevam
2014-04-15 16:10   ` Tejun Heo
2014-04-16  7:38     ` Shawn Guo [this message]
2014-04-16 14:01       ` Tejun Heo
2014-04-17  2:05         ` Shawn Guo
2014-04-15 16:03 ` [PATCH 1/2] ahci: imx: use macros to define registers and bits Tejun Heo
2014-04-16  6:35   ` Shawn Guo
2014-04-16 13:57     ` Tejun Heo
2014-04-16  7:59 ` Uwe Kleine-König
2014-04-16  8:08   ` Shawn Guo

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=20140416073823.GJ2523@dragon \
    --to=shawn.guo@freescale.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).