drivers/phy/amlogic/phy-meson-gxl-usb2.c

Source file repositories/reference/linux-study-clean/drivers/phy/amlogic/phy-meson-gxl-usb2.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/amlogic/phy-meson-gxl-usb2.c
Extension
.c
Size
8288 bytes
Lines
297
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_meson_gxl_usb2_priv {
	struct regmap		*regmap;
	enum phy_mode		mode;
	int			is_enabled;
	struct clk		*clk;
	struct reset_control	*reset;
};

static const struct regmap_config phy_meson_gxl_usb2_regmap_conf = {
	.reg_bits = 8,
	.val_bits = 32,
	.reg_stride = 4,
	.max_register = U2P_R3,
};

static int phy_meson_gxl_usb2_init(struct phy *phy)
{
	struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);
	int ret;

	ret = reset_control_reset(priv->reset);
	if (ret)
		return ret;

	ret = clk_prepare_enable(priv->clk);
	if (ret) {
		reset_control_rearm(priv->reset);
		return ret;
	}

	return 0;
}

static int phy_meson_gxl_usb2_exit(struct phy *phy)
{
	struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);

	clk_disable_unprepare(priv->clk);
	reset_control_rearm(priv->reset);

	return 0;
}

static int phy_meson_gxl_usb2_reset(struct phy *phy)
{
	struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);

	if (priv->is_enabled) {
		/* reset the PHY and wait until settings are stabilized */
		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
				   U2P_R0_POWER_ON_RESET);
		udelay(RESET_COMPLETE_TIME);
		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET,
				   0);
		udelay(RESET_COMPLETE_TIME);
	}

	return 0;
}

static int phy_meson_gxl_usb2_set_mode(struct phy *phy,
				       enum phy_mode mode, int submode)
{
	struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy);

	switch (mode) {
	case PHY_MODE_USB_HOST:
	case PHY_MODE_USB_OTG:
		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN,
				   U2P_R0_DM_PULLDOWN);
		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN,
				   U2P_R0_DP_PULLDOWN);
		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP,
				   U2P_R0_ID_PULLUP);
		break;

	case PHY_MODE_USB_DEVICE:
		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN,
				   0);
		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN,
				   0);
		regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP,
				   U2P_R0_ID_PULLUP);
		break;

	default:
		return -EINVAL;
	}

	phy_meson_gxl_usb2_reset(phy);

Annotation

Implementation Notes