drivers/phy/marvell/phy-berlin-usb.c

Source file repositories/reference/linux-study-clean/drivers/phy/marvell/phy-berlin-usb.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/marvell/phy-berlin-usb.c
Extension
.c
Size
6011 bytes
Lines
209
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 phy_berlin_usb_priv {
	void __iomem		*base;
	struct reset_control	*rst_ctrl;
	u32			pll_divider;
};

static int phy_berlin_usb_power_on(struct phy *phy)
{
	struct phy_berlin_usb_priv *priv = phy_get_drvdata(phy);

	reset_control_reset(priv->rst_ctrl);

	writel(priv->pll_divider,
	       priv->base + USB_PHY_PLL);
	writel(CLK_STABLE | PLL_CTRL_REG | PHASE_OFF_TOL_250 | KVC0_REG_CTRL |
	       CLK_BLK_EN, priv->base + USB_PHY_PLL_CONTROL);
	writel(V2I_VCO_RATIO(0x5) | R_ROTATE_0 | ANA_TEST_DC_CTRL(0x5),
	       priv->base + USB_PHY_ANALOG);
	writel(PHASE_FREEZE_DLY_4_CL | ACK_LENGTH_16_CL | SQ_LENGTH_12 |
	       DISCON_THRESHOLD_270 | SQ_THRESHOLD(0xa) | LPF_COEF(0x2) |
	       INTPL_CUR_30, priv->base + USB_PHY_RX_CTRL);

	writel(TX_VDD12_13 | TX_OUT_AMP(0x3), priv->base + USB_PHY_TX_CTRL1);
	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
	       priv->base + USB_PHY_TX_CTRL0);

	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4) |
	       EXT_FS_RCAL_DIV(0x2), priv->base + USB_PHY_TX_CTRL0);

	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
	       priv->base + USB_PHY_TX_CTRL0);
	writel(TX_CHAN_CTRL_REG(0xf) | DRV_SLEWRATE(0x3) | IMP_CAL_FS_HS_DLY_3 |
	       FS_DRV_EN_MASK(0xd), priv->base + USB_PHY_TX_CTRL2);

	return 0;
}

static const struct phy_ops phy_berlin_usb_ops = {
	.power_on	= phy_berlin_usb_power_on,
	.owner		= THIS_MODULE,
};

static const struct of_device_id phy_berlin_usb_of_match[] = {
	{
		.compatible = "marvell,berlin2-usb-phy",
		.data = &phy_berlin_pll_dividers[0],
	},
	{
		.compatible = "marvell,berlin2cd-usb-phy",
		.data = &phy_berlin_pll_dividers[1],
	},
	{ },
};
MODULE_DEVICE_TABLE(of, phy_berlin_usb_of_match);

static int phy_berlin_usb_probe(struct platform_device *pdev)
{
	struct phy_berlin_usb_priv *priv;
	struct phy *phy;
	struct phy_provider *phy_provider;

	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	priv->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(priv->base))
		return PTR_ERR(priv->base);

	priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL);
	if (IS_ERR(priv->rst_ctrl))
		return PTR_ERR(priv->rst_ctrl);

	priv->pll_divider = *((u32 *)device_get_match_data(&pdev->dev));

	phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops);
	if (IS_ERR(phy)) {
		dev_err(&pdev->dev, "failed to create PHY\n");
		return PTR_ERR(phy);
	}

	phy_set_drvdata(phy, priv);

	phy_provider =
		devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
	return PTR_ERR_OR_ZERO(phy_provider);
}

static struct platform_driver phy_berlin_usb_driver = {
	.probe	= phy_berlin_usb_probe,

Annotation

Implementation Notes