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
>
>
next prev parent 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).