drivers/phy/canaan/phy-k230-usb.c

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

File Facts

System
Linux kernel
Corpus path
drivers/phy/canaan/phy-k230-usb.c
Extension
.c
Size
7935 bytes
Lines
285
Domain
Driver Families
Bucket
drivers/phy
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 k230_usb_phy_instance {
	struct k230_usb_phy_global *global;
	struct phy *phy;
	u32 test_offset;
	u32 ctl_offset;
	int index;
};

struct k230_usb_phy_global {
	struct k230_usb_phy_instance phys[MAX_PHYS];
	void __iomem *base;
};

static int k230_usb_phy_power_on(struct phy *phy)
{
	struct k230_usb_phy_instance *inst = phy_get_drvdata(phy);
	struct k230_usb_phy_global *global = inst->global;
	void __iomem *base = global->base;
	u32 val;

	/* Apply recommended settings */
	writel(K230_PHY_CTL0_VAL, base + inst->ctl_offset + CTL0_OFFSET);
	writel(K230_PHY_CTL1_VAL, base + inst->ctl_offset + CTL1_OFFSET);

	/* Configure test register (pull-ups/pull-downs) */
	val = readl(base + inst->test_offset + TEST_CTL3_OFFSET);
	val |= USB_IDPULLUP0;

	if (inst->index == 1)
		val |= (USB_DMPULLDOWN0 | USB_DPPULLDOWN0);
	else
		val &= ~(USB_DMPULLDOWN0 | USB_DPPULLDOWN0);

	writel(val, base + inst->test_offset + TEST_CTL3_OFFSET);

	return 0;
}

static int k230_usb_phy_power_off(struct phy *phy)
{
	struct k230_usb_phy_instance *inst = phy_get_drvdata(phy);
	struct k230_usb_phy_global *global = inst->global;
	void __iomem *base = global->base;
	u32 val;

	val = readl(base + inst->test_offset + TEST_CTL3_OFFSET);
	val &= ~(USB_DMPULLDOWN0 | USB_DPPULLDOWN0);
	writel(val, base + inst->test_offset + TEST_CTL3_OFFSET);

	return 0;
}

static const struct phy_ops k230_usb_phy_ops = {
	.power_on = k230_usb_phy_power_on,
	.power_off = k230_usb_phy_power_off,
	.owner = THIS_MODULE,
};

static struct phy *k230_usb_phy_xlate(struct device *dev,
				      const struct of_phandle_args *args)
{
	struct k230_usb_phy_global *global = dev_get_drvdata(dev);
	unsigned int idx = args->args[0];

	if (idx >= MAX_PHYS)
		return ERR_PTR(-EINVAL);

	return global->phys[idx].phy;
}

static int k230_usb_phy_probe(struct platform_device *pdev)
{
	struct k230_usb_phy_global *global;
	struct device *dev = &pdev->dev;
	struct phy_provider *provider;
	int i;

	global = devm_kzalloc(dev, sizeof(*global), GFP_KERNEL);
	if (!global)
		return -ENOMEM;
	dev_set_drvdata(dev, global);

	global->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(global->base))
		return dev_err_probe(dev, PTR_ERR(global->base),
				     "failed to map registers\n");

	static const struct {
		u32 test_offset;
		u32 ctl_offset;

Annotation

Implementation Notes