drivers/usb/gadget/udc/rzv2m_usb3drd.c

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

File Facts

System
Linux kernel
Corpus path
drivers/usb/gadget/udc/rzv2m_usb3drd.c
Extension
.c
Size
3445 bytes
Lines
138
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

// SPDX-License-Identifier: GPL-2.0
/*
 * Renesas RZ/V2M USB3DRD driver
 *
 * Copyright (C) 2022 Renesas Electronics Corporation
 */

#include <linux/io.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/usb/rzv2m_usb3drd.h>

#define USB_PERI_DRD_CON	0x000

#define USB_PERI_DRD_CON_PERI_RST	BIT(31)
#define USB_PERI_DRD_CON_HOST_RST	BIT(30)
#define USB_PERI_DRD_CON_PERI_CON	BIT(24)

static void rzv2m_usb3drd_set_bit(struct rzv2m_usb3drd *usb3, u32 bits,
				  u32 offs)
{
	u32 val = readl(usb3->reg + offs);

	val |= bits;
	writel(val, usb3->reg + offs);
}

static void rzv2m_usb3drd_clear_bit(struct rzv2m_usb3drd *usb3, u32 bits,
				    u32 offs)
{
	u32 val = readl(usb3->reg + offs);

	val &= ~bits;
	writel(val, usb3->reg + offs);
}

void rzv2m_usb3drd_reset(struct device *dev, bool host)
{
	struct rzv2m_usb3drd *usb3 = dev_get_drvdata(dev);

	if (host) {
		rzv2m_usb3drd_clear_bit(usb3, USB_PERI_DRD_CON_PERI_CON,
					USB_PERI_DRD_CON);
		rzv2m_usb3drd_clear_bit(usb3, USB_PERI_DRD_CON_HOST_RST,
					USB_PERI_DRD_CON);
		rzv2m_usb3drd_set_bit(usb3, USB_PERI_DRD_CON_PERI_RST,
				      USB_PERI_DRD_CON);
	} else {
		rzv2m_usb3drd_set_bit(usb3, USB_PERI_DRD_CON_PERI_CON,
				      USB_PERI_DRD_CON);
		rzv2m_usb3drd_set_bit(usb3, USB_PERI_DRD_CON_HOST_RST,
				      USB_PERI_DRD_CON);
		rzv2m_usb3drd_clear_bit(usb3, USB_PERI_DRD_CON_PERI_RST,
					USB_PERI_DRD_CON);
	}
}
EXPORT_SYMBOL_GPL(rzv2m_usb3drd_reset);

static void rzv2m_usb3drd_remove(struct platform_device *pdev)
{
	struct rzv2m_usb3drd *usb3 = platform_get_drvdata(pdev);

	of_platform_depopulate(usb3->dev);
	pm_runtime_put(usb3->dev);
	pm_runtime_disable(&pdev->dev);
	reset_control_assert(usb3->drd_rstc);
}

static int rzv2m_usb3drd_probe(struct platform_device *pdev)
{
	struct rzv2m_usb3drd *usb3;
	int ret;

	usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL);
	if (!usb3)
		return -ENOMEM;

	usb3->dev = &pdev->dev;

	usb3->drd_irq = platform_get_irq_byname(pdev, "drd");
	if (usb3->drd_irq < 0)
		return usb3->drd_irq;

	usb3->reg = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(usb3->reg))
		return PTR_ERR(usb3->reg);

	platform_set_drvdata(pdev, usb3);

Annotation

Implementation Notes