@@ -1815,17 +1815,40 @@ static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
static int gpiochip_irq_reqres(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ int ret;
- return gpiochip_reqres_irq(chip, d->hwirq);
+ ret = gpiochip_reqres_irq(chip, d->hwirq);
+ if (ret || !chip->irq.irq_reqres)
+ return ret;
+ ret = chip->irq.irq_reqres(d);
+ if (ret)
+ gpiochip_relres_irq(chip, d->hwirq);
+ return ret;
}
static void gpiochip_irq_relres(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+ if (chip->irq.irq_relres)
+ chip->irq.irq_relres(d);
gpiochip_relres_irq(chip, d->hwirq);
}
+static void gpiochip_set_irq_hooks(struct gpio_chip *gpiochip)
+{
+ struct irq_chip *irqchip = gpiochip->irq.chip;
+
+ if (WARN_ON(irqchip->irq_request_resources == gpiochip_irq_reqres))
+ return;
+
+ gpiochip->irq.irq_reqres = irqchip->irq_request_resources;
+ gpiochip->irq.irq_relres = irqchip->irq_release_resources;
+
+ irqchip->irq_request_resources = gpiochip_irq_reqres;
+ irqchip->irq_release_resources = gpiochip_irq_relres;
+}
+
/**
* gpiochip_add_irqchip() - adds an IRQ chip to a GPIO chip
* @gpiochip: the GPIO chip to add the IRQ chip to
@@ -1884,16 +1907,6 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
if (!gpiochip->irq.domain)
return -EINVAL;
- /*
- * It is possible for a driver to override this, but only if the
- * alternative functions are both implemented.
- */
- if (!irqchip->irq_request_resources &&
- !irqchip->irq_release_resources) {
- irqchip->irq_request_resources = gpiochip_irq_reqres;
- irqchip->irq_release_resources = gpiochip_irq_relres;
- }
-
if (gpiochip->irq.parent_handler) {
void *data = gpiochip->irq.parent_handler_data ?: gpiochip;
@@ -1909,6 +1922,8 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
}
}
+ gpiochip_set_irq_hooks(gpiochip);
+
acpi_gpiochip_request_interrupts(gpiochip);
return 0;
@@ -1922,11 +1937,12 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,
*/
static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
{
+ struct irq_chip *irqchip = gpiochip->irq.chip;
unsigned int offset;
acpi_gpiochip_free_interrupts(gpiochip);
- if (gpiochip->irq.chip && gpiochip->irq.parent_handler) {
+ if (irqchip && gpiochip->irq.parent_handler) {
struct gpio_irq_chip *irq = &gpiochip->irq;
unsigned int i;
@@ -1950,11 +1966,13 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
irq_domain_remove(gpiochip->irq.domain);
}
- if (gpiochip->irq.chip) {
- gpiochip->irq.chip->irq_request_resources = NULL;
- gpiochip->irq.chip->irq_release_resources = NULL;
- gpiochip->irq.chip = NULL;
+ if (irqchip && irqchip->irq_request_resources == gpiochip_irq_reqres) {
+ irqchip->irq_request_resources = gpiochip->irq.irq_reqres;
+ irqchip->irq_release_resources = gpiochip->irq.irq_relres;
}
+ gpiochip->irq.irq_reqres = NULL;
+ gpiochip->irq.irq_relres = NULL;
+ gpiochip->irq.chip = NULL;
gpiochip_irqchip_free_valid_mask(gpiochip);
}
@@ -2043,15 +2061,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
return -EINVAL;
}
- /*
- * It is possible for a driver to override this, but only if the
- * alternative functions are both implemented.
- */
- if (!irqchip->irq_request_resources &&
- !irqchip->irq_release_resources) {
- irqchip->irq_request_resources = gpiochip_irq_reqres;
- irqchip->irq_release_resources = gpiochip_irq_relres;
- }
+ gpiochip_set_irq_hooks(gpiochip);
acpi_gpiochip_request_interrupts(gpiochip);
@@ -872,36 +872,6 @@ static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned offset,
return -EINVAL;
}
-static int intel_gpio_irq_reqres(struct irq_data *d)
-{
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
- int pin;
- int ret;
-
- pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
- if (pin >= 0) {
- ret = gpiochip_lock_as_irq(gc, pin);
- if (ret) {
- dev_err(pctrl->dev, "unable to lock HW IRQ %d for IRQ\n",
- pin);
- return ret;
- }
- }
- return 0;
-}
-
-static void intel_gpio_irq_relres(struct irq_data *d)
-{
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
- int pin;
-
- pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
- if (pin >= 0)
- gpiochip_unlock_as_irq(gc, pin);
-}
-
static void intel_gpio_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
@@ -1117,8 +1087,6 @@ static irqreturn_t intel_gpio_irq(int irq, void *data)
static struct irq_chip intel_gpio_irqchip = {
.name = "intel-gpio",
- .irq_request_resources = intel_gpio_irq_reqres,
- .irq_release_resources = intel_gpio_irq_relres,
.irq_enable = intel_gpio_irq_enable,
.irq_ack = intel_gpio_irq_ack,
.irq_mask = intel_gpio_irq_mask,
@@ -1290,15 +1290,7 @@ static int st_gpio_irq_request_resources(struct irq_data *d)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
st_gpio_direction_input(gc, d->hwirq);
-
- return gpiochip_lock_as_irq(gc, d->hwirq);
-}
-
-static void st_gpio_irq_release_resources(struct irq_data *d)
-{
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-
- gpiochip_unlock_as_irq(gc, d->hwirq);
+ return 0;
}
static int st_gpio_irq_set_type(struct irq_data *d, unsigned type)
@@ -1456,7 +1448,6 @@ static const struct gpio_chip st_gpio_template = {
static struct irq_chip st_gpio_irqchip = {
.name = "GPIO",
.irq_request_resources = st_gpio_irq_request_resources,
- .irq_release_resources = st_gpio_irq_release_resources,
.irq_disable = st_gpio_irq_mask,
.irq_mask = st_gpio_irq_mask,
.irq_unmask = st_gpio_irq_unmask,
@@ -138,6 +138,20 @@ struct gpio_irq_chip {
* will allocate and map all IRQs during initialization.
*/
unsigned int first;
+
+ /**
+ * @irq_reqres:
+ *
+ * Store old irq_chip irq_request_resources callback
+ */
+ int (*irq_reqres)(struct irq_data *d);
+
+ /**
+ * @irq_relres:
+ *
+ * Store old irq_chip irq_release_resources callback
+ */
+ void (*irq_relres)(struct irq_data *d);
};
static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip)