drivers/platform/x86/intel/int0002_vgpio.c

Source file repositories/reference/linux-study-clean/drivers/platform/x86/intel/int0002_vgpio.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/x86/intel/int0002_vgpio.c
Extension
.c
Size
7771 bytes
Lines
294
Domain
Driver Families
Bucket
drivers/platform
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 int0002_data {
	struct gpio_chip chip;
	int parent_irq;
	int wake_enable_count;
};

/*
 * As this is not a real GPIO at all, but just a hack to model an event in
 * ACPI the get / set functions are dummy functions.
 */

static int int0002_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
	return 0;
}

static int int0002_gpio_set(struct gpio_chip *chip, unsigned int offset,
			    int value)
{
	return 0;
}

static int int0002_gpio_direction_output(struct gpio_chip *chip,
					 unsigned int offset, int value)
{
	return 0;
}

static void int0002_irq_ack(struct irq_data *data)
{
	outl(GPE0A_PME_B0_STS_BIT, GPE0A_STS_PORT);
}

static void int0002_irq_unmask(struct irq_data *data)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
	irq_hw_number_t hwirq = irqd_to_hwirq(data);
	u32 gpe_en_reg;

	gpiochip_enable_irq(gc, hwirq);

	gpe_en_reg = inl(GPE0A_EN_PORT);
	gpe_en_reg |= GPE0A_PME_B0_EN_BIT;
	outl(gpe_en_reg, GPE0A_EN_PORT);
}

static void int0002_irq_mask(struct irq_data *data)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
	irq_hw_number_t hwirq = irqd_to_hwirq(data);
	u32 gpe_en_reg;

	gpe_en_reg = inl(GPE0A_EN_PORT);
	gpe_en_reg &= ~GPE0A_PME_B0_EN_BIT;
	outl(gpe_en_reg, GPE0A_EN_PORT);

	gpiochip_disable_irq(gc, hwirq);
}

static int int0002_irq_set_wake(struct irq_data *data, unsigned int on)
{
	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
	struct int0002_data *int0002 = container_of(chip, struct int0002_data, chip);

	/*
	 * Applying of the wakeup flag to our parent IRQ is delayed till system
	 * suspend, because we only want to do this when using s2idle.
	 */
	if (on)
		int0002->wake_enable_count++;
	else
		int0002->wake_enable_count--;

	return 0;
}

static irqreturn_t int0002_irq(int irq, void *data)
{
	struct gpio_chip *chip = data;
	u32 gpe_sts_reg;

	gpe_sts_reg = inl(GPE0A_STS_PORT);
	if (!(gpe_sts_reg & GPE0A_PME_B0_STS_BIT))
		return IRQ_NONE;

	generic_handle_domain_irq_safe(chip->irq.domain, GPE0A_PME_B0_VIRT_GPIO_PIN);

	pm_wakeup_hard_event(chip->parent);

	return IRQ_HANDLED;

Annotation

Implementation Notes