drivers/usb/phy/phy-tahvo.c

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

File Facts

System
Linux kernel
Corpus path
drivers/usb/phy/phy-tahvo.c
Extension
.c
Size
10839 bytes
Lines
440
Domain
Driver Families
Bucket
drivers/usb
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 tahvo_usb {
	struct platform_device	*pt_dev;
	struct usb_phy		phy;
	int			vbus_state;
	struct mutex		serialize;
	struct clk		*ick;
	int			irq;
	int			tahvo_mode;
	struct extcon_dev	*extcon;
};

static const unsigned int tahvo_cable[] = {
	EXTCON_USB,
	EXTCON_USB_HOST,

	EXTCON_NONE,
};

static ssize_t vbus_show(struct device *device,
			       struct device_attribute *attr, char *buf)
{
	struct tahvo_usb *tu = dev_get_drvdata(device);
	return sprintf(buf, "%s\n", str_on_off(tu->vbus_state));
}
static DEVICE_ATTR_RO(vbus);

static void check_vbus_state(struct tahvo_usb *tu)
{
	struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
	int reg, prev_state;

	reg = retu_read(rdev, TAHVO_REG_IDSR);
	if (reg & TAHVO_STAT_VBUS) {
		switch (tu->phy.otg->state) {
		case OTG_STATE_B_IDLE:
			/* Enable the gadget driver */
			if (tu->phy.otg->gadget)
				usb_gadget_vbus_connect(tu->phy.otg->gadget);
			tu->phy.otg->state = OTG_STATE_B_PERIPHERAL;
			usb_phy_set_event(&tu->phy, USB_EVENT_ENUMERATED);
			break;
		case OTG_STATE_A_IDLE:
			/*
			 * Session is now valid assuming the USB hub is driving
			 * Vbus.
			 */
			tu->phy.otg->state = OTG_STATE_A_HOST;
			break;
		default:
			break;
		}
		dev_info(&tu->pt_dev->dev, "USB cable connected\n");
	} else {
		switch (tu->phy.otg->state) {
		case OTG_STATE_B_PERIPHERAL:
			if (tu->phy.otg->gadget)
				usb_gadget_vbus_disconnect(tu->phy.otg->gadget);
			tu->phy.otg->state = OTG_STATE_B_IDLE;
			usb_phy_set_event(&tu->phy, USB_EVENT_NONE);
			break;
		case OTG_STATE_A_HOST:
			tu->phy.otg->state = OTG_STATE_A_IDLE;
			break;
		default:
			break;
		}
		dev_info(&tu->pt_dev->dev, "USB cable disconnected\n");
	}

	prev_state = tu->vbus_state;
	tu->vbus_state = reg & TAHVO_STAT_VBUS;
	if (prev_state != tu->vbus_state) {
		extcon_set_state_sync(tu->extcon, EXTCON_USB, tu->vbus_state);
		sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state");
	}
}

static void tahvo_usb_become_host(struct tahvo_usb *tu)
{
	struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);

	extcon_set_state_sync(tu->extcon, EXTCON_USB_HOST, true);

	/* Power up the transceiver in USB host mode */
	retu_write(rdev, TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND |
		   USBR_MASTER_SW2 | USBR_MASTER_SW1);
	tu->phy.otg->state = OTG_STATE_A_IDLE;

	check_vbus_state(tu);
}

Annotation

Implementation Notes