diff options
Diffstat (limited to 'arch/powerpc/platforms/embedded6xx/hlwd-pic.c')
| -rw-r--r-- | arch/powerpc/platforms/embedded6xx/hlwd-pic.c | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c index 3006b5117ec6..b57e87b0b3ce 100644 --- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c +++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c @@ -1,23 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * arch/powerpc/platforms/embedded6xx/hlwd-pic.c * * Nintendo Wii "Hollywood" interrupt controller support. * Copyright (C) 2009 The GameCube Linux Team * Copyright (C) 2009 Albert Herranz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * */ #define DRV_MODULE_NAME "hlwd-pic" #define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt #include <linux/kernel.h> -#include <linux/init.h> #include <linux/irq.h> #include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <asm/io.h> #include "hlwd-pic.h" @@ -34,6 +30,8 @@ */ #define HW_BROADWAY_ICR 0x00 #define HW_BROADWAY_IMR 0x04 +#define HW_STARLET_ICR 0x08 +#define HW_STARLET_IMR 0x0c /* @@ -73,6 +71,9 @@ static void hlwd_pic_unmask(struct irq_data *d) void __iomem *io_base = irq_data_get_irq_chip_data(d); setbits32(io_base + HW_BROADWAY_IMR, 1 << irq); + + /* Make sure the ARM (aka. Starlet) doesn't handle this interrupt. */ + clrbits32(io_base + HW_STARLET_IMR, 1 << irq); } @@ -107,32 +108,29 @@ static const struct irq_domain_ops hlwd_irq_domain_ops = { static unsigned int __hlwd_pic_get_irq(struct irq_domain *h) { void __iomem *io_base = h->host_data; - int irq; u32 irq_status; irq_status = in_be32(io_base + HW_BROADWAY_ICR) & in_be32(io_base + HW_BROADWAY_IMR); if (irq_status == 0) - return NO_IRQ; /* no more IRQs pending */ + return 0; /* no more IRQs pending */ - irq = __ffs(irq_status); - return irq_linear_revmap(h, irq); + return __ffs(irq_status); } -static void hlwd_pic_irq_cascade(unsigned int cascade_virq, - struct irq_desc *desc) +static void hlwd_pic_irq_cascade(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); - struct irq_domain *irq_domain = irq_get_handler_data(cascade_virq); - unsigned int virq; + struct irq_domain *irq_domain = irq_desc_get_handler_data(desc); + unsigned int hwirq; raw_spin_lock(&desc->lock); chip->irq_mask(&desc->irq_data); /* IRQ_LEVEL */ raw_spin_unlock(&desc->lock); - virq = __hlwd_pic_get_irq(irq_domain); - if (virq != NO_IRQ) - generic_handle_irq(virq); + hwirq = __hlwd_pic_get_irq(irq_domain); + if (hwirq) + generic_handle_domain_irq(irq_domain, hwirq); else pr_err("spurious interrupt!\n"); @@ -155,7 +153,7 @@ static void __hlwd_quiesce(void __iomem *io_base) out_be32(io_base + HW_BROADWAY_ICR, 0xffffffff); } -struct irq_domain *hlwd_pic_init(struct device_node *np) +static struct irq_domain *__init hlwd_pic_init(struct device_node *np) { struct irq_domain *irq_domain; struct resource res; @@ -173,14 +171,16 @@ struct irq_domain *hlwd_pic_init(struct device_node *np) return NULL; } - pr_info("controller at 0x%08x mapped to 0x%p\n", res.start, io_base); + pr_info("controller at 0x%pa mapped to 0x%p\n", &res.start, io_base); __hlwd_quiesce(io_base); - irq_domain = irq_domain_add_linear(np, HLWD_NR_IRQS, - &hlwd_irq_domain_ops, io_base); + irq_domain = irq_domain_create_linear(of_fwnode_handle(np), + HLWD_NR_IRQS, + &hlwd_irq_domain_ops, io_base); if (!irq_domain) { pr_err("failed to allocate irq_domain\n"); + iounmap(io_base); return NULL; } @@ -189,7 +189,8 @@ struct irq_domain *hlwd_pic_init(struct device_node *np) unsigned int hlwd_pic_get_irq(void) { - return __hlwd_pic_get_irq(hlwd_irq_host); + unsigned int hwirq = __hlwd_pic_get_irq(hlwd_irq_host); + return hwirq ? irq_find_mapping(hlwd_irq_host, hwirq) : 0; } /* @@ -197,7 +198,7 @@ unsigned int hlwd_pic_get_irq(void) * */ -void hlwd_pic_probe(void) +void __init hlwd_pic_probe(void) { struct irq_domain *host; struct device_node *np; @@ -214,6 +215,7 @@ void hlwd_pic_probe(void) irq_set_chained_handler(cascade_virq, hlwd_pic_irq_cascade); hlwd_irq_host = host; + of_node_put(np); break; } } |
