drivers/gpio/gpio-lpc18xx.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-lpc18xx.c
Extension
.c
Size
10239 bytes
Lines
414
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 lpc18xx_gpio_pin_ic {
	void __iomem *base;
	struct irq_domain *domain;
	struct raw_spinlock lock;
	struct gpio_chip *gpio;
};

struct lpc18xx_gpio_chip {
	struct gpio_chip gpio;
	void __iomem *base;
	struct lpc18xx_gpio_pin_ic *pin_ic;
	spinlock_t lock;
};

static inline void lpc18xx_gpio_pin_ic_isel(struct lpc18xx_gpio_pin_ic *ic,
					    u32 pin, bool set)
{
	u32 val = readl_relaxed(ic->base + LPC18XX_GPIO_PIN_IC_ISEL);

	if (set)
		val &= ~BIT(pin);
	else
		val |= BIT(pin);

	writel_relaxed(val, ic->base + LPC18XX_GPIO_PIN_IC_ISEL);
}

static inline void lpc18xx_gpio_pin_ic_set(struct lpc18xx_gpio_pin_ic *ic,
					   u32 pin, u32 reg)
{
	writel_relaxed(BIT(pin), ic->base + reg);
}

static void lpc18xx_gpio_pin_ic_mask(struct irq_data *d)
{
	struct lpc18xx_gpio_pin_ic *ic = d->chip_data;
	u32 type = irqd_get_trigger_type(d);
	irq_hw_number_t hwirq = irqd_to_hwirq(d);

	raw_spin_lock(&ic->lock);

	if (type & IRQ_TYPE_LEVEL_MASK || type & IRQ_TYPE_EDGE_RISING)
		lpc18xx_gpio_pin_ic_set(ic, d->hwirq,
					LPC18XX_GPIO_PIN_IC_CIENR);

	if (type & IRQ_TYPE_EDGE_FALLING)
		lpc18xx_gpio_pin_ic_set(ic, d->hwirq,
					LPC18XX_GPIO_PIN_IC_CIENF);

	raw_spin_unlock(&ic->lock);

	irq_chip_mask_parent(d);

	gpiochip_disable_irq(ic->gpio, hwirq);
}

static void lpc18xx_gpio_pin_ic_unmask(struct irq_data *d)
{
	struct lpc18xx_gpio_pin_ic *ic = d->chip_data;
	u32 type = irqd_get_trigger_type(d);
	irq_hw_number_t hwirq = irqd_to_hwirq(d);

	gpiochip_enable_irq(ic->gpio, hwirq);

	raw_spin_lock(&ic->lock);

	if (type & IRQ_TYPE_LEVEL_MASK || type & IRQ_TYPE_EDGE_RISING)
		lpc18xx_gpio_pin_ic_set(ic, d->hwirq,
					LPC18XX_GPIO_PIN_IC_SIENR);

	if (type & IRQ_TYPE_EDGE_FALLING)
		lpc18xx_gpio_pin_ic_set(ic, d->hwirq,
					LPC18XX_GPIO_PIN_IC_SIENF);

	raw_spin_unlock(&ic->lock);

	irq_chip_unmask_parent(d);
}

static void lpc18xx_gpio_pin_ic_eoi(struct irq_data *d)
{
	struct lpc18xx_gpio_pin_ic *ic = d->chip_data;
	u32 type = irqd_get_trigger_type(d);

	raw_spin_lock(&ic->lock);

	if (type & IRQ_TYPE_EDGE_BOTH)
		lpc18xx_gpio_pin_ic_set(ic, d->hwirq,
					LPC18XX_GPIO_PIN_IC_IST);

Annotation

Implementation Notes