]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/acpi/gsi.c
sched: Don't scan all-offline ->cpus_allowed twice if !CONFIG_CPUSETS
[karo-tx-linux.git] / drivers / acpi / gsi.c
1 /*
2  * ACPI GSI IRQ layer
3  *
4  * Copyright (C) 2015 ARM Ltd.
5  * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 #include <linux/acpi.h>
12 #include <linux/irq.h>
13 #include <linux/irqdomain.h>
14
15 enum acpi_irq_model_id acpi_irq_model;
16
17 static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
18 {
19         switch (polarity) {
20         case ACPI_ACTIVE_LOW:
21                 return trigger == ACPI_EDGE_SENSITIVE ?
22                        IRQ_TYPE_EDGE_FALLING :
23                        IRQ_TYPE_LEVEL_LOW;
24         case ACPI_ACTIVE_HIGH:
25                 return trigger == ACPI_EDGE_SENSITIVE ?
26                        IRQ_TYPE_EDGE_RISING :
27                        IRQ_TYPE_LEVEL_HIGH;
28         case ACPI_ACTIVE_BOTH:
29                 if (trigger == ACPI_EDGE_SENSITIVE)
30                         return IRQ_TYPE_EDGE_BOTH;
31         default:
32                 return IRQ_TYPE_NONE;
33         }
34 }
35
36 /**
37  * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI
38  * @gsi: GSI IRQ number to map
39  * @irq: pointer where linux IRQ number is stored
40  *
41  * irq location updated with irq value [>0 on success, 0 on failure]
42  *
43  * Returns: linux IRQ number on success (>0)
44  *          -EINVAL on failure
45  */
46 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
47 {
48         /*
49          * Only default domain is supported at present, always find
50          * the mapping corresponding to default domain by passing NULL
51          * as irq_domain parameter
52          */
53         *irq = irq_find_mapping(NULL, gsi);
54         /*
55          * *irq == 0 means no mapping, that should
56          * be reported as a failure
57          */
58         return (*irq > 0) ? *irq : -EINVAL;
59 }
60 EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
61
62 /**
63  * acpi_register_gsi() - Map a GSI to a linux IRQ number
64  * @dev: device for which IRQ has to be mapped
65  * @gsi: GSI IRQ number
66  * @trigger: trigger type of the GSI number to be mapped
67  * @polarity: polarity of the GSI to be mapped
68  *
69  * Returns: a valid linux IRQ number on success
70  *          -EINVAL on failure
71  */
72 int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
73                       int polarity)
74 {
75         unsigned int irq;
76         unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
77
78         /*
79          * There is no way at present to look-up the IRQ domain on ACPI,
80          * hence always create mapping referring to the default domain
81          * by passing NULL as irq_domain parameter
82          */
83         irq = irq_create_mapping(NULL, gsi);
84         if (!irq)
85                 return -EINVAL;
86
87         /* Set irq type if specified and different than the current one */
88         if (irq_type != IRQ_TYPE_NONE &&
89                 irq_type != irq_get_trigger_type(irq))
90                 irq_set_irq_type(irq, irq_type);
91         return irq;
92 }
93 EXPORT_SYMBOL_GPL(acpi_register_gsi);
94
95 /**
96  * acpi_unregister_gsi() - Free a GSI<->linux IRQ number mapping
97  * @gsi: GSI IRQ number
98  */
99 void acpi_unregister_gsi(u32 gsi)
100 {
101         int irq = irq_find_mapping(NULL, gsi);
102
103         irq_dispose_mapping(irq);
104 }
105 EXPORT_SYMBOL_GPL(acpi_unregister_gsi);