drivers/usb/gadget/udc/aspeed-vhub/core.c

Source file repositories/reference/linux-study-clean/drivers/usb/gadget/udc/aspeed-vhub/core.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/gadget/udc/aspeed-vhub/core.c
Extension
.c
Size
11956 bytes
Lines
472
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

if (ep_acks & mask) {
				ast_vhub_epn_ack_irq(&vhub->epns[i]);
				ep_acks &= ~mask;
			}
		}
	}

	/* Handle device interrupts */
	if (istat & vhub->port_irq_mask) {
		for (i = 0; i < vhub->max_ports; i++) {
			if (istat & VHUB_DEV_IRQ(i))
				ast_vhub_dev_irq(&vhub->ports[i].dev);
		}
	}

	/* Handle top-level vHub EP0 interrupts */
	if (istat & (VHUB_IRQ_HUB_EP0_OUT_ACK_STALL |
		     VHUB_IRQ_HUB_EP0_IN_ACK_STALL |
		     VHUB_IRQ_HUB_EP0_SETUP)) {
		if (istat & VHUB_IRQ_HUB_EP0_IN_ACK_STALL)
			ast_vhub_ep0_handle_ack(&vhub->ep0, true);
		if (istat & VHUB_IRQ_HUB_EP0_OUT_ACK_STALL)
			ast_vhub_ep0_handle_ack(&vhub->ep0, false);
		if (istat & VHUB_IRQ_HUB_EP0_SETUP)
			ast_vhub_ep0_handle_setup(&vhub->ep0);
	}

	/* Various top level bus events */
	if (istat & (VHUB_IRQ_BUS_RESUME |
		     VHUB_IRQ_BUS_SUSPEND |
		     VHUB_IRQ_BUS_RESET)) {
		if (istat & VHUB_IRQ_BUS_RESUME)
			ast_vhub_hub_resume(vhub);
		if (istat & VHUB_IRQ_BUS_SUSPEND)
			ast_vhub_hub_suspend(vhub);
		if (istat & VHUB_IRQ_BUS_RESET)
			ast_vhub_hub_reset(vhub);
	}

 bail:
	spin_unlock(&vhub->lock);
	return iret;
}

void ast_vhub_init_hw(struct ast_vhub *vhub)
{
	u32 ctrl, port_mask, epn_mask;

	UDCDBG(vhub,"(Re)Starting HW ...\n");

	/* Enable PHY */
	ctrl = VHUB_CTRL_PHY_CLK |
		VHUB_CTRL_PHY_RESET_DIS;

       /*
	* We do *NOT* set the VHUB_CTRL_CLK_STOP_SUSPEND bit
	* to stop the logic clock during suspend because
	* it causes the registers to become inaccessible and
	* we haven't yet figured out a good wayt to bring the
	* controller back into life to issue a wakeup.
	*/

	/*
	 * Set some ISO & split control bits according to Aspeed
	 * recommendation
	 *
	 * VHUB_CTRL_ISO_RSP_CTRL: When set tells the HW to respond
	 * with 0 bytes data packet to ISO IN endpoints when no data
	 * is available.
	 *
	 * VHUB_CTRL_SPLIT_IN: This makes a SOF complete a split IN
	 * transaction.
	 */
	ctrl |= VHUB_CTRL_ISO_RSP_CTRL | VHUB_CTRL_SPLIT_IN;
	writel(ctrl, vhub->regs + AST_VHUB_CTRL);
	udelay(1);

	/* Set descriptor ring size */
	if (AST_VHUB_DESCS_COUNT == 256) {
		ctrl |= VHUB_CTRL_LONG_DESC;
		writel(ctrl, vhub->regs + AST_VHUB_CTRL);
	} else {
		BUILD_BUG_ON(AST_VHUB_DESCS_COUNT != 32);
	}

	/* Reset all devices */
	port_mask = GENMASK(vhub->max_ports, 1);
	writel(VHUB_SW_RESET_ROOT_HUB |
	       VHUB_SW_RESET_DMA_CONTROLLER |
	       VHUB_SW_RESET_EP_POOL |

Annotation

Implementation Notes