drivers/gpio/gpio-ath79.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-ath79.c
Extension
.c
Size
9449 bytes
Lines
349
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 ath79_gpio_ctrl {
	struct gpio_generic_chip chip;
	void __iomem *base;
	unsigned long both_edges;
};

static struct ath79_gpio_ctrl *irq_data_to_ath79_gpio(struct irq_data *data)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
	struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);

	return container_of(gen_gc, struct ath79_gpio_ctrl, chip);
}

static u32 ath79_gpio_read(struct ath79_gpio_ctrl *ctrl, unsigned reg)
{
	return readl(ctrl->base + reg);
}

static void ath79_gpio_write(struct ath79_gpio_ctrl *ctrl,
			unsigned reg, u32 val)
{
	writel(val, ctrl->base + reg);
}

static bool ath79_gpio_update_bits(
	struct ath79_gpio_ctrl *ctrl, unsigned reg, u32 mask, u32 bits)
{
	u32 old_val, new_val;

	old_val = ath79_gpio_read(ctrl, reg);
	new_val = (old_val & ~mask) | (bits & mask);

	if (new_val != old_val)
		ath79_gpio_write(ctrl, reg, new_val);

	return new_val != old_val;
}

static void ath79_gpio_irq_unmask(struct irq_data *data)
{
	struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
	u32 mask = BIT(irqd_to_hwirq(data));

	gpiochip_enable_irq(&ctrl->chip.gc, irqd_to_hwirq(data));

	guard(gpio_generic_lock_irqsave)(&ctrl->chip);

	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
}

static void ath79_gpio_irq_mask(struct irq_data *data)
{
	struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
	u32 mask = BIT(irqd_to_hwirq(data));

	scoped_guard(gpio_generic_lock_irqsave, &ctrl->chip)
		ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);

	gpiochip_disable_irq(&ctrl->chip.gc, irqd_to_hwirq(data));
}

static void ath79_gpio_irq_enable(struct irq_data *data)
{
	struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
	u32 mask = BIT(irqd_to_hwirq(data));

	guard(gpio_generic_lock_irqsave)(&ctrl->chip);
	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask);
	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask);
}

static void ath79_gpio_irq_disable(struct irq_data *data)
{
	struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
	u32 mask = BIT(irqd_to_hwirq(data));

	guard(gpio_generic_lock_irqsave)(&ctrl->chip);
	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0);
	ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, 0);
}

static int ath79_gpio_irq_set_type(struct irq_data *data,
				unsigned int flow_type)
{
	struct ath79_gpio_ctrl *ctrl = irq_data_to_ath79_gpio(data);
	u32 mask = BIT(irqd_to_hwirq(data));
	u32 type = 0, polarity = 0;
	bool disabled;

Annotation

Implementation Notes