drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c

Source file repositories/reference/linux-study-clean/drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c
Extension
.c
Size
10980 bytes
Lines
417
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 ns2_phy_driver {
	void __iomem *icfgdrd_regs;
	void __iomem *idmdrd_rst_ctrl;
	void __iomem *crmu_usb2_ctrl;
	void __iomem *usb2h_strap_reg;
	struct ns2_phy_data *data;
	struct extcon_dev *edev;
	struct gpio_desc *vbus_gpiod;
	struct gpio_desc *id_gpiod;
	int id_irq;
	int vbus_irq;
	unsigned long debounce_jiffies;
	struct delayed_work wq_extcon;
};

struct ns2_phy_data {
	struct ns2_phy_driver *driver;
	struct phy *phy;
	int new_state;
};

static const unsigned int usb_extcon_cable[] = {
	EXTCON_USB,
	EXTCON_USB_HOST,
	EXTCON_NONE,
};

static inline int pll_lock_stat(u32 usb_reg, int reg_mask,
				struct ns2_phy_driver *driver)
{
	u32 val;

	return readl_poll_timeout_atomic(driver->icfgdrd_regs + usb_reg,
					 val, (val & reg_mask), 1,
					 PLL_LOCK_RETRY);
}

static int ns2_drd_phy_init(struct phy *phy)
{
	struct ns2_phy_data *data = phy_get_drvdata(phy);
	struct ns2_phy_driver *driver = data->driver;
	u32 val;

	val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);

	if (data->new_state == EVT_HOST) {
		val &= ~DRD_DEVICE_MODE;
		val |= DRD_HOST_MODE;
	} else {
		val &= ~DRD_HOST_MODE;
		val |= DRD_DEVICE_MODE;
	}
	writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);

	return 0;
}

static int ns2_drd_phy_poweroff(struct phy *phy)
{
	struct ns2_phy_data *data = phy_get_drvdata(phy);
	struct ns2_phy_driver *driver = data->driver;
	u32 val;

	val = readl(driver->crmu_usb2_ctrl);
	val &= ~AFE_CORERDY_VDDC;
	writel(val, driver->crmu_usb2_ctrl);

	val = readl(driver->crmu_usb2_ctrl);
	val &= ~DRD_DEV_MODE;
	writel(val, driver->crmu_usb2_ctrl);

	/* Disable Host and Device Mode */
	val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
	val &= ~(DRD_HOST_MODE | DRD_DEVICE_MODE | ICFG_OFF_MODE);
	writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);

	return 0;
}

static int ns2_drd_phy_poweron(struct phy *phy)
{
	struct ns2_phy_data *data = phy_get_drvdata(phy);
	struct ns2_phy_driver *driver = data->driver;
	u32 extcon_event = data->new_state;
	int ret;
	u32 val;

	if (extcon_event == EVT_DEVICE) {
		writel(DRD_DEV_VAL, driver->icfgdrd_regs + ICFG_DRD_P0CTL);

Annotation

Implementation Notes