drivers/irqchip/irq-madera.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-madera.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-madera.c
Extension
.c
Size
7291 bytes
Lines
251
Domain
Driver Families
Bucket
drivers/irqchip
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 (!irq_data) {
			dev_err(&pdev->dev, "Invalid IRQ: %d\n", madera->irq);
			return -EINVAL;
		}

		irq_flags = irqd_get_trigger_type(irq_data);

		/* Codec defaults to trigger low, use this if no flags given */
		if (irq_flags == IRQ_TYPE_NONE)
			irq_flags = IRQF_TRIGGER_LOW;
	}

	if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
		dev_err(&pdev->dev, "Host interrupt not level-triggered\n");
		return -EINVAL;
	}

	/*
	 * The silicon always starts at active-low, check if we need to
	 * switch to active-high.
	 */
	if (irq_flags & IRQF_TRIGGER_HIGH) {
		ret = regmap_update_bits(madera->regmap, MADERA_IRQ1_CTRL,
					 MADERA_IRQ_POL_MASK, 0);
		if (ret) {
			dev_err(&pdev->dev,
				"Failed to set IRQ polarity: %d\n", ret);
			return ret;
		}
	}

	/*
	 * NOTE: regmap registers this against the OF node of the parent of
	 * the regmap - that is, against the mfd driver
	 */
	ret = regmap_add_irq_chip(madera->regmap, madera->irq, IRQF_ONESHOT, 0,
				  &madera_irq_chip, &madera->irq_data);
	if (ret) {
		dev_err(&pdev->dev, "add_irq_chip failed: %d\n", ret);
		return ret;
	}

	/* Save dev in parent MFD struct so it is accessible to siblings */
	madera->irq_dev = &pdev->dev;

	return 0;
}

static void madera_irq_remove(struct platform_device *pdev)
{
	struct madera *madera = dev_get_drvdata(pdev->dev.parent);

	/*
	 * The IRQ is disabled by the parent MFD driver before
	 * it starts cleaning up all child drivers
	 */
	madera->irq_dev = NULL;
	regmap_del_irq_chip(madera->irq, madera->irq_data);
}

static struct platform_driver madera_irq_driver = {
	.probe		= madera_irq_probe,
	.remove		= madera_irq_remove,
	.driver = {
		.name	= "madera-irq",
		.pm	= &madera_irq_pm_ops,
	}
};
module_platform_driver(madera_irq_driver);

MODULE_SOFTDEP("pre: madera");
MODULE_DESCRIPTION("Madera IRQ driver");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL v2");

Annotation

Implementation Notes