drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c

Source file repositories/reference/linux-study-clean/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c
Extension
.c
Size
11231 bytes
Lines
448
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_g12a_usb3_pcie_priv {
	struct regmap		*regmap;
	struct regmap		*regmap_cr;
	struct clk		*clk_ref;
	struct reset_control	*reset;
	struct phy		*phy;
	unsigned int		mode;
};

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

static int phy_g12a_usb3_pcie_cr_bus_addr(struct phy_g12a_usb3_pcie_priv *priv,
					  unsigned int addr)
{
	unsigned int val, reg;
	int ret;

	reg = FIELD_PREP(PHY_R4_PHY_CR_DATA_IN, addr);

	regmap_write(priv->regmap, PHY_R4, reg);
	regmap_write(priv->regmap, PHY_R4, reg);

	regmap_write(priv->regmap, PHY_R4, reg | PHY_R4_PHY_CR_CAP_ADDR);

	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
				       (val & PHY_R5_PHY_CR_ACK),
				       5, 1000);
	if (ret)
		return ret;

	regmap_write(priv->regmap, PHY_R4, reg);

	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
				       !(val & PHY_R5_PHY_CR_ACK),
				       5, 1000);
	if (ret)
		return ret;

	return 0;
}

static int phy_g12a_usb3_pcie_cr_bus_read(void *context, unsigned int addr,
					  unsigned int *data)
{
	struct phy_g12a_usb3_pcie_priv *priv = context;
	unsigned int val;
	int ret;

	ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr);
	if (ret)
		return ret;

	regmap_write(priv->regmap, PHY_R4, 0);
	regmap_write(priv->regmap, PHY_R4, PHY_R4_PHY_CR_READ);

	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
				       (val & PHY_R5_PHY_CR_ACK),
				       5, 1000);
	if (ret)
		return ret;

	*data = FIELD_GET(PHY_R5_PHY_CR_DATA_OUT, val);

	regmap_write(priv->regmap, PHY_R4, 0);

	ret = regmap_read_poll_timeout(priv->regmap, PHY_R5, val,
				       !(val & PHY_R5_PHY_CR_ACK),
				       5, 1000);
	if (ret)
		return ret;

	return 0;
}

static int phy_g12a_usb3_pcie_cr_bus_write(void *context, unsigned int addr,
					   unsigned int data)
{
	struct phy_g12a_usb3_pcie_priv *priv = context;
	unsigned int val, reg;
	int ret;

	ret = phy_g12a_usb3_pcie_cr_bus_addr(priv, addr);
	if (ret)
		return ret;

Annotation

Implementation Notes