aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/powermac/pic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/powermac/pic.c')
-rw-r--r--arch/powerpc/platforms/powermac/pic.c222
1 files changed, 66 insertions, 156 deletions
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 890d5f72b19..4c24bf60d39 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -21,10 +21,9 @@
#include <linux/signal.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
#include <linux/adb.h>
#include <linux/pmu.h>
-#include <linux/module.h>
#include <asm/sections.h>
#include <asm/io.h>
@@ -53,21 +52,16 @@ struct device_node *of_irq_dflt_pic;
/* Default addresses */
static volatile struct pmac_irq_hw __iomem *pmac_irq_hw[4];
-#define GC_LEVEL_MASK 0x3ff00000
-#define OHARE_LEVEL_MASK 0x1ff00000
-#define HEATHROW_LEVEL_MASK 0x1ff00000
-
static int max_irqs;
static int max_real_irqs;
-static u32 level_mask[4];
static DEFINE_RAW_SPINLOCK(pmac_pic_lock);
-#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
-static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
-static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+/* The max irq number this driver deals with is 128; see max_irqs */
+static DECLARE_BITMAP(ppc_lost_interrupts, 128);
+static DECLARE_BITMAP(ppc_cached_irq_mask, 128);
static int pmac_irq_cascade = -1;
-static struct irq_host *pmac_pic_host;
+static struct irq_domain *pmac_pic_host;
static void __pmac_retrigger(unsigned int irq_nr)
{
@@ -82,9 +76,9 @@ static void __pmac_retrigger(unsigned int irq_nr)
}
}
-static void pmac_mask_and_ack_irq(unsigned int virq)
+static void pmac_mask_and_ack_irq(struct irq_data *d)
{
- unsigned int src = irq_map[virq].hwirq;
+ unsigned int src = irqd_to_hwirq(d);
unsigned long bit = 1UL << (src & 0x1f);
int i = src >> 5;
unsigned long flags;
@@ -104,9 +98,9 @@ static void pmac_mask_and_ack_irq(unsigned int virq)
raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
}
-static void pmac_ack_irq(unsigned int virq)
+static void pmac_ack_irq(struct irq_data *d)
{
- unsigned int src = irq_map[virq].hwirq;
+ unsigned int src = irqd_to_hwirq(d);
unsigned long bit = 1UL << (src & 0x1f);
int i = src >> 5;
unsigned long flags;
@@ -149,15 +143,15 @@ static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
/* When an irq gets requested for the first client, if it's an
* edge interrupt, we clear any previous one on the controller
*/
-static unsigned int pmac_startup_irq(unsigned int virq)
+static unsigned int pmac_startup_irq(struct irq_data *d)
{
unsigned long flags;
- unsigned int src = irq_map[virq].hwirq;
+ unsigned int src = irqd_to_hwirq(d);
unsigned long bit = 1UL << (src & 0x1f);
int i = src >> 5;
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
- if ((irq_to_desc(virq)->status & IRQ_LEVEL) == 0)
+ if (!irqd_is_level_type(d))
out_le32(&pmac_irq_hw[i]->ack, bit);
__set_bit(src, ppc_cached_irq_mask);
__pmac_set_irq_mask(src, 0);
@@ -166,10 +160,10 @@ static unsigned int pmac_startup_irq(unsigned int virq)
return 0;
}
-static void pmac_mask_irq(unsigned int virq)
+static void pmac_mask_irq(struct irq_data *d)
{
unsigned long flags;
- unsigned int src = irq_map[virq].hwirq;
+ unsigned int src = irqd_to_hwirq(d);
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
__clear_bit(src, ppc_cached_irq_mask);
@@ -177,10 +171,10 @@ static void pmac_mask_irq(unsigned int virq)
raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
}
-static void pmac_unmask_irq(unsigned int virq)
+static void pmac_unmask_irq(struct irq_data *d)
{
unsigned long flags;
- unsigned int src = irq_map[virq].hwirq;
+ unsigned int src = irqd_to_hwirq(d);
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
__set_bit(src, ppc_cached_irq_mask);
@@ -188,24 +182,24 @@ static void pmac_unmask_irq(unsigned int virq)
raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
}
-static int pmac_retrigger(unsigned int virq)
+static int pmac_retrigger(struct irq_data *d)
{
unsigned long flags;
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
- __pmac_retrigger(irq_map[virq].hwirq);
+ __pmac_retrigger(irqd_to_hwirq(d));
raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
return 1;
}
static struct irq_chip pmac_pic = {
.name = "PMAC-PIC",
- .startup = pmac_startup_irq,
- .mask = pmac_mask_irq,
- .ack = pmac_ack_irq,
- .mask_ack = pmac_mask_and_ack_irq,
- .unmask = pmac_unmask_irq,
- .retrigger = pmac_retrigger,
+ .irq_startup = pmac_startup_irq,
+ .irq_mask = pmac_mask_irq,
+ .irq_ack = pmac_ack_irq,
+ .irq_mask_ack = pmac_mask_and_ack_irq,
+ .irq_unmask = pmac_unmask_irq,
+ .irq_retrigger = pmac_retrigger,
};
static irqreturn_t gatwick_action(int cpl, void *dev_id)
@@ -218,8 +212,7 @@ static irqreturn_t gatwick_action(int cpl, void *dev_id)
for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
int i = irq >> 5;
bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
- /* We must read level interrupts from the level register */
- bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
+ bits |= in_le32(&pmac_irq_hw[i]->level);
bits &= ppc_cached_irq_mask[i];
if (bits == 0)
continue;
@@ -239,21 +232,17 @@ static unsigned int pmac_pic_get_irq(void)
unsigned long bits = 0;
unsigned long flags;
-#ifdef CONFIG_SMP
- void psurge_smp_message_recv(void);
-
- /* IPI's are a hack on the powersurge -- Cort */
- if ( smp_processor_id() != 0 ) {
- psurge_smp_message_recv();
- return NO_IRQ_IGNORE; /* ignore, already handled */
+#ifdef CONFIG_PPC_PMAC32_PSURGE
+ /* IPI's are a hack on the powersurge -- Cort */
+ if (smp_processor_id() != 0) {
+ return psurge_secondary_virq;
}
-#endif /* CONFIG_SMP */
+#endif /* CONFIG_PPC_PMAC32_PSURGE */
raw_spin_lock_irqsave(&pmac_pic_lock, flags);
for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
int i = irq >> 5;
bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
- /* We must read level interrupts from the level register */
- bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
+ bits |= in_le32(&pmac_irq_hw[i]->level);
bits &= ppc_cached_irq_mask[i];
if (bits == 0)
continue;
@@ -276,51 +265,33 @@ static struct irqaction xmon_action = {
static struct irqaction gatwick_cascade_action = {
.handler = gatwick_action,
- .flags = IRQF_DISABLED,
.name = "cascade",
};
-static int pmac_pic_host_match(struct irq_host *h, struct device_node *node)
+static int pmac_pic_host_match(struct irq_domain *h, struct device_node *node)
{
/* We match all, we don't always have a node anyway */
return 1;
}
-static int pmac_pic_host_map(struct irq_host *h, unsigned int virq,
+static int pmac_pic_host_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
- struct irq_desc *desc = irq_to_desc(virq);
- int level;
-
if (hw >= max_irqs)
return -EINVAL;
/* Mark level interrupts, set delayed disable for edge ones and set
* handlers
*/
- level = !!(level_mask[hw >> 5] & (1UL << (hw & 0x1f)));
- if (level)
- desc->status |= IRQ_LEVEL;
- set_irq_chip_and_handler(virq, &pmac_pic, level ?
- handle_level_irq : handle_edge_irq);
- return 0;
-}
-
-static int pmac_pic_host_xlate(struct irq_host *h, struct device_node *ct,
- const u32 *intspec, unsigned int intsize,
- irq_hw_number_t *out_hwirq,
- unsigned int *out_flags)
-
-{
- *out_flags = IRQ_TYPE_NONE;
- *out_hwirq = *intspec;
+ irq_set_status_flags(virq, IRQ_LEVEL);
+ irq_set_chip_and_handler(virq, &pmac_pic, handle_level_irq);
return 0;
}
-static struct irq_host_ops pmac_pic_host_ops = {
+static const struct irq_domain_ops pmac_pic_host_ops = {
.match = pmac_pic_host_match,
.map = pmac_pic_host_map,
- .xlate = pmac_pic_host_xlate,
+ .xlate = irq_domain_xlate_onecell,
};
static void __init pmac_pic_probe_oldstyle(void)
@@ -340,21 +311,14 @@ static void __init pmac_pic_probe_oldstyle(void)
if ((master = of_find_node_by_name(NULL, "gc")) != NULL) {
max_irqs = max_real_irqs = 32;
- level_mask[0] = GC_LEVEL_MASK;
} else if ((master = of_find_node_by_name(NULL, "ohare")) != NULL) {
max_irqs = max_real_irqs = 32;
- level_mask[0] = OHARE_LEVEL_MASK;
-
/* We might have a second cascaded ohare */
slave = of_find_node_by_name(NULL, "pci106b,7");
- if (slave) {
+ if (slave)
max_irqs = 64;
- level_mask[1] = OHARE_LEVEL_MASK;
- }
} else if ((master = of_find_node_by_name(NULL, "mac-io")) != NULL) {
max_irqs = max_real_irqs = 64;
- level_mask[0] = HEATHROW_LEVEL_MASK;
- level_mask[1] = 0;
/* We might have a second cascaded heathrow */
slave = of_find_node_by_name(master, "mac-io");
@@ -369,20 +333,16 @@ static void __init pmac_pic_probe_oldstyle(void)
}
/* We found a slave */
- if (slave) {
+ if (slave)
max_irqs = 128;
- level_mask[2] = HEATHROW_LEVEL_MASK;
- level_mask[3] = 0;
- }
}
BUG_ON(master == NULL);
/*
* Allocate an irq host
*/
- pmac_pic_host = irq_alloc_host(master, IRQ_HOST_MAP_LINEAR, max_irqs,
- &pmac_pic_host_ops,
- max_irqs);
+ pmac_pic_host = irq_domain_add_linear(master, max_irqs,
+ &pmac_pic_host_ops, NULL);
BUG_ON(pmac_pic_host == NULL);
irq_set_default_host(pmac_pic_host);
@@ -433,8 +393,8 @@ static void __init pmac_pic_probe_oldstyle(void)
#endif
}
-int of_irq_map_oldworld(struct device_node *device, int index,
- struct of_irq *out_irq)
+int of_irq_parse_oldworld(struct device_node *device, int index,
+ struct of_phandle_args *out_irq)
{
const u32 *ints = NULL;
int intlen;
@@ -462,24 +422,14 @@ int of_irq_map_oldworld(struct device_node *device, int index,
if (index >= intlen)
return -EINVAL;
- out_irq->controller = NULL;
- out_irq->specifier[0] = ints[index];
- out_irq->size = 1;
+ out_irq->np = NULL;
+ out_irq->args[0] = ints[index];
+ out_irq->args_count = 1;
return 0;
}
#endif /* CONFIG_PPC32 */
-static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
-{
- struct mpic *mpic = desc->handler_data;
-
- unsigned int cascade_irq = mpic_get_one_irq(mpic);
- if (cascade_irq != NO_IRQ)
- generic_handle_irq(cascade_irq);
- desc->chip->eoi(irq);
-}
-
static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
{
#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
@@ -502,18 +452,11 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
int master)
{
const char *name = master ? " MPIC 1 " : " MPIC 2 ";
- struct resource r;
struct mpic *mpic;
- unsigned int flags = master ? MPIC_PRIMARY : 0;
- int rc;
-
- rc = of_address_to_resource(np, 0, &r);
- if (rc)
- return NULL;
+ unsigned int flags = master ? 0 : MPIC_SECONDARY;
pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);
- flags |= MPIC_WANTS_RESET;
if (of_get_property(np, "big-endian", NULL))
flags |= MPIC_BIG_ENDIAN;
@@ -523,7 +466,7 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
if (master && (flags & MPIC_BIG_ENDIAN))
flags |= MPIC_U3_HT_IRQS;
- mpic = mpic_alloc(np, r.start, flags, 0, 0, name);
+ mpic = mpic_alloc(np, 0, flags, 0, 0, name);
if (mpic == NULL)
return NULL;
@@ -536,7 +479,6 @@ static int __init pmac_pic_probe_mpic(void)
{
struct mpic *mpic1, *mpic2;
struct device_node *np, *master = NULL, *slave = NULL;
- unsigned int cascade;
/* We can have up to 2 MPICs cascaded */
for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
@@ -572,27 +514,14 @@ static int __init pmac_pic_probe_mpic(void)
of_node_put(master);
- /* No slave, let's go out */
- if (slave == NULL)
- return 0;
-
- /* Get/Map slave interrupt */
- cascade = irq_of_parse_and_map(slave, 0);
- if (cascade == NO_IRQ) {
- printk(KERN_ERR "Failed to map cascade IRQ\n");
- return 0;
- }
-
- mpic2 = pmac_setup_one_mpic(slave, 0);
- if (mpic2 == NULL) {
- printk(KERN_ERR "Failed to setup slave MPIC\n");
+ /* Set up a cascaded controller, if present */
+ if (slave) {
+ mpic2 = pmac_setup_one_mpic(slave, 0);
+ if (mpic2 == NULL)
+ printk(KERN_ERR "Failed to setup slave MPIC\n");
of_node_put(slave);
- return 0;
}
- set_irq_data(cascade, mpic2);
- set_irq_chained_handler(cascade, pmac_u3_cascade);
- of_node_put(slave);
return 0;
}
@@ -600,7 +529,7 @@ static int __init pmac_pic_probe_mpic(void)
void __init pmac_pic_init(void)
{
/* We configure the OF parsing based on our oldworld vs. newworld
- * platform type and wether we were booted by BootX.
+ * platform type and whether we were booted by BootX.
*/
#ifdef CONFIG_PPC32
if (!pmac_newworld)
@@ -676,7 +605,7 @@ not_found:
return viaint;
}
-static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state)
+static int pmacpic_suspend(void)
{
int viaint = pmacpic_find_viaint();
@@ -697,7 +626,7 @@ static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state)
return 0;
}
-static int pmacpic_resume(struct sys_device *sysdev)
+static void pmacpic_resume(void)
{
int i;
@@ -707,40 +636,21 @@ static int pmacpic_resume(struct sys_device *sysdev)
mb();
for (i = 0; i < max_real_irqs; ++i)
if (test_bit(i, sleep_save_mask))
- pmac_unmask_irq(i);
-
- return 0;
+ pmac_unmask_irq(irq_get_irq_data(i));
}
-#endif /* CONFIG_PM && CONFIG_PPC32 */
-
-static struct sysdev_class pmacpic_sysclass = {
- .name = "pmac_pic",
-};
-
-static struct sys_device device_pmacpic = {
- .id = 0,
- .cls = &pmacpic_sysclass,
+static struct syscore_ops pmacpic_syscore_ops = {
+ .suspend = pmacpic_suspend,
+ .resume = pmacpic_resume,
};
-static struct sysdev_driver driver_pmacpic = {
-#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
- .suspend = &pmacpic_suspend,
- .resume = &pmacpic_resume,
-#endif /* CONFIG_PM && CONFIG_PPC32 */
-};
-
-static int __init init_pmacpic_sysfs(void)
+static int __init init_pmacpic_syscore(void)
{
-#ifdef CONFIG_PPC32
- if (max_irqs == 0)
- return -ENODEV;
-#endif
- printk(KERN_DEBUG "Registering pmac pic with sysfs...\n");
- sysdev_class_register(&pmacpic_sysclass);
- sysdev_register(&device_pmacpic);
- sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic);
+ if (pmac_irq_hw[0])
+ register_syscore_ops(&pmacpic_syscore_ops);
return 0;
}
-machine_subsys_initcall(powermac, init_pmacpic_sysfs);
+machine_subsys_initcall(powermac, init_pmacpic_syscore);
+
+#endif /* CONFIG_PM && CONFIG_PPC32 */