drivers/usb/gadget/udc/renesas_usb3.c

Source file repositories/reference/linux-study-clean/drivers/usb/gadget/udc/renesas_usb3.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/gadget/udc/renesas_usb3.c
Extension
.c
Size
79282 bytes
Lines
3030
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations renesas_usb3_b_device_fops = {
	.open = renesas_usb3_b_device_open,
	.write = renesas_usb3_b_device_write,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
};

static void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3,
				      struct device *dev)
{
	usb3->dentry = debugfs_create_dir(dev_name(dev), usb_debug_root);

	debugfs_create_file("b_device", 0644, usb3->dentry, usb3,
			    &renesas_usb3_b_device_fops);
}

/*------- platform_driver ------------------------------------------------*/
static void renesas_usb3_remove(struct platform_device *pdev)
{
	struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);

	debugfs_remove_recursive(usb3->dentry);
	put_device(usb3->host_dev);
	device_remove_file(&pdev->dev, &dev_attr_role);

	cancel_work_sync(&usb3->role_work);
	usb_role_switch_unregister(usb3->role_sw);

	usb_del_gadget_udc(&usb3->gadget);
	reset_control_assert(usb3->usbp_rstc);
	renesas_usb3_dma_free_prd(usb3, &pdev->dev);

	__renesas_usb3_ep_free_request(usb3->ep0_req);
	pm_runtime_disable(&pdev->dev);
}

static int renesas_usb3_init_ep(struct renesas_usb3 *usb3, struct device *dev,
				const struct renesas_usb3_priv *priv)
{
	struct renesas_usb3_ep *usb3_ep;
	int i;

	/* calculate num_usb3_eps from renesas_usb3_priv */
	usb3->num_usb3_eps = priv->ramsize_per_ramif * priv->num_ramif * 2 /
			     priv->ramsize_per_pipe + 1;

	if (usb3->num_usb3_eps > USB3_MAX_NUM_PIPES(usb3))
		usb3->num_usb3_eps = USB3_MAX_NUM_PIPES(usb3);

	usb3->usb3_ep = devm_kcalloc(dev,
				     usb3->num_usb3_eps, sizeof(*usb3_ep),
				     GFP_KERNEL);
	if (!usb3->usb3_ep)
		return -ENOMEM;

	dev_dbg(dev, "%s: num_usb3_eps = %d\n", __func__, usb3->num_usb3_eps);
	/*
	 * This driver prepares pipes as follows:
	 *  - odd pipes = IN pipe
	 *  - even pipes = OUT pipe (except pipe 0)
	 */
	usb3_for_each_ep(usb3_ep, usb3, i) {
		snprintf(usb3_ep->ep_name, sizeof(usb3_ep->ep_name), "ep%d", i);
		usb3_ep->usb3 = usb3;
		usb3_ep->num = i;
		usb3_ep->ep.name = usb3_ep->ep_name;
		usb3_ep->ep.ops = &renesas_usb3_ep_ops;
		INIT_LIST_HEAD(&usb3_ep->queue);
		INIT_LIST_HEAD(&usb3_ep->ep.ep_list);
		if (!i) {
			/* for control pipe */
			usb3->gadget.ep0 = &usb3_ep->ep;
			usb_ep_set_maxpacket_limit(&usb3_ep->ep,
						USB3_EP0_SS_MAX_PACKET_SIZE);
			usb3_ep->ep.caps.type_control = true;
			usb3_ep->ep.caps.dir_in = true;
			usb3_ep->ep.caps.dir_out = true;
			continue;
		}

		/* for bulk or interrupt pipe */
		usb_ep_set_maxpacket_limit(&usb3_ep->ep, ~0);
		list_add_tail(&usb3_ep->ep.ep_list, &usb3->gadget.ep_list);
		usb3_ep->ep.caps.type_bulk = true;
		usb3_ep->ep.caps.type_int = true;
		if (i & 1)
			usb3_ep->ep.caps.dir_in = true;
		else
			usb3_ep->ep.caps.dir_out = true;

Annotation

Implementation Notes