drivers/usb/musb/omap2430.c

Source file repositories/reference/linux-study-clean/drivers/usb/musb/omap2430.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/musb/omap2430.c
Extension
.c
Size
15498 bytes
Lines
625
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 omap2430_glue {
	struct device		*dev;
	struct platform_device	*musb;
	enum musb_vbus_id_status status;
	struct work_struct	omap_musb_mailbox_work;
	struct device		*control_otghs;
	unsigned int		is_runtime_suspended:1;
	unsigned int		needs_resume:1;
	unsigned int		phy_suspended:1;
};
#define glue_to_musb(g)		platform_get_drvdata(g->musb)

static struct omap2430_glue	*_glue;

static inline void omap2430_low_level_exit(struct musb *musb)
{
	u32 l;

	/* in any role */
	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
	l |= ENABLEFORCE;	/* enable MSTANDBY */
	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}

static inline void omap2430_low_level_init(struct musb *musb)
{
	u32 l;

	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}

static int omap2430_musb_mailbox(enum musb_vbus_id_status status)
{
	struct omap2430_glue	*glue = _glue;

	if (!glue) {
		pr_err("%s: musb core is not yet initialized\n", __func__);
		return -EPROBE_DEFER;
	}
	glue->status = status;

	if (!glue_to_musb(glue)) {
		pr_err("%s: musb core is not yet ready\n", __func__);
		return -EPROBE_DEFER;
	}

	schedule_work(&glue->omap_musb_mailbox_work);

	return 0;
}

/*
 * HDRC controls CPEN, but beware current surges during device connect.
 * They can trigger transient overcurrent conditions that must be ignored.
 *
 * Note that we're skipping A_WAIT_VFALL -> A_IDLE and jumping right to B_IDLE
 * as set by musb_set_peripheral().
 */
static void omap_musb_set_mailbox(struct omap2430_glue *glue)
{
	struct musb *musb = glue_to_musb(glue);
	int error;

	pm_runtime_get_sync(musb->controller);

	dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
		usb_otg_state_string(musb->xceiv->otg->state),
		musb_readb(musb->mregs, MUSB_DEVCTL));

	switch (glue->status) {
	case MUSB_ID_GROUND:
		dev_dbg(musb->controller, "ID GND\n");
		switch (musb->xceiv->otg->state) {
		case OTG_STATE_A_IDLE:
			error = musb_set_host(musb);
			if (error)
				break;
			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
			fallthrough;
		case OTG_STATE_A_WAIT_VRISE:
		case OTG_STATE_A_WAIT_BCON:
		case OTG_STATE_A_HOST:
			/*
			 * On multiple ID ground interrupts just keep enabling
			 * VBUS. At least cpcap VBUS shuts down otherwise.
			 */
			otg_set_vbus(musb->xceiv->otg, 1);
			break;

Annotation

Implementation Notes