summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2020-02-10 20:27:31 +0300
committerTom Rini <trini@konsulko.com>2020-02-10 20:27:31 +0300
commit4e5c4683b7a54090323043ab9a67772baeecb1b1 (patch)
treef92a230d39f521cdeafc45a8ac9eb036e76983b2 /drivers/misc
parent5f2fe7d4617bbddc45b6a0cbf21cd468c57f4eba (diff)
parent0f6a70e971b2d87de3e58e8f0b51b0cd6723bc96 (diff)
downloadu-boot-4e5c4683b7a54090323043ab9a67772baeecb1b1.tar.xz
Merge https://gitlab.denx.de/u-boot/custodians/u-boot-x86
- Move P2SB from Apollo Lake to a more generic location - Add a function to find a device by drvdata in DM core - Enhancement of DM IRQ uclass driver - Add a clock driver for Intel devices - Add support for ACPI general-purpose events - Add a TPM driver for H1/Cr50 - Enable TPM on Google Chromebook Coral
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/irq-uclass.c131
-rw-r--r--drivers/misc/irq_sandbox.c43
2 files changed, 172 insertions, 2 deletions
diff --git a/drivers/misc/irq-uclass.c b/drivers/misc/irq-uclass.c
index d5182cf149..61aa10e465 100644
--- a/drivers/misc/irq-uclass.c
+++ b/drivers/misc/irq-uclass.c
@@ -1,11 +1,16 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
+ * Copyright 2019 Google, LLC
+ * Written by Simon Glass <sjg@chromium.org>
*/
+#define LOG_CATEGORY UCLASS_IRQ
+
#include <common.h>
#include <dm.h>
+#include <dt-structs.h>
#include <irq.h>
+#include <dm/device-internal.h>
int irq_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
{
@@ -47,6 +52,130 @@ int irq_restore_polarities(struct udevice *dev)
return ops->restore_polarities(dev);
}
+int irq_read_and_clear(struct irq *irq)
+{
+ const struct irq_ops *ops = irq_get_ops(irq->dev);
+
+ if (!ops->read_and_clear)
+ return -ENOSYS;
+
+ return ops->read_and_clear(irq);
+}
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+int irq_get_by_index_platdata(struct udevice *dev, int index,
+ struct phandle_1_arg *cells, struct irq *irq)
+{
+ int ret;
+
+ if (index != 0)
+ return -ENOSYS;
+ ret = uclass_get_device(UCLASS_IRQ, 0, &irq->dev);
+ if (ret)
+ return ret;
+ irq->id = cells[0].arg[0];
+
+ return 0;
+}
+#else
+static int irq_of_xlate_default(struct irq *irq,
+ struct ofnode_phandle_args *args)
+{
+ log_debug("(irq=%p)\n", irq);
+
+ if (args->args_count > 1) {
+ log_debug("Invaild args_count: %d\n", args->args_count);
+ return -EINVAL;
+ }
+
+ if (args->args_count)
+ irq->id = args->args[0];
+ else
+ irq->id = 0;
+
+ return 0;
+}
+
+static int irq_get_by_index_tail(int ret, ofnode node,
+ struct ofnode_phandle_args *args,
+ const char *list_name, int index,
+ struct irq *irq)
+{
+ struct udevice *dev_irq;
+ const struct irq_ops *ops;
+
+ assert(irq);
+ irq->dev = NULL;
+ if (ret)
+ goto err;
+
+ ret = uclass_get_device_by_ofnode(UCLASS_IRQ, args->node, &dev_irq);
+ if (ret) {
+ log_debug("uclass_get_device_by_ofnode failed: err=%d\n", ret);
+ return ret;
+ }
+
+ irq->dev = dev_irq;
+
+ ops = irq_get_ops(dev_irq);
+
+ if (ops->of_xlate)
+ ret = ops->of_xlate(irq, args);
+ else
+ ret = irq_of_xlate_default(irq, args);
+ if (ret) {
+ log_debug("of_xlate() failed: %d\n", ret);
+ return ret;
+ }
+
+ return irq_request(dev_irq, irq);
+err:
+ log_debug("Node '%s', property '%s', failed to request IRQ index %d: %d\n",
+ ofnode_get_name(node), list_name, index, ret);
+ return ret;
+}
+
+int irq_get_by_index(struct udevice *dev, int index, struct irq *irq)
+{
+ struct ofnode_phandle_args args;
+ int ret;
+
+ ret = dev_read_phandle_with_args(dev, "interrupts-extended",
+ "#interrupt-cells", 0, index, &args);
+
+ return irq_get_by_index_tail(ret, dev_ofnode(dev), &args,
+ "interrupts-extended", index > 0, irq);
+}
+#endif /* OF_PLATDATA */
+
+int irq_request(struct udevice *dev, struct irq *irq)
+{
+ const struct irq_ops *ops;
+
+ log_debug("(dev=%p, irq=%p)\n", dev, irq);
+ if (!irq)
+ return 0;
+ ops = irq_get_ops(dev);
+
+ irq->dev = dev;
+
+ if (!ops->request)
+ return 0;
+
+ return ops->request(irq);
+}
+
+int irq_first_device_type(enum irq_dev_t type, struct udevice **devp)
+{
+ int ret;
+
+ ret = uclass_first_device_drvdata(UCLASS_IRQ, type, devp);
+ if (ret)
+ return log_msg_ret("find", ret);
+
+ return 0;
+}
+
UCLASS_DRIVER(irq) = {
.id = UCLASS_IRQ,
.name = "irq",
diff --git a/drivers/misc/irq_sandbox.c b/drivers/misc/irq_sandbox.c
index 6dda1a4c44..54bc47c8d8 100644
--- a/drivers/misc/irq_sandbox.c
+++ b/drivers/misc/irq_sandbox.c
@@ -8,6 +8,18 @@
#include <common.h>
#include <dm.h>
#include <irq.h>
+#include <asm/test.h>
+
+/**
+ * struct sandbox_irq_priv - private data for this driver
+ *
+ * @count: Counts the number calls to the read_and_clear() method
+ * @pending: true if an interrupt is pending, else false
+ */
+struct sandbox_irq_priv {
+ int count;
+ bool pending;
+};
static int sandbox_set_polarity(struct udevice *dev, uint irq, bool active_low)
{
@@ -35,15 +47,43 @@ static int sandbox_restore_polarities(struct udevice *dev)
return 0;
}
+static int sandbox_irq_read_and_clear(struct irq *irq)
+{
+ struct sandbox_irq_priv *priv = dev_get_priv(irq->dev);
+
+ if (irq->id != SANDBOX_IRQN_PEND)
+ return -EINVAL;
+ priv->count++;
+ if (priv->pending) {
+ priv->pending = false;
+ return 1;
+ }
+
+ if (!(priv->count % 3))
+ priv->pending = true;
+
+ return 0;
+}
+
+static int sandbox_irq_of_xlate(struct irq *irq,
+ struct ofnode_phandle_args *args)
+{
+ irq->id = args->args[0];
+
+ return 0;
+}
+
static const struct irq_ops sandbox_irq_ops = {
.route_pmc_gpio_gpe = sandbox_route_pmc_gpio_gpe,
.set_polarity = sandbox_set_polarity,
.snapshot_polarities = sandbox_snapshot_polarities,
.restore_polarities = sandbox_restore_polarities,
+ .read_and_clear = sandbox_irq_read_and_clear,
+ .of_xlate = sandbox_irq_of_xlate,
};
static const struct udevice_id sandbox_irq_ids[] = {
- { .compatible = "sandbox,irq"},
+ { .compatible = "sandbox,irq", SANDBOX_IRQT_BASE },
{ }
};
@@ -52,4 +92,5 @@ U_BOOT_DRIVER(sandbox_irq_drv) = {
.id = UCLASS_IRQ,
.of_match = sandbox_irq_ids,
.ops = &sandbox_irq_ops,
+ .priv_auto_alloc_size = sizeof(struct sandbox_irq_priv),
};