summaryrefslogtreecommitdiff
path: root/drivers/platform
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2021-12-30 00:14:24 +0100
committerHans de Goede <hdegoede@redhat.com>2022-01-05 11:31:18 +0100
commitcd26465fbc03beaa68979c06fc983be86eafcb4b (patch)
treef8f58620daa813594a8fcf916dc1459de942c552 /drivers/platform
parentfc64a2b21603dc1e1bae6f34b4bccfadc992894f (diff)
platform/x86: x86-android-tablets: Add support for PMIC interrupts
The Crystal Cove PMIC has a pin which can be used to connect the IRQ of an external charger IC. On some boards this is used so we need a way to look this up. Note that the Intel PMICs have 2 levels of interrupts and thus 2 levels of IRQ domains all tied to a single fwnode. Level 1 is the irqchip which demultiplexes the actual PMIC interrupt into interrupts for the various MFD cells. Level 2 are the irqchips used in the cell drivers which themselves export IRQs, such as the crystal_cove_gpio driver, which de-multiplexes the level 2 interrupts for the GPIOs into individual per GPIO IRQs. The crystal_cove_charger driver registers an irqchip with a single IRQ for the charger driver to consume. Note the MFD cell IRQ cannot be consumed directly because the level 2 interrupts must be explicitly acked. To allow finding the right IRQ domain when looking up the IRQ for the charger, the crystal_cove_charger driver sets a DOMAIN_BUS_WIRED token on its IRQ domain. Add support for looking up the IRQ from the crystal_cove_charger driver. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://lore.kernel.org/r/20211229231431.437982-6-hdegoede@redhat.com
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/x86-android-tablets.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/platform/x86/x86-android-tablets.c b/drivers/platform/x86/x86-android-tablets.c
index ea033d7f4439..44138882bc9f 100644
--- a/drivers/platform/x86/x86-android-tablets.c
+++ b/drivers/platform/x86/x86-android-tablets.c
@@ -17,6 +17,7 @@
#include <linux/gpio/machine.h>
#include <linux/i2c.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/string.h>
@@ -31,11 +32,13 @@ enum x86_acpi_irq_type {
X86_ACPI_IRQ_TYPE_NONE,
X86_ACPI_IRQ_TYPE_APIC,
X86_ACPI_IRQ_TYPE_GPIOINT,
+ X86_ACPI_IRQ_TYPE_PMIC,
};
struct x86_acpi_irq_data {
- char *chip; /* GPIO chip label (GPIOINT) */
+ char *chip; /* GPIO chip label (GPIOINT) or PMIC ACPI path (PMIC) */
enum x86_acpi_irq_type type;
+ enum irq_domain_bus_token domain;
int index;
int trigger; /* ACPI_EDGE_SENSITIVE / ACPI_LEVEL_SENSITIVE */
int polarity; /* ACPI_ACTIVE_HIGH / ACPI_ACTIVE_LOW / ACPI_ACTIVE_BOTH */
@@ -48,9 +51,14 @@ static int x86_acpi_irq_helper_gpiochip_find(struct gpio_chip *gc, void *data)
static int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
{
+ struct irq_fwspec fwspec = { };
+ struct irq_domain *domain;
+ struct acpi_device *adev;
struct gpio_desc *gpiod;
struct gpio_chip *chip;
unsigned int irq_type;
+ acpi_handle handle;
+ acpi_status status;
int irq, ret;
switch (data->type) {
@@ -86,6 +94,27 @@ static int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
irq_set_irq_type(irq, irq_type);
return irq;
+ case X86_ACPI_IRQ_TYPE_PMIC:
+ status = acpi_get_handle(NULL, data->chip, &handle);
+ if (ACPI_FAILURE(status)) {
+ pr_err("error could not get %s handle\n", data->chip);
+ return -ENODEV;
+ }
+
+ acpi_bus_get_device(handle, &adev);
+ if (!adev) {
+ pr_err("error could not get %s adev\n", data->chip);
+ return -ENODEV;
+ }
+
+ fwspec.fwnode = acpi_fwnode_handle(adev);
+ domain = irq_find_matching_fwspec(&fwspec, data->domain);
+ if (!domain) {
+ pr_err("error could not find IRQ domain for %s\n", data->chip);
+ return -ENODEV;
+ }
+
+ return irq_create_mapping(domain, data->index);
default:
return 0;
}