u-boot/arch/x86/cpu/acpi_gpe.c
Simon Glass 41575d8e4c dm: treewide: Rename auto_alloc_size members to be shorter
This construct is quite long-winded. In earlier days it made some sense
since auto-allocation was a strange concept. But with driver model now
used pretty universally, we can shorten this to 'auto'. This reduces
verbosity and makes it easier to read.

Coincidentally it also ensures that every declaration is on one line,
thus making dtoc's job easier.

Signed-off-by: Simon Glass <sjg@chromium.org>
2020-12-13 08:00:25 -07:00

112 lines
2.6 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 Google, LLC
* Written by Simon Glass <sjg@chromium.org>
*/
#include <common.h>
#include <dm.h>
#include <irq.h>
#include <log.h>
#include <acpi/acpi_device.h>
#include <asm/io.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/x86-irq.h>
/**
* struct acpi_gpe_priv - private driver information
*
* @acpi_base: Base I/O address of ACPI registers
*/
struct acpi_gpe_priv {
ulong acpi_base;
};
#define GPE0_STS(x) (0x20 + ((x) * 4))
static int acpi_gpe_read_and_clear(struct irq *irq)
{
struct acpi_gpe_priv *priv = dev_get_priv(irq->dev);
u32 mask, sts;
ulong start;
int ret = 0;
int bank;
bank = irq->id / 32;
mask = 1 << (irq->id % 32);
/* Wait up to 1ms for GPE status to clear */
start = get_timer(0);
do {
if (get_timer(start) > 1)
return ret;
sts = inl(priv->acpi_base + GPE0_STS(bank));
if (sts & mask) {
outl(mask, priv->acpi_base + GPE0_STS(bank));
ret = 1;
}
} while (sts & mask);
return ret;
}
static int acpi_gpe_ofdata_to_platdata(struct udevice *dev)
{
struct acpi_gpe_priv *priv = dev_get_priv(dev);
priv->acpi_base = dev_read_addr(dev);
if (!priv->acpi_base || priv->acpi_base == FDT_ADDR_T_NONE)
return log_msg_ret("acpi_base", -EINVAL);
return 0;
}
static int acpi_gpe_of_xlate(struct irq *irq, struct ofnode_phandle_args *args)
{
irq->id = args->args[0];
irq->flags = args->args[1];
return 0;
}
#if CONFIG_IS_ENABLED(ACPIGEN)
static int acpi_gpe_get_acpi(const struct irq *irq, struct acpi_irq *acpi_irq)
{
memset(acpi_irq, '\0', sizeof(*acpi_irq));
acpi_irq->pin = irq->id;
acpi_irq->mode = irq->flags & IRQ_TYPE_EDGE_BOTH ?
ACPI_IRQ_EDGE_TRIGGERED : ACPI_IRQ_LEVEL_TRIGGERED;
acpi_irq->polarity = irq->flags &
(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW) ?
ACPI_IRQ_ACTIVE_LOW : ACPI_IRQ_ACTIVE_HIGH;
acpi_irq->shared = irq->flags & X86_IRQ_TYPE_SHARED ?
ACPI_IRQ_SHARED : ACPI_IRQ_EXCLUSIVE;
acpi_irq->wake = irq->flags & X86_IRQ_TYPE_WAKE ? ACPI_IRQ_WAKE :
ACPI_IRQ_NO_WAKE;
return 0;
}
#endif
static const struct irq_ops acpi_gpe_ops = {
.read_and_clear = acpi_gpe_read_and_clear,
.of_xlate = acpi_gpe_of_xlate,
#if CONFIG_IS_ENABLED(ACPIGEN)
.get_acpi = acpi_gpe_get_acpi,
#endif
};
static const struct udevice_id acpi_gpe_ids[] = {
{ .compatible = "intel,acpi-gpe", .data = X86_IRQT_ACPI_GPE },
{ }
};
U_BOOT_DRIVER(acpi_gpe_drv) = {
.name = "acpi_gpe",
.id = UCLASS_IRQ,
.of_match = acpi_gpe_ids,
.ops = &acpi_gpe_ops,
.ofdata_to_platdata = acpi_gpe_ofdata_to_platdata,
.priv_auto = sizeof(struct acpi_gpe_priv),
};