Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[platform/kernel/linux-rpi.git] / drivers / soc / tegra / pmc.c
index 9ed0c3b..df9a5ca 100644 (file)
@@ -1951,44 +1951,17 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq,
                                                            event->id,
                                                            &pmc->irq, pmc);
 
-                       /*
-                        * GPIOs don't have an equivalent interrupt in the
-                        * parent controller (GIC). However some code, such
-                        * as the one in irq_get_irqchip_state(), require a
-                        * valid IRQ chip to be set. Make sure that's the
-                        * case by passing NULL here, which will install a
-                        * dummy IRQ chip for the interrupt in the parent
-                        * domain.
-                        */
-                       if (domain->parent)
-                               irq_domain_set_hwirq_and_chip(domain->parent,
-                                                             virq, 0, NULL,
-                                                             NULL);
-
+                       /* GPIO hierarchies stop at the PMC level */
+                       if (!err && domain->parent)
+                               err = irq_domain_disconnect_hierarchy(domain->parent,
+                                                                     virq);
                        break;
                }
        }
 
-       /*
-        * For interrupts that don't have associated wake events, assign a
-        * dummy hardware IRQ number. This is used in the ->irq_set_type()
-        * and ->irq_set_wake() callbacks to return early for these IRQs.
-        */
-       if (i == soc->num_wake_events) {
-               err = irq_domain_set_hwirq_and_chip(domain, virq, ULONG_MAX,
-                                                   &pmc->irq, pmc);
-
-               /*
-                * Interrupts without a wake event don't have a corresponding
-                * interrupt in the parent controller (GIC). Pass NULL for the
-                * chip here, which causes a dummy IRQ chip to be installed
-                * for the interrupt in the parent domain, to make this
-                * explicit.
-                */
-               if (domain->parent)
-                       irq_domain_set_hwirq_and_chip(domain->parent, virq, 0,
-                                                     NULL, NULL);
-       }
+       /* If there is no wake-up event, there is no PMC mapping */
+       if (i == soc->num_wake_events)
+               err = irq_domain_disconnect_hierarchy(domain, virq);
 
        return err;
 }
@@ -2004,9 +1977,6 @@ static int tegra210_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
        unsigned int offset, bit;
        u32 value;
 
-       if (data->hwirq == ULONG_MAX)
-               return 0;
-
        offset = data->hwirq / 32;
        bit = data->hwirq % 32;
 
@@ -2041,9 +2011,6 @@ static int tegra210_pmc_irq_set_type(struct irq_data *data, unsigned int type)
        unsigned int offset, bit;
        u32 value;
 
-       if (data->hwirq == ULONG_MAX)
-               return 0;
-
        offset = data->hwirq / 32;
        bit = data->hwirq % 32;
 
@@ -2084,10 +2051,6 @@ static int tegra186_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
        unsigned int offset, bit;
        u32 value;
 
-       /* nothing to do if there's no associated wake event */
-       if (WARN_ON(data->hwirq == ULONG_MAX))
-               return 0;
-
        offset = data->hwirq / 32;
        bit = data->hwirq % 32;
 
@@ -2115,10 +2078,6 @@ static int tegra186_pmc_irq_set_type(struct irq_data *data, unsigned int type)
        struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
        u32 value;
 
-       /* nothing to do if there's no associated wake event */
-       if (data->hwirq == ULONG_MAX)
-               return 0;
-
        value = readl(pmc->wake + WAKE_AOWAKE_CNTRL(data->hwirq));
 
        switch (type) {
@@ -2145,6 +2104,34 @@ static int tegra186_pmc_irq_set_type(struct irq_data *data, unsigned int type)
        return 0;
 }
 
+static void tegra_irq_mask_parent(struct irq_data *data)
+{
+       if (data->parent_data)
+               irq_chip_mask_parent(data);
+}
+
+static void tegra_irq_unmask_parent(struct irq_data *data)
+{
+       if (data->parent_data)
+               irq_chip_unmask_parent(data);
+}
+
+static void tegra_irq_eoi_parent(struct irq_data *data)
+{
+       if (data->parent_data)
+               irq_chip_eoi_parent(data);
+}
+
+static int tegra_irq_set_affinity_parent(struct irq_data *data,
+                                        const struct cpumask *dest,
+                                        bool force)
+{
+       if (data->parent_data)
+               return irq_chip_set_affinity_parent(data, dest, force);
+
+       return -EINVAL;
+}
+
 static int tegra_pmc_irq_init(struct tegra_pmc *pmc)
 {
        struct irq_domain *parent = NULL;
@@ -2160,10 +2147,10 @@ static int tegra_pmc_irq_init(struct tegra_pmc *pmc)
                return 0;
 
        pmc->irq.name = dev_name(pmc->dev);
-       pmc->irq.irq_mask = irq_chip_mask_parent;
-       pmc->irq.irq_unmask = irq_chip_unmask_parent;
-       pmc->irq.irq_eoi = irq_chip_eoi_parent;
-       pmc->irq.irq_set_affinity = irq_chip_set_affinity_parent;
+       pmc->irq.irq_mask = tegra_irq_mask_parent;
+       pmc->irq.irq_unmask = tegra_irq_unmask_parent;
+       pmc->irq.irq_eoi = tegra_irq_eoi_parent;
+       pmc->irq.irq_set_affinity = tegra_irq_set_affinity_parent;
        pmc->irq.irq_set_type = pmc->soc->irq_set_type;
        pmc->irq.irq_set_wake = pmc->soc->irq_set_wake;
 
@@ -2190,7 +2177,7 @@ static int tegra_pmc_clk_notify_cb(struct notifier_block *nb,
 
        case POST_RATE_CHANGE:
                pmc->rate = data->new_rate;
-               /* fall through */
+               fallthrough;
 
        case ABORT_RATE_CHANGE:
                mutex_unlock(&pmc->powergates_lock);