mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-18 10:48:51 +00:00
41575d8e4c
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>
112 lines
2.6 KiB
C
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),
|
|
};
|