drivers/phy/broadcom/phy-brcm-usb.c

Source file repositories/reference/linux-study-clean/drivers/phy/broadcom/phy-brcm-usb.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/broadcom/phy-brcm-usb.c
Extension
.c
Size
17479 bytes
Lines
697
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 value_to_name_map {
	int value;
	const char *name;
};

struct match_chip_info {
	void (*init_func)(struct brcm_usb_init_params *params);
	u8 required_regs[BRCM_REGS_MAX + 1];
	u8 optional_reg;
};

static const struct value_to_name_map brcm_dr_mode_to_name[] = {
	{ USB_CTLR_MODE_HOST, "host" },
	{ USB_CTLR_MODE_DEVICE, "peripheral" },
	{ USB_CTLR_MODE_DRD, "drd" },
	{ USB_CTLR_MODE_TYPEC_PD, "typec-pd" }
};

static const struct value_to_name_map brcm_dual_mode_to_name[] = {
	{ 0, "host" },
	{ 1, "device" },
	{ 2, "auto" },
};

struct brcm_usb_phy {
	struct phy *phy;
	unsigned int id;
	bool inited;
};

struct brcm_usb_phy_data {
	struct  brcm_usb_init_params ini;
	bool			has_eohci;
	bool			has_xhci;
	struct clk		*usb_20_clk;
	struct clk		*usb_30_clk;
	struct clk		*suspend_clk;
	struct mutex		mutex;	/* serialize phy init */
	int			init_count;
	int			wake_irq;
	struct brcm_usb_phy	phys[BRCM_USB_PHY_ID_MAX];
	struct notifier_block	pm_notifier;
	bool			pm_active;
};

static s8 *node_reg_names[BRCM_REGS_MAX] = {
	"crtl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec"
};

static int brcm_pm_notifier(struct notifier_block *notifier,
			    unsigned long pm_event,
			    void *unused)
{
	struct brcm_usb_phy_data *priv =
		container_of(notifier, struct brcm_usb_phy_data, pm_notifier);

	switch (pm_event) {
	case PM_HIBERNATION_PREPARE:
	case PM_SUSPEND_PREPARE:
		priv->pm_active = true;
		break;
	case PM_POST_RESTORE:
	case PM_POST_HIBERNATION:
	case PM_POST_SUSPEND:
		priv->pm_active = false;
		break;
	}
	return NOTIFY_DONE;
}

static irqreturn_t brcm_usb_phy_wake_isr(int irq, void *dev_id)
{
	struct device *dev = dev_id;

	pm_wakeup_event(dev, 0);

	return IRQ_HANDLED;
}

static int brcm_usb_phy_init(struct phy *gphy)
{
	struct brcm_usb_phy *phy = phy_get_drvdata(gphy);
	struct brcm_usb_phy_data *priv =
		container_of(phy, struct brcm_usb_phy_data, phys[phy->id]);

	if (priv->pm_active)
		return 0;

	/*
	 * Use a lock to make sure a second caller waits until

Annotation

Implementation Notes