drivers/gpio/gpio-cadence.c

Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-cadence.c

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-cadence.c
Extension
.c
Size
8790 bytes
Lines
329
Domain
Driver Families
Bucket
drivers/gpio
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 cdns_gpio_quirks {
	bool skip_init;
};

struct cdns_gpio_chip {
	struct gpio_generic_chip gen_gc;
	void __iomem *regs;
	u32 bypass_orig;
	const struct cdns_gpio_quirks *quirks;
};

static const struct cdns_gpio_quirks cdns_default_quirks = {
	.skip_init = false,
};

static const struct cdns_gpio_quirks ax3000_gpio_quirks = {
	.skip_init = true,
};

static int cdns_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
	struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);

	guard(gpio_generic_lock)(&cgpio->gen_gc);

	iowrite32(ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE) & ~BIT(offset),
		  cgpio->regs + CDNS_GPIO_BYPASS_MODE);

	return 0;
}

static void cdns_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
	struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);

	guard(gpio_generic_lock)(&cgpio->gen_gc);

	iowrite32(ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE) |
		  (BIT(offset) & cgpio->bypass_orig),
		  cgpio->regs + CDNS_GPIO_BYPASS_MODE);
}

static void cdns_gpio_irq_mask(struct irq_data *d)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
	struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);

	iowrite32(BIT(d->hwirq), cgpio->regs + CDNS_GPIO_IRQ_DIS);
	gpiochip_disable_irq(chip, irqd_to_hwirq(d));
}

static void cdns_gpio_irq_unmask(struct irq_data *d)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
	struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);

	gpiochip_enable_irq(chip, irqd_to_hwirq(d));
	iowrite32(BIT(d->hwirq), cgpio->regs + CDNS_GPIO_IRQ_EN);
}

static int cdns_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
	struct cdns_gpio_chip *cgpio = gpiochip_get_data(chip);
	u32 int_value;
	u32 int_type;
	u32 int_any;
	u32 mask = BIT(d->hwirq);
	int ret = 0;

	guard(gpio_generic_lock)(&cgpio->gen_gc);

	int_value = ioread32(cgpio->regs + CDNS_GPIO_IRQ_VALUE) & ~mask;
	int_type = ioread32(cgpio->regs + CDNS_GPIO_IRQ_TYPE) & ~mask;
	/*
	 * Interrupt polarity and trigger behaviour is configured like this:
	 *
	 * (type, value)
	 * (0, 0) = Falling edge triggered
	 * (0, 1) = Rising edge triggered
	 * (1, 0) = Low level triggered
	 * (1, 1) = High level triggered
	 */
	int_any = ioread32(cgpio->regs + CDNS_GPIO_IRQ_ANY_EDGE) & ~mask;

	if (type == IRQ_TYPE_LEVEL_HIGH) {
		int_type |= mask;
		int_value |= mask;
	} else if (type == IRQ_TYPE_LEVEL_LOW) {
		int_type |= mask;

Annotation

Implementation Notes