mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-13 22:25:03 +00:00
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
This commit is contained in:
parent
fc64a2b216
commit
cd26465fbc
1 changed files with 30 additions and 1 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue