drivers/gpio/gpio-xgs-iproc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-xgs-iproc.c
Extension
.c
Size
9245 bytes
Lines
330
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 iproc_gpio_chip {
	struct gpio_generic_chip gen_gc;
	spinlock_t lock;
	struct device *dev;
	void __iomem *base;
	void __iomem *intr;
};

static inline struct iproc_gpio_chip *
to_iproc_gpio(struct gpio_chip *gc)
{
	return container_of(to_gpio_generic_chip(gc), struct iproc_gpio_chip, gen_gc);
}

static void iproc_gpio_irq_ack(struct irq_data *d)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
	struct iproc_gpio_chip *chip = to_iproc_gpio(gc);
	int pin = d->hwirq;
	unsigned long flags;
	u32 irq = d->irq;
	u32 irq_type, event_status = 0;

	spin_lock_irqsave(&chip->lock, flags);
	irq_type = irq_get_trigger_type(irq);
	if (irq_type & IRQ_TYPE_EDGE_BOTH) {
		event_status |= BIT(pin);
		writel_relaxed(event_status,
			       chip->base + IPROC_GPIO_CCA_INT_EVENT);
	}
	spin_unlock_irqrestore(&chip->lock, flags);
}

static void iproc_gpio_irq_unmask(struct irq_data *d)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
	struct iproc_gpio_chip *chip = to_iproc_gpio(gc);
	int pin = d->hwirq;
	unsigned long flags;
	u32 irq = d->irq;
	u32 int_mask, irq_type, event_mask;

	gpiochip_enable_irq(gc, pin);
	spin_lock_irqsave(&chip->lock, flags);
	irq_type = irq_get_trigger_type(irq);
	event_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);
	int_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);

	if (irq_type & IRQ_TYPE_EDGE_BOTH) {
		event_mask |= 1 << pin;
		writel_relaxed(event_mask,
			       chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);
	} else {
		int_mask |= 1 << pin;
		writel_relaxed(int_mask,
			       chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);
	}
	spin_unlock_irqrestore(&chip->lock, flags);
}

static void iproc_gpio_irq_mask(struct irq_data *d)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
	struct iproc_gpio_chip *chip = to_iproc_gpio(gc);
	int pin = d->hwirq;
	unsigned long flags;
	u32 irq = d->irq;
	u32 irq_type, int_mask, event_mask;

	spin_lock_irqsave(&chip->lock, flags);
	irq_type = irq_get_trigger_type(irq);
	event_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);
	int_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);

	if (irq_type & IRQ_TYPE_EDGE_BOTH) {
		event_mask &= ~BIT(pin);
		writel_relaxed(event_mask,
			       chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);
	} else {
		int_mask &= ~BIT(pin);
		writel_relaxed(int_mask,
			       chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);
	}
	spin_unlock_irqrestore(&chip->lock, flags);
	gpiochip_disable_irq(gc, pin);
}

static int iproc_gpio_irq_set_type(struct irq_data *d, u32 type)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);

Annotation

Implementation Notes