[PATCH 2/2] ahci: imx: software workaround for phy reset issue in resume

Tejun Heo tj at kernel.org
Tue Apr 15 09:10:18 PDT 2014


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().

> +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?

...
> +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



More information about the linux-arm-kernel mailing list