drivers/gpio/gpio-ep93xx.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-ep93xx.c
Extension
.c
Size
10464 bytes
Lines
399
Domain
Driver Families
Bucket
drivers/gpio
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 ep93xx_gpio_irq_chip {
	void __iomem *base;
	u8 int_unmasked;
	u8 int_enabled;
	u8 int_type1;
	u8 int_type2;
	u8 int_debounce;
};

struct ep93xx_gpio_chip {
	void __iomem			*base;
	struct gpio_generic_chip	chip;
	struct ep93xx_gpio_irq_chip	*eic;
};

static struct ep93xx_gpio_chip *to_ep93xx_gpio_chip(struct gpio_chip *gc)
{
	return container_of(to_gpio_generic_chip(gc), struct ep93xx_gpio_chip, chip);
}

static struct ep93xx_gpio_irq_chip *to_ep93xx_gpio_irq_chip(struct gpio_chip *gc)
{
	struct ep93xx_gpio_chip *egc = to_ep93xx_gpio_chip(gc);

	return egc->eic;
}

/*************************************************************************
 * Interrupt handling for EP93xx on-chip GPIOs
 *************************************************************************/
#define EP93XX_INT_TYPE1_OFFSET		0x00
#define EP93XX_INT_TYPE2_OFFSET		0x04
#define EP93XX_INT_EOI_OFFSET		0x08
#define EP93XX_INT_EN_OFFSET		0x0c
#define EP93XX_INT_STATUS_OFFSET	0x10
#define EP93XX_INT_RAW_STATUS_OFFSET	0x14
#define EP93XX_INT_DEBOUNCE_OFFSET	0x18

static void ep93xx_gpio_update_int_params(struct ep93xx_gpio_irq_chip *eic)
{
	writeb_relaxed(0, eic->base + EP93XX_INT_EN_OFFSET);

	writeb_relaxed(eic->int_type2,
		       eic->base + EP93XX_INT_TYPE2_OFFSET);

	writeb_relaxed(eic->int_type1,
		       eic->base + EP93XX_INT_TYPE1_OFFSET);

	writeb_relaxed(eic->int_unmasked & eic->int_enabled,
		       eic->base + EP93XX_INT_EN_OFFSET);
}

static void ep93xx_gpio_int_debounce(struct gpio_chip *gc,
				     unsigned int offset, bool enable)
{
	struct ep93xx_gpio_irq_chip *eic = to_ep93xx_gpio_irq_chip(gc);
	int port_mask = BIT(offset);

	if (enable)
		eic->int_debounce |= port_mask;
	else
		eic->int_debounce &= ~port_mask;

	writeb(eic->int_debounce, eic->base + EP93XX_INT_DEBOUNCE_OFFSET);
}

static u32 ep93xx_gpio_ab_irq_handler(struct gpio_chip *gc)
{
	struct ep93xx_gpio_irq_chip *eic = to_ep93xx_gpio_irq_chip(gc);
	unsigned long stat;
	int offset;

	stat = readb(eic->base + EP93XX_INT_STATUS_OFFSET);
	for_each_set_bit(offset, &stat, 8)
		generic_handle_domain_irq(gc->irq.domain, offset);

	return stat;
}

static irqreturn_t ep93xx_ab_irq_handler(int irq, void *dev_id)
{
	return IRQ_RETVAL(ep93xx_gpio_ab_irq_handler(dev_id));
}

static void ep93xx_gpio_f_irq_handler(struct irq_desc *desc)
{
	struct irq_chip *irqchip = irq_desc_get_chip(desc);
	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
	struct gpio_irq_chip *gic = &gc->irq;
	unsigned int parent = irq_desc_get_irq(desc);

Annotation

Implementation Notes