drivers/phy/qualcomm/phy-qcom-ipq806x-usb.c

Source file repositories/reference/linux-study-clean/drivers/phy/qualcomm/phy-qcom-ipq806x-usb.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/qualcomm/phy-qcom-ipq806x-usb.c
Extension
.c
Size
15847 bytes
Lines
566
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 usb_phy {
	void __iomem		*base;
	struct device		*dev;
	struct clk		*xo_clk;
	struct clk		*ref_clk;
	u32			rx_eq;
	u32			tx_deamp_3_5db;
	u32			mpll;
};

struct phy_drvdata {
	struct phy_ops	ops;
	u32		clk_rate;
};

/**
 * usb_phy_write_readback() - Write register and read back masked value to
 * confirm it is written
 *
 * @phy_dwc3: QCOM DWC3 phy context
 * @offset: register offset.
 * @mask: register bitmask specifying what should be updated
 * @val: value to write.
 */
static inline void usb_phy_write_readback(struct usb_phy *phy_dwc3,
					  u32 offset,
					  const u32 mask, u32 val)
{
	u32 write_val, tmp = readl(phy_dwc3->base + offset);

	tmp &= ~mask;		/* retain other bits */
	write_val = tmp | val;

	writel(write_val, phy_dwc3->base + offset);

	/* Read back to see if val was written */
	tmp = readl(phy_dwc3->base + offset);
	tmp &= mask;		/* clear other bits */

	if (tmp != val)
		dev_err(phy_dwc3->dev, "write: %x to QSCRATCH: %x FAILED\n", val, offset);
}

static int wait_for_latch(void __iomem *addr)
{
	u32 val;

	return readl_poll_timeout(addr, val, !val, LATCH_SLEEP, LATCH_TIMEOUT);
}

/**
 * usb_ss_write_phycreg() - Write SSPHY register
 *
 * @phy_dwc3: QCOM DWC3 phy context
 * @addr: SSPHY address to write.
 * @val: value to write.
 */
static int usb_ss_write_phycreg(struct usb_phy *phy_dwc3,
				u32 addr, u32 val)
{
	int ret;

	writel(addr, phy_dwc3->base + CR_PROTOCOL_DATA_IN_REG);
	writel(SS_CR_CAP_ADDR_REG,
	       phy_dwc3->base + CR_PROTOCOL_CAP_ADDR_REG);

	ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_CAP_ADDR_REG);
	if (ret)
		goto err_wait;

	writel(val, phy_dwc3->base + CR_PROTOCOL_DATA_IN_REG);
	writel(SS_CR_CAP_DATA_REG,
	       phy_dwc3->base + CR_PROTOCOL_CAP_DATA_REG);

	ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_CAP_DATA_REG);
	if (ret)
		goto err_wait;

	writel(SS_CR_WRITE_REG, phy_dwc3->base + CR_PROTOCOL_WRITE_REG);

	ret = wait_for_latch(phy_dwc3->base + CR_PROTOCOL_WRITE_REG);

err_wait:
	if (ret)
		dev_err(phy_dwc3->dev, "timeout waiting for latch\n");
	return ret;
}

/**
 * usb_ss_read_phycreg() - Read SSPHY register.

Annotation

Implementation Notes