Skip to content

Commit

Permalink
irq_domain: Remove 'new' irq_domain in favour of the ppc one
Browse files Browse the repository at this point in the history
This patch removes the simplistic implementation of irq_domains and enables
the powerpc infrastructure for all irq_domain users.  The powerpc
infrastructure includes support for complex mappings between Linux and
hardware irq numbers, and can manage allocation of irq_descs.

This patch also converts the few users of irq_domain_add()/irq_domain_del()
to call irq_domain_add_legacy() instead.

v3: Fix bug that set up too many irqs in translation range.
v2: Fix removal of irq_alloc_descs() call in gic driver

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Milton Miller <miltonm@bga.com>
Tested-by: Olof Johansson <olof@lixom.net>
  • Loading branch information
Grant Likely committed Feb 16, 2012
1 parent 5769089 commit 7529495
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 263 deletions.
85 changes: 37 additions & 48 deletions arch/arm/common/gic.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ union gic_base {
};

struct gic_chip_data {
unsigned int irq_offset;
union gic_base dist_base;
union gic_base cpu_base;
#ifdef CONFIG_CPU_PM
Expand All @@ -61,9 +60,7 @@ struct gic_chip_data {
u32 __percpu *saved_ppi_enable;
u32 __percpu *saved_ppi_conf;
#endif
#ifdef CONFIG_IRQ_DOMAIN
struct irq_domain domain;
#endif
struct irq_domain *domain;
unsigned int gic_irqs;
#ifdef CONFIG_GIC_NON_BANKED
void __iomem *(*get_base)(union gic_base *);
Expand Down Expand Up @@ -282,7 +279,7 @@ asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
irqnr = irqstat & ~0x1c00;

if (likely(irqnr > 15 && irqnr < 1021)) {
irqnr = irq_domain_to_irq(&gic->domain, irqnr);
irqnr = irq_find_mapping(gic->domain, irqnr);
handle_IRQ(irqnr, regs);
continue;
}
Expand Down Expand Up @@ -314,8 +311,8 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
if (gic_irq == 1023)
goto out;

cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
cascade_irq = irq_find_mapping(chip_data->domain, gic_irq);
if (unlikely(gic_irq < 32 || gic_irq > 1020))
do_bad_IRQ(cascade_irq, desc);
else
generic_handle_irq(cascade_irq);
Expand Down Expand Up @@ -348,10 +345,9 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)

static void __init gic_dist_init(struct gic_chip_data *gic)
{
unsigned int i, irq;
unsigned int i;
u32 cpumask;
unsigned int gic_irqs = gic->gic_irqs;
struct irq_domain *domain = &gic->domain;
void __iomem *base = gic_data_dist_base(gic);
u32 cpu = cpu_logical_map(smp_processor_id());

Expand Down Expand Up @@ -386,23 +382,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
for (i = 32; i < gic_irqs; i += 32)
writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);

/*
* Setup the Linux IRQ subsystem.
*/
irq_domain_for_each_irq(domain, i, irq) {
if (i < 32) {
irq_set_percpu_devid(irq);
irq_set_chip_and_handler(irq, &gic_chip,
handle_percpu_devid_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
} else {
irq_set_chip_and_handler(irq, &gic_chip,
handle_fasteoi_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
irq_set_chip_data(irq, gic);
}

writel_relaxed(1, base + GIC_DIST_CTRL);
}

Expand Down Expand Up @@ -618,7 +597,23 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
}
#endif

#ifdef CONFIG_OF
static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
if (hw < 32) {
irq_set_percpu_devid(irq);
irq_set_chip_and_handler(irq, &gic_chip,
handle_percpu_devid_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
} else {
irq_set_chip_and_handler(irq, &gic_chip,
handle_fasteoi_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
irq_set_chip_data(irq, d->host_data);
return 0;
}

static int gic_irq_domain_xlate(struct irq_domain *d,
struct device_node *controller,
const u32 *intspec, unsigned int intsize,
Expand All @@ -639,26 +634,23 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
return 0;
}
#endif

struct irq_domain_ops gic_irq_domain_ops = {
#ifdef CONFIG_OF
.map = gic_irq_domain_map,
.xlate = gic_irq_domain_xlate,
#endif
};

void __init gic_init_bases(unsigned int gic_nr, int irq_start,
void __iomem *dist_base, void __iomem *cpu_base,
u32 percpu_offset)
u32 percpu_offset, struct device_node *node)
{
irq_hw_number_t hwirq_base;
struct gic_chip_data *gic;
struct irq_domain *domain;
int gic_irqs;
int gic_irqs, irq_base;

BUG_ON(gic_nr >= MAX_GIC_NR);

gic = &gic_data[gic_nr];
domain = &gic->domain;
#ifdef CONFIG_GIC_NON_BANKED
if (percpu_offset) { /* Frankein-GIC without banked registers... */
unsigned int cpu;
Expand Down Expand Up @@ -694,10 +686,10 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
* For primary GICs, skip over SGIs.
* For secondary GICs, skip over PPIs, too.
*/
domain->hwirq_base = 32;
hwirq_base = 32;
if (gic_nr == 0) {
if ((irq_start & 31) > 0) {
domain->hwirq_base = 16;
hwirq_base = 16;
if (irq_start != -1)
irq_start = (irq_start & ~31) + 16;
}
Expand All @@ -713,17 +705,17 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
gic_irqs = 1020;
gic->gic_irqs = gic_irqs;

domain->nr_irq = gic_irqs - domain->hwirq_base;
domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq,
numa_node_id());
if (IS_ERR_VALUE(domain->irq_base)) {
gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */
irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, numa_node_id());
if (IS_ERR_VALUE(irq_base)) {
WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
irq_start);
domain->irq_base = irq_start;
irq_base = irq_start;
}
domain->host_data = gic;
domain->ops = &gic_irq_domain_ops;
irq_domain_add(domain);
gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base,
hwirq_base, &gic_irq_domain_ops, gic);
if (WARN_ON(!gic->domain))
return;

gic_chip.flags |= gic_arch_extn.flags;
gic_dist_init(gic);
Expand Down Expand Up @@ -768,7 +760,6 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent)
void __iomem *dist_base;
u32 percpu_offset;
int irq;
struct irq_domain *domain = &gic_data[gic_cnt].domain;

if (WARN_ON(!node))
return -ENODEV;
Expand All @@ -782,9 +773,7 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent)
if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
percpu_offset = 0;

domain->of_node = of_node_get(node);

gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset);
gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);

if (parent) {
irq = irq_of_parse_and_map(node, 0);
Expand Down
16 changes: 5 additions & 11 deletions arch/arm/common/vic.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct vic_device {
u32 int_enable;
u32 soft_int;
u32 protect;
struct irq_domain domain;
struct irq_domain *domain;
};

/* we cannot allocate memory when VICs are initially registered */
Expand Down Expand Up @@ -192,14 +192,8 @@ static void __init vic_register(void __iomem *base, unsigned int irq,
v->resume_sources = resume_sources;
v->irq = irq;
vic_id++;

v->domain.irq_base = irq;
v->domain.nr_irq = 32;
#ifdef CONFIG_OF_IRQ
v->domain.of_node = of_node_get(node);
#endif /* CONFIG_OF */
v->domain.ops = &irq_domain_simple_ops;
irq_domain_add(&v->domain);
v->domain = irq_domain_add_legacy(node, 32, irq, 0,
&irq_domain_simple_ops, v);
}

static void vic_ack_irq(struct irq_data *d)
Expand Down Expand Up @@ -348,7 +342,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
vic_register(base, irq_start, 0, node);
}

static void __init __vic_init(void __iomem *base, unsigned int irq_start,
void __init __vic_init(void __iomem *base, unsigned int irq_start,
u32 vic_sources, u32 resume_sources,
struct device_node *node)
{
Expand Down Expand Up @@ -444,7 +438,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
while (stat) {
irq = ffs(stat) - 1;
handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs);
handle_IRQ(irq_find_mapping(vic->domain, irq), regs);
stat &= ~(1 << irq);
handled = 1;
}
Expand Down
4 changes: 2 additions & 2 deletions arch/arm/include/asm/hardware/gic.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct device_node;
extern struct irq_chip gic_arch_extn;

void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
u32 offset);
u32 offset, struct device_node *);
int gic_of_init(struct device_node *node, struct device_node *parent);
void gic_secondary_init(unsigned int);
void gic_handle_irq(struct pt_regs *regs);
Expand All @@ -49,7 +49,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
static inline void gic_init(unsigned int nr, int start,
void __iomem *dist , void __iomem *cpu)
{
gic_init_bases(nr, start, dist, cpu, 0);
gic_init_bases(nr, start, dist, cpu, 0, NULL);
}

#endif
Expand Down
2 changes: 2 additions & 0 deletions arch/arm/include/asm/hardware/vic.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
struct device_node;
struct pt_regs;

void __vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources,
u32 resume_sources, struct device_node *node);
void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
int vic_of_init(struct device_node *node, struct device_node *parent);
void vic_handle_irq(struct pt_regs *regs);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-exynos/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ void __init exynos4_init_irq(void)
gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;

if (!of_have_populated_dt())
gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset);
gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL);
#ifdef CONFIG_OF
else
of_irq_init(exynos4_dt_irq_match);
Expand Down
7 changes: 5 additions & 2 deletions arch/arm/mach-versatile/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,11 @@ static const struct of_device_id sic_of_match[] __initconst = {

void __init versatile_init_irq(void)
{
vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
irq_domain_generate_simple(vic_of_match, VERSATILE_VIC_BASE, IRQ_VIC_START);
struct device_node *np;

np = of_find_matching_node_by_address(NULL, vic_of_match,
VERSATILE_VIC_BASE);
__vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0, np);

writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);

Expand Down
14 changes: 2 additions & 12 deletions drivers/mfd/twl-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,6 @@ struct twl_client {

static struct twl_client twl_modules[TWL_NUM_SLAVES];

#ifdef CONFIG_IRQ_DOMAIN
static struct irq_domain domain;
#endif

/* mapping the module id to slave id and base address */
struct twl_mapping {
unsigned char sid; /* Slave ID */
Expand Down Expand Up @@ -1227,14 +1223,8 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)

pdata->irq_base = status;
pdata->irq_end = pdata->irq_base + nr_irqs;

#ifdef CONFIG_IRQ_DOMAIN
domain.irq_base = pdata->irq_base;
domain.nr_irq = nr_irqs;
domain.of_node = of_node_get(node);
domain.ops = &irq_domain_simple_ops;
irq_domain_add(&domain);
#endif
irq_domain_add_legacy(node, nr_irqs, pdata->irq_base, 0,
&irq_domain_simple_ops, NULL);

if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
dev_dbg(&client->dev, "can't talk I2C?\n");
Expand Down
Loading

0 comments on commit 7529495

Please sign in to comment.