drivers/phy/marvell/phy-pxa-28nm-hsic.c

Source file repositories/reference/linux-study-clean/drivers/phy/marvell/phy-pxa-28nm-hsic.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/marvell/phy-pxa-28nm-hsic.c
Extension
.c
Size
5346 bytes
Lines
210
Domain
Driver Families
Bucket
drivers/phy
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mv_hsic_phy {
	struct phy		*phy;
	struct platform_device	*pdev;
	void __iomem		*base;
	struct clk		*clk;
};

static int wait_for_reg(void __iomem *reg, u32 mask, u32 ms)
{
	u32 val;

	return readl_poll_timeout(reg, val, ((val & mask) == mask),
				  1000, 1000 * ms);
}

static int mv_hsic_phy_init(struct phy *phy)
{
	struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
	struct platform_device *pdev = mv_phy->pdev;
	void __iomem *base = mv_phy->base;
	int ret;

	clk_prepare_enable(mv_phy->clk);

	/* Set reference clock */
	writel(0x1 << PHY_28NM_HSIC_PLL_SELLPFR_SHIFT |
		0xf0 << PHY_28NM_HSIC_PLL_FBDIV_SHIFT |
		0xd << PHY_28NM_HSIC_PLL_REFDIV_SHIFT,
		base + PHY_28NM_HSIC_PLL_CTRL01);

	/* Turn on PLL */
	writel(readl(base + PHY_28NM_HSIC_PLL_CTRL2) |
		PHY_28NM_HSIC_S2H_PU_PLL,
		base + PHY_28NM_HSIC_PLL_CTRL2);

	/* Make sure PHY PLL is locked */
	ret = wait_for_reg(base + PHY_28NM_HSIC_PLL_CTRL2,
			   PHY_28NM_HSIC_H2S_PLL_LOCK, 100);
	if (ret) {
		dev_err(&pdev->dev, "HSIC PHY PLL not locked after 100mS.");
		clk_disable_unprepare(mv_phy->clk);
	}

	return ret;
}

static int mv_hsic_phy_power_on(struct phy *phy)
{
	struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
	struct platform_device *pdev = mv_phy->pdev;
	void __iomem *base = mv_phy->base;
	u32 reg;
	int ret;

	reg = readl(base + PHY_28NM_HSIC_CTRL);
	/* Avoid SE0 state when resume for some device will take it as reset */
	reg &= ~S2H_DRV_SE0_4RESUME;
	reg |= PHY_28NM_HSIC_S2H_HSIC_EN;	/* Enable HSIC PHY */
	writel(reg, base + PHY_28NM_HSIC_CTRL);

	/*
	 *  Calibration Timing
	 *		   ____________________________
	 *  CAL START   ___|
	 *			   ____________________
	 *  CAL_DONE    ___________|
	 *		   | 400us |
	 */

	/* Make sure PHY Calibration is ready */
	ret = wait_for_reg(base + PHY_28NM_HSIC_IMPCAL_CAL,
			   PHY_28NM_HSIC_H2S_IMPCAL_DONE, 100);
	if (ret) {
		dev_warn(&pdev->dev, "HSIC PHY READY not set after 100mS.");
		return ret;
	}

	/* Waiting for HSIC connect int*/
	ret = wait_for_reg(base + PHY_28NM_HSIC_INT,
			   PHY_28NM_HSIC_CONNECT_INT, 200);
	if (ret)
		dev_warn(&pdev->dev, "HSIC wait for connect interrupt timeout.");

	return ret;
}

static int mv_hsic_phy_power_off(struct phy *phy)
{
	struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy);
	void __iomem *base = mv_phy->base;

Annotation

Implementation Notes