Merge tag 'irqchip-core-4.1-3' of git://git.infradead.org/users/jcooper/linux into irq/core
irqchip core change for v4.1 (round 3) from Jason Cooper Purge the gic_arch_extn hacks and abuse by using the new stacked domains NOTE: Due to the nature of these changes, patches crossing subsystems have been kept together in their own branches. - tegra - Handle the LIC properly - omap - Convert crossbar to stacked domains - kill arm,routable-irqs in GIC binding - exynos - Convert PMU wakeup to stacked domains - shmobile, ux500, zynq (irq_set_wake branch) - Switch from abusing gic_arch_extn to using gic_set_irqchip_flags
This commit is contained in:
@@ -18,7 +18,9 @@
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <linux/cpu_pm.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irqchip/arm-gic.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
@@ -43,8 +45,8 @@
|
||||
#define EXYNOS5420_CPU_STATE 0x28
|
||||
|
||||
/**
|
||||
* struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
|
||||
* @hwirq: Hardware IRQ signal of the GIC
|
||||
* struct exynos_wkup_irq - PMU IRQ to mask mapping
|
||||
* @hwirq: Hardware IRQ signal of the PMU
|
||||
* @mask: Mask in PMU wake-up mask register
|
||||
*/
|
||||
struct exynos_wkup_irq {
|
||||
@@ -93,14 +95,14 @@ static const struct exynos_wkup_irq exynos3250_wkup_irq[] = {
|
||||
};
|
||||
|
||||
static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
|
||||
{ 76, BIT(1) }, /* RTC alarm */
|
||||
{ 77, BIT(2) }, /* RTC tick */
|
||||
{ 44, BIT(1) }, /* RTC alarm */
|
||||
{ 45, BIT(2) }, /* RTC tick */
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
|
||||
{ 75, BIT(1) }, /* RTC alarm */
|
||||
{ 76, BIT(2) }, /* RTC tick */
|
||||
{ 43, BIT(1) }, /* RTC alarm */
|
||||
{ 44, BIT(2) }, /* RTC tick */
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
@@ -167,6 +169,113 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static struct irq_chip exynos_pmu_chip = {
|
||||
.name = "PMU",
|
||||
.irq_eoi = irq_chip_eoi_parent,
|
||||
.irq_mask = irq_chip_mask_parent,
|
||||
.irq_unmask = irq_chip_unmask_parent,
|
||||
.irq_retrigger = irq_chip_retrigger_hierarchy,
|
||||
.irq_set_wake = exynos_irq_set_wake,
|
||||
#ifdef CONFIG_SMP
|
||||
.irq_set_affinity = irq_chip_set_affinity_parent,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int exynos_pmu_domain_xlate(struct irq_domain *domain,
|
||||
struct device_node *controller,
|
||||
const u32 *intspec,
|
||||
unsigned int intsize,
|
||||
unsigned long *out_hwirq,
|
||||
unsigned int *out_type)
|
||||
{
|
||||
if (domain->of_node != controller)
|
||||
return -EINVAL; /* Shouldn't happen, really... */
|
||||
if (intsize != 3)
|
||||
return -EINVAL; /* Not GIC compliant */
|
||||
if (intspec[0] != 0)
|
||||
return -EINVAL; /* No PPI should point to this domain */
|
||||
|
||||
*out_hwirq = intspec[1];
|
||||
*out_type = intspec[2];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_pmu_domain_alloc(struct irq_domain *domain,
|
||||
unsigned int virq,
|
||||
unsigned int nr_irqs, void *data)
|
||||
{
|
||||
struct of_phandle_args *args = data;
|
||||
struct of_phandle_args parent_args;
|
||||
irq_hw_number_t hwirq;
|
||||
int i;
|
||||
|
||||
if (args->args_count != 3)
|
||||
return -EINVAL; /* Not GIC compliant */
|
||||
if (args->args[0] != 0)
|
||||
return -EINVAL; /* No PPI should point to this domain */
|
||||
|
||||
hwirq = args->args[1];
|
||||
|
||||
for (i = 0; i < nr_irqs; i++)
|
||||
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
|
||||
&exynos_pmu_chip, NULL);
|
||||
|
||||
parent_args = *args;
|
||||
parent_args.np = domain->parent->of_node;
|
||||
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
|
||||
}
|
||||
|
||||
static struct irq_domain_ops exynos_pmu_domain_ops = {
|
||||
.xlate = exynos_pmu_domain_xlate,
|
||||
.alloc = exynos_pmu_domain_alloc,
|
||||
.free = irq_domain_free_irqs_common,
|
||||
};
|
||||
|
||||
static int __init exynos_pmu_irq_init(struct device_node *node,
|
||||
struct device_node *parent)
|
||||
{
|
||||
struct irq_domain *parent_domain, *domain;
|
||||
|
||||
if (!parent) {
|
||||
pr_err("%s: no parent, giving up\n", node->full_name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
parent_domain = irq_find_host(parent);
|
||||
if (!parent_domain) {
|
||||
pr_err("%s: unable to obtain parent domain\n", node->full_name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
pmu_base_addr = of_iomap(node, 0);
|
||||
|
||||
if (!pmu_base_addr) {
|
||||
pr_err("%s: failed to find exynos pmu register\n",
|
||||
node->full_name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
domain = irq_domain_add_hierarchy(parent_domain, 0, 0,
|
||||
node, &exynos_pmu_domain_ops,
|
||||
NULL);
|
||||
if (!domain) {
|
||||
iounmap(pmu_base_addr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define EXYNOS_PMU_IRQ(symbol, name) OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init)
|
||||
|
||||
EXYNOS_PMU_IRQ(exynos3250_pmu_irq, "samsung,exynos3250-pmu");
|
||||
EXYNOS_PMU_IRQ(exynos4210_pmu_irq, "samsung,exynos4210-pmu");
|
||||
EXYNOS_PMU_IRQ(exynos4212_pmu_irq, "samsung,exynos4212-pmu");
|
||||
EXYNOS_PMU_IRQ(exynos4412_pmu_irq, "samsung,exynos4412-pmu");
|
||||
EXYNOS_PMU_IRQ(exynos4415_pmu_irq, "samsung,exynos4415-pmu");
|
||||
EXYNOS_PMU_IRQ(exynos5250_pmu_irq, "samsung,exynos5250-pmu");
|
||||
EXYNOS_PMU_IRQ(exynos5420_pmu_irq, "samsung,exynos5420-pmu");
|
||||
|
||||
static int exynos_cpu_do_idle(void)
|
||||
{
|
||||
/* issue the standby signal into the pm unit. */
|
||||
@@ -615,17 +724,19 @@ static struct syscore_ops exynos_pm_syscore_ops;
|
||||
void __init exynos_pm_init(void)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
struct device_node *np;
|
||||
u32 tmp;
|
||||
|
||||
of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match);
|
||||
if (!match) {
|
||||
np = of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match);
|
||||
if (!np) {
|
||||
pr_err("Failed to find PMU node\n");
|
||||
return;
|
||||
}
|
||||
pm_data = (struct exynos_pm_data *) match->data;
|
||||
|
||||
/* Platform-specific GIC callback */
|
||||
gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
|
||||
if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL)))
|
||||
pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
|
||||
|
||||
pm_data = (struct exynos_pm_data *) match->data;
|
||||
|
||||
/* All wakeup disable */
|
||||
tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
|
||||
|
Reference in New Issue
Block a user