drivers/phy/starfive/phy-jh7110-usb.c

Source file repositories/reference/linux-study-clean/drivers/phy/starfive/phy-jh7110-usb.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/starfive/phy-jh7110-usb.c
Extension
.c
Size
4391 bytes
Lines
176
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 jh7110_usb2_phy {
	struct phy *phy;
	void __iomem *regs;
	struct regmap *sys_syscon;
	struct clk *usb_125m_clk;
	struct clk *app_125m;
	enum phy_mode mode;
};

static void usb2_set_ls_keepalive(struct jh7110_usb2_phy *phy, bool set)
{
	unsigned int val;

	/* Host mode enable the LS speed keep-alive signal */
	val = readl(phy->regs + USB_LS_KEEPALIVE_OFF);
	if (set)
		val |= USB_LS_KEEPALIVE_ENABLE;
	else
		val &= ~USB_LS_KEEPALIVE_ENABLE;

	writel(val, phy->regs + USB_LS_KEEPALIVE_OFF);
}

static int usb2_phy_set_mode(struct phy *_phy,
			     enum phy_mode mode, int submode)
{
	struct jh7110_usb2_phy *phy = phy_get_drvdata(_phy);

	switch (mode) {
	case PHY_MODE_USB_HOST:
	case PHY_MODE_USB_DEVICE:
	case PHY_MODE_USB_OTG:
		break;
	default:
		return -EINVAL;
	}

	if (mode != phy->mode) {
		dev_dbg(&_phy->dev, "Changing phy to %d\n", mode);
		phy->mode = mode;
		usb2_set_ls_keepalive(phy, (mode != PHY_MODE_USB_DEVICE));
	}

	/* Connect usb 2.0 phy mode */
	regmap_update_bits(phy->sys_syscon, SYSCON_USB_SPLIT_OFFSET,
			   USB_PDRSTN_SPLIT, USB_PDRSTN_SPLIT);

	return 0;
}

static int jh7110_usb2_phy_init(struct phy *_phy)
{
	struct jh7110_usb2_phy *phy = phy_get_drvdata(_phy);
	int ret;
	unsigned int val;

	ret = clk_set_rate(phy->usb_125m_clk, USB_125M_CLK_RATE);
	if (ret)
		return ret;

	ret = clk_prepare_enable(phy->app_125m);
	if (ret)
		return ret;

	val = readl(phy->regs + USB_CLK_MODE_OFF);
	val |= USB_CLK_MODE_RX_NORMAL_PWR;
	writel(val, phy->regs + USB_CLK_MODE_OFF);

	return 0;
}

static int jh7110_usb2_phy_exit(struct phy *_phy)
{
	struct jh7110_usb2_phy *phy = phy_get_drvdata(_phy);

	clk_disable_unprepare(phy->app_125m);

	return 0;
}

static const struct phy_ops jh7110_usb2_phy_ops = {
	.init		= jh7110_usb2_phy_init,
	.exit		= jh7110_usb2_phy_exit,
	.set_mode	= usb2_phy_set_mode,
	.owner		= THIS_MODULE,
};

static int jh7110_usb_phy_probe(struct platform_device *pdev)
{
	struct jh7110_usb2_phy *phy;

Annotation

Implementation Notes