drivers/phy/ti/phy-dm816x-usb.c

Source file repositories/reference/linux-study-clean/drivers/phy/ti/phy-dm816x-usb.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/ti/phy-dm816x-usb.c
Extension
.c
Size
7089 bytes
Lines
275
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 dm816x_usb_phy {
	struct regmap *syscon;
	struct device *dev;
	unsigned int instance;
	struct clk *refclk;
	struct usb_phy phy;
	unsigned int usb_ctrl;		/* Shared between phy0 and phy1 */
	unsigned int usbphy_ctrl;
};

static int dm816x_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host)
{
	otg->host = host;
	if (!host)
		otg->state = OTG_STATE_UNDEFINED;

	return 0;
}

static int dm816x_usb_phy_set_peripheral(struct usb_otg *otg,
					 struct usb_gadget *gadget)
{
	otg->gadget = gadget;
	if (!gadget)
		otg->state = OTG_STATE_UNDEFINED;

	return 0;
}

static int dm816x_usb_phy_init(struct phy *x)
{
	struct dm816x_usb_phy *phy = phy_get_drvdata(x);
	unsigned int val;

	if (clk_get_rate(phy->refclk) != 24000000)
		dev_warn(phy->dev, "nonstandard phy refclk\n");

	/* Set PLL ref clock and put phys to sleep */
	regmap_update_bits(phy->syscon, phy->usb_ctrl,
			   DM816X_USB_CTRL_PHYCLKSRC |
			   DM816X_USB_CTRL_PHYSLEEP1 |
			   DM816X_USB_CTRL_PHYSLEEP0,
			   0);
	regmap_read(phy->syscon, phy->usb_ctrl, &val);
	if ((val & 3) != 0)
		dev_info(phy->dev,
			 "Working dm816x USB_CTRL! (0x%08x)\n",
			 val);

	/*
	 * TI kernel sets these values for "symmetrical eye diagram and
	 * better signal quality" so let's assume somebody checked the
	 * values with a scope and set them here too.
	 */
	regmap_read(phy->syscon, phy->usbphy_ctrl, &val);
	val |= DM816X_USBPHY_CTRL_TXRISETUNE |
		DM816X_USBPHY_CTRL_TXVREFTUNE |
		DM816X_USBPHY_CTRL_TXPREEMTUNE;
	regmap_write(phy->syscon, phy->usbphy_ctrl, val);

	return 0;
}

static const struct phy_ops ops = {
	.init		= dm816x_usb_phy_init,
	.owner		= THIS_MODULE,
};

static int __maybe_unused dm816x_usb_phy_runtime_suspend(struct device *dev)
{
	struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
	unsigned int mask, val;
	int error = 0;

	mask = BIT(phy->instance);
	val = ~BIT(phy->instance);
	error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
				   mask, val);
	if (error)
		dev_err(phy->dev, "phy%i failed to power off\n",
			phy->instance);
	clk_disable(phy->refclk);

	return 0;
}

static int __maybe_unused dm816x_usb_phy_runtime_resume(struct device *dev)
{
	struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
	unsigned int mask, val;

Annotation

Implementation Notes