18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Support for the interrupt controllers found on Power Macintosh,
48c2ecf20Sopenharmony_ci *  currently Apple's "Grand Central" interrupt controller in all
58c2ecf20Sopenharmony_ci *  it's incarnations. OpenPIC support used on newer machines is
68c2ecf20Sopenharmony_ci *  in a separate file
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci *  Copyright (C) 1997 Paul Mackerras (paulus@samba.org)
98c2ecf20Sopenharmony_ci *  Copyright (C) 2005 Benjamin Herrenschmidt (benh@kernel.crashing.org)
108c2ecf20Sopenharmony_ci *                     IBM, Corp.
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/stddef.h>
148c2ecf20Sopenharmony_ci#include <linux/init.h>
158c2ecf20Sopenharmony_ci#include <linux/sched.h>
168c2ecf20Sopenharmony_ci#include <linux/signal.h>
178c2ecf20Sopenharmony_ci#include <linux/pci.h>
188c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
198c2ecf20Sopenharmony_ci#include <linux/syscore_ops.h>
208c2ecf20Sopenharmony_ci#include <linux/adb.h>
218c2ecf20Sopenharmony_ci#include <linux/pmu.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include <asm/sections.h>
248c2ecf20Sopenharmony_ci#include <asm/io.h>
258c2ecf20Sopenharmony_ci#include <asm/smp.h>
268c2ecf20Sopenharmony_ci#include <asm/prom.h>
278c2ecf20Sopenharmony_ci#include <asm/pci-bridge.h>
288c2ecf20Sopenharmony_ci#include <asm/time.h>
298c2ecf20Sopenharmony_ci#include <asm/pmac_feature.h>
308c2ecf20Sopenharmony_ci#include <asm/mpic.h>
318c2ecf20Sopenharmony_ci#include <asm/xmon.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include "pmac.h"
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC32
368c2ecf20Sopenharmony_cistruct pmac_irq_hw {
378c2ecf20Sopenharmony_ci        unsigned int    event;
388c2ecf20Sopenharmony_ci        unsigned int    enable;
398c2ecf20Sopenharmony_ci        unsigned int    ack;
408c2ecf20Sopenharmony_ci        unsigned int    level;
418c2ecf20Sopenharmony_ci};
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/* Workaround flags for 32bit powermac machines */
448c2ecf20Sopenharmony_ciunsigned int of_irq_workarounds;
458c2ecf20Sopenharmony_cistruct device_node *of_irq_dflt_pic;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/* Default addresses */
488c2ecf20Sopenharmony_cistatic volatile struct pmac_irq_hw __iomem *pmac_irq_hw[4];
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic int max_irqs;
518c2ecf20Sopenharmony_cistatic int max_real_irqs;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic DEFINE_RAW_SPINLOCK(pmac_pic_lock);
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/* The max irq number this driver deals with is 128; see max_irqs */
568c2ecf20Sopenharmony_cistatic DECLARE_BITMAP(ppc_lost_interrupts, 128);
578c2ecf20Sopenharmony_cistatic DECLARE_BITMAP(ppc_cached_irq_mask, 128);
588c2ecf20Sopenharmony_cistatic int pmac_irq_cascade = -1;
598c2ecf20Sopenharmony_cistatic struct irq_domain *pmac_pic_host;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic void __pmac_retrigger(unsigned int irq_nr)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	if (irq_nr >= max_real_irqs && pmac_irq_cascade > 0) {
648c2ecf20Sopenharmony_ci		__set_bit(irq_nr, ppc_lost_interrupts);
658c2ecf20Sopenharmony_ci		irq_nr = pmac_irq_cascade;
668c2ecf20Sopenharmony_ci		mb();
678c2ecf20Sopenharmony_ci	}
688c2ecf20Sopenharmony_ci	if (!__test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
698c2ecf20Sopenharmony_ci		atomic_inc(&ppc_n_lost_interrupts);
708c2ecf20Sopenharmony_ci		set_dec(1);
718c2ecf20Sopenharmony_ci	}
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic void pmac_mask_and_ack_irq(struct irq_data *d)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	unsigned int src = irqd_to_hwirq(d);
778c2ecf20Sopenharmony_ci        unsigned long bit = 1UL << (src & 0x1f);
788c2ecf20Sopenharmony_ci        int i = src >> 5;
798c2ecf20Sopenharmony_ci        unsigned long flags;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
828c2ecf20Sopenharmony_ci        __clear_bit(src, ppc_cached_irq_mask);
838c2ecf20Sopenharmony_ci        if (__test_and_clear_bit(src, ppc_lost_interrupts))
848c2ecf20Sopenharmony_ci                atomic_dec(&ppc_n_lost_interrupts);
858c2ecf20Sopenharmony_ci        out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
868c2ecf20Sopenharmony_ci        out_le32(&pmac_irq_hw[i]->ack, bit);
878c2ecf20Sopenharmony_ci        do {
888c2ecf20Sopenharmony_ci                /* make sure ack gets to controller before we enable
898c2ecf20Sopenharmony_ci                   interrupts */
908c2ecf20Sopenharmony_ci                mb();
918c2ecf20Sopenharmony_ci        } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
928c2ecf20Sopenharmony_ci                != (ppc_cached_irq_mask[i] & bit));
938c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cistatic void pmac_ack_irq(struct irq_data *d)
978c2ecf20Sopenharmony_ci{
988c2ecf20Sopenharmony_ci	unsigned int src = irqd_to_hwirq(d);
998c2ecf20Sopenharmony_ci        unsigned long bit = 1UL << (src & 0x1f);
1008c2ecf20Sopenharmony_ci        int i = src >> 5;
1018c2ecf20Sopenharmony_ci        unsigned long flags;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
1048c2ecf20Sopenharmony_ci	if (__test_and_clear_bit(src, ppc_lost_interrupts))
1058c2ecf20Sopenharmony_ci                atomic_dec(&ppc_n_lost_interrupts);
1068c2ecf20Sopenharmony_ci        out_le32(&pmac_irq_hw[i]->ack, bit);
1078c2ecf20Sopenharmony_ci        (void)in_le32(&pmac_irq_hw[i]->ack);
1088c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistatic void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci        unsigned long bit = 1UL << (irq_nr & 0x1f);
1148c2ecf20Sopenharmony_ci        int i = irq_nr >> 5;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci        if ((unsigned)irq_nr >= max_irqs)
1178c2ecf20Sopenharmony_ci                return;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci        /* enable unmasked interrupts */
1208c2ecf20Sopenharmony_ci        out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci        do {
1238c2ecf20Sopenharmony_ci                /* make sure mask gets to controller before we
1248c2ecf20Sopenharmony_ci                   return to user */
1258c2ecf20Sopenharmony_ci                mb();
1268c2ecf20Sopenharmony_ci        } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
1278c2ecf20Sopenharmony_ci                != (ppc_cached_irq_mask[i] & bit));
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci        /*
1308c2ecf20Sopenharmony_ci         * Unfortunately, setting the bit in the enable register
1318c2ecf20Sopenharmony_ci         * when the device interrupt is already on *doesn't* set
1328c2ecf20Sopenharmony_ci         * the bit in the flag register or request another interrupt.
1338c2ecf20Sopenharmony_ci         */
1348c2ecf20Sopenharmony_ci        if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))
1358c2ecf20Sopenharmony_ci		__pmac_retrigger(irq_nr);
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci/* When an irq gets requested for the first client, if it's an
1398c2ecf20Sopenharmony_ci * edge interrupt, we clear any previous one on the controller
1408c2ecf20Sopenharmony_ci */
1418c2ecf20Sopenharmony_cistatic unsigned int pmac_startup_irq(struct irq_data *d)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	unsigned long flags;
1448c2ecf20Sopenharmony_ci	unsigned int src = irqd_to_hwirq(d);
1458c2ecf20Sopenharmony_ci        unsigned long bit = 1UL << (src & 0x1f);
1468c2ecf20Sopenharmony_ci        int i = src >> 5;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
1498c2ecf20Sopenharmony_ci	if (!irqd_is_level_type(d))
1508c2ecf20Sopenharmony_ci		out_le32(&pmac_irq_hw[i]->ack, bit);
1518c2ecf20Sopenharmony_ci        __set_bit(src, ppc_cached_irq_mask);
1528c2ecf20Sopenharmony_ci        __pmac_set_irq_mask(src, 0);
1538c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	return 0;
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic void pmac_mask_irq(struct irq_data *d)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	unsigned long flags;
1618c2ecf20Sopenharmony_ci	unsigned int src = irqd_to_hwirq(d);
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
1648c2ecf20Sopenharmony_ci        __clear_bit(src, ppc_cached_irq_mask);
1658c2ecf20Sopenharmony_ci        __pmac_set_irq_mask(src, 1);
1668c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
1678c2ecf20Sopenharmony_ci}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic void pmac_unmask_irq(struct irq_data *d)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	unsigned long flags;
1728c2ecf20Sopenharmony_ci	unsigned int src = irqd_to_hwirq(d);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
1758c2ecf20Sopenharmony_ci	__set_bit(src, ppc_cached_irq_mask);
1768c2ecf20Sopenharmony_ci        __pmac_set_irq_mask(src, 0);
1778c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic int pmac_retrigger(struct irq_data *d)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	unsigned long flags;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
1858c2ecf20Sopenharmony_ci	__pmac_retrigger(irqd_to_hwirq(d));
1868c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
1878c2ecf20Sopenharmony_ci	return 1;
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic struct irq_chip pmac_pic = {
1918c2ecf20Sopenharmony_ci	.name		= "PMAC-PIC",
1928c2ecf20Sopenharmony_ci	.irq_startup	= pmac_startup_irq,
1938c2ecf20Sopenharmony_ci	.irq_mask	= pmac_mask_irq,
1948c2ecf20Sopenharmony_ci	.irq_ack	= pmac_ack_irq,
1958c2ecf20Sopenharmony_ci	.irq_mask_ack	= pmac_mask_and_ack_irq,
1968c2ecf20Sopenharmony_ci	.irq_unmask	= pmac_unmask_irq,
1978c2ecf20Sopenharmony_ci	.irq_retrigger	= pmac_retrigger,
1988c2ecf20Sopenharmony_ci};
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistatic irqreturn_t gatwick_action(int cpl, void *dev_id)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	unsigned long flags;
2038c2ecf20Sopenharmony_ci	int irq, bits;
2048c2ecf20Sopenharmony_ci	int rc = IRQ_NONE;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
2078c2ecf20Sopenharmony_ci	for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
2088c2ecf20Sopenharmony_ci		int i = irq >> 5;
2098c2ecf20Sopenharmony_ci		bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
2108c2ecf20Sopenharmony_ci		bits |= in_le32(&pmac_irq_hw[i]->level);
2118c2ecf20Sopenharmony_ci		bits &= ppc_cached_irq_mask[i];
2128c2ecf20Sopenharmony_ci		if (bits == 0)
2138c2ecf20Sopenharmony_ci			continue;
2148c2ecf20Sopenharmony_ci		irq += __ilog2(bits);
2158c2ecf20Sopenharmony_ci		raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
2168c2ecf20Sopenharmony_ci		generic_handle_irq(irq);
2178c2ecf20Sopenharmony_ci		raw_spin_lock_irqsave(&pmac_pic_lock, flags);
2188c2ecf20Sopenharmony_ci		rc = IRQ_HANDLED;
2198c2ecf20Sopenharmony_ci	}
2208c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
2218c2ecf20Sopenharmony_ci	return rc;
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistatic unsigned int pmac_pic_get_irq(void)
2258c2ecf20Sopenharmony_ci{
2268c2ecf20Sopenharmony_ci	int irq;
2278c2ecf20Sopenharmony_ci	unsigned long bits = 0;
2288c2ecf20Sopenharmony_ci	unsigned long flags;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_PMAC32_PSURGE
2318c2ecf20Sopenharmony_ci	/* IPI's are a hack on the powersurge -- Cort */
2328c2ecf20Sopenharmony_ci	if (smp_processor_id() != 0) {
2338c2ecf20Sopenharmony_ci		return  psurge_secondary_virq;
2348c2ecf20Sopenharmony_ci        }
2358c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_PMAC32_PSURGE */
2368c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
2378c2ecf20Sopenharmony_ci	for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
2388c2ecf20Sopenharmony_ci		int i = irq >> 5;
2398c2ecf20Sopenharmony_ci		bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
2408c2ecf20Sopenharmony_ci		bits |= in_le32(&pmac_irq_hw[i]->level);
2418c2ecf20Sopenharmony_ci		bits &= ppc_cached_irq_mask[i];
2428c2ecf20Sopenharmony_ci		if (bits == 0)
2438c2ecf20Sopenharmony_ci			continue;
2448c2ecf20Sopenharmony_ci		irq += __ilog2(bits);
2458c2ecf20Sopenharmony_ci		break;
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
2488c2ecf20Sopenharmony_ci	if (unlikely(irq < 0))
2498c2ecf20Sopenharmony_ci		return 0;
2508c2ecf20Sopenharmony_ci	return irq_linear_revmap(pmac_pic_host, irq);
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistatic int pmac_pic_host_match(struct irq_domain *h, struct device_node *node,
2548c2ecf20Sopenharmony_ci			       enum irq_domain_bus_token bus_token)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	/* We match all, we don't always have a node anyway */
2578c2ecf20Sopenharmony_ci	return 1;
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistatic int pmac_pic_host_map(struct irq_domain *h, unsigned int virq,
2618c2ecf20Sopenharmony_ci			     irq_hw_number_t hw)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	if (hw >= max_irqs)
2648c2ecf20Sopenharmony_ci		return -EINVAL;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	/* Mark level interrupts, set delayed disable for edge ones and set
2678c2ecf20Sopenharmony_ci	 * handlers
2688c2ecf20Sopenharmony_ci	 */
2698c2ecf20Sopenharmony_ci	irq_set_status_flags(virq, IRQ_LEVEL);
2708c2ecf20Sopenharmony_ci	irq_set_chip_and_handler(virq, &pmac_pic, handle_level_irq);
2718c2ecf20Sopenharmony_ci	return 0;
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_cistatic const struct irq_domain_ops pmac_pic_host_ops = {
2758c2ecf20Sopenharmony_ci	.match = pmac_pic_host_match,
2768c2ecf20Sopenharmony_ci	.map = pmac_pic_host_map,
2778c2ecf20Sopenharmony_ci	.xlate = irq_domain_xlate_onecell,
2788c2ecf20Sopenharmony_ci};
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic void __init pmac_pic_probe_oldstyle(void)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci        int i;
2838c2ecf20Sopenharmony_ci        struct device_node *master = NULL;
2848c2ecf20Sopenharmony_ci	struct device_node *slave = NULL;
2858c2ecf20Sopenharmony_ci	u8 __iomem *addr;
2868c2ecf20Sopenharmony_ci	struct resource r;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	/* Set our get_irq function */
2898c2ecf20Sopenharmony_ci	ppc_md.get_irq = pmac_pic_get_irq;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	/*
2928c2ecf20Sopenharmony_ci	 * Find the interrupt controller type & node
2938c2ecf20Sopenharmony_ci	 */
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	if ((master = of_find_node_by_name(NULL, "gc")) != NULL) {
2968c2ecf20Sopenharmony_ci		max_irqs = max_real_irqs = 32;
2978c2ecf20Sopenharmony_ci	} else if ((master = of_find_node_by_name(NULL, "ohare")) != NULL) {
2988c2ecf20Sopenharmony_ci		max_irqs = max_real_irqs = 32;
2998c2ecf20Sopenharmony_ci		/* We might have a second cascaded ohare */
3008c2ecf20Sopenharmony_ci		slave = of_find_node_by_name(NULL, "pci106b,7");
3018c2ecf20Sopenharmony_ci		if (slave)
3028c2ecf20Sopenharmony_ci			max_irqs = 64;
3038c2ecf20Sopenharmony_ci	} else if ((master = of_find_node_by_name(NULL, "mac-io")) != NULL) {
3048c2ecf20Sopenharmony_ci		max_irqs = max_real_irqs = 64;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci		/* We might have a second cascaded heathrow */
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci		/* Compensate for of_node_put() in of_find_node_by_name() */
3098c2ecf20Sopenharmony_ci		of_node_get(master);
3108c2ecf20Sopenharmony_ci		slave = of_find_node_by_name(master, "mac-io");
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci		/* Check ordering of master & slave */
3138c2ecf20Sopenharmony_ci		if (of_device_is_compatible(master, "gatwick")) {
3148c2ecf20Sopenharmony_ci			struct device_node *tmp;
3158c2ecf20Sopenharmony_ci			BUG_ON(slave == NULL);
3168c2ecf20Sopenharmony_ci			tmp = master;
3178c2ecf20Sopenharmony_ci			master = slave;
3188c2ecf20Sopenharmony_ci			slave = tmp;
3198c2ecf20Sopenharmony_ci		}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci		/* We found a slave */
3228c2ecf20Sopenharmony_ci		if (slave)
3238c2ecf20Sopenharmony_ci			max_irqs = 128;
3248c2ecf20Sopenharmony_ci	}
3258c2ecf20Sopenharmony_ci	BUG_ON(master == NULL);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	/*
3288c2ecf20Sopenharmony_ci	 * Allocate an irq host
3298c2ecf20Sopenharmony_ci	 */
3308c2ecf20Sopenharmony_ci	pmac_pic_host = irq_domain_add_linear(master, max_irqs,
3318c2ecf20Sopenharmony_ci					      &pmac_pic_host_ops, NULL);
3328c2ecf20Sopenharmony_ci	BUG_ON(pmac_pic_host == NULL);
3338c2ecf20Sopenharmony_ci	irq_set_default_host(pmac_pic_host);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	/* Get addresses of first controller if we have a node for it */
3368c2ecf20Sopenharmony_ci	BUG_ON(of_address_to_resource(master, 0, &r));
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	/* Map interrupts of primary controller */
3398c2ecf20Sopenharmony_ci	addr = (u8 __iomem *) ioremap(r.start, 0x40);
3408c2ecf20Sopenharmony_ci	i = 0;
3418c2ecf20Sopenharmony_ci	pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)
3428c2ecf20Sopenharmony_ci		(addr + 0x20);
3438c2ecf20Sopenharmony_ci	if (max_real_irqs > 32)
3448c2ecf20Sopenharmony_ci		pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)
3458c2ecf20Sopenharmony_ci			(addr + 0x10);
3468c2ecf20Sopenharmony_ci	of_node_put(master);
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	printk(KERN_INFO "irq: Found primary Apple PIC %pOF for %d irqs\n",
3498c2ecf20Sopenharmony_ci	       master, max_real_irqs);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	/* Map interrupts of cascaded controller */
3528c2ecf20Sopenharmony_ci	if (slave && !of_address_to_resource(slave, 0, &r)) {
3538c2ecf20Sopenharmony_ci		addr = (u8 __iomem *)ioremap(r.start, 0x40);
3548c2ecf20Sopenharmony_ci		pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)
3558c2ecf20Sopenharmony_ci			(addr + 0x20);
3568c2ecf20Sopenharmony_ci		if (max_irqs > 64)
3578c2ecf20Sopenharmony_ci			pmac_irq_hw[i++] =
3588c2ecf20Sopenharmony_ci				(volatile struct pmac_irq_hw __iomem *)
3598c2ecf20Sopenharmony_ci				(addr + 0x10);
3608c2ecf20Sopenharmony_ci		pmac_irq_cascade = irq_of_parse_and_map(slave, 0);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci		printk(KERN_INFO "irq: Found slave Apple PIC %pOF for %d irqs"
3638c2ecf20Sopenharmony_ci		       " cascade: %d\n", slave,
3648c2ecf20Sopenharmony_ci		       max_irqs - max_real_irqs, pmac_irq_cascade);
3658c2ecf20Sopenharmony_ci	}
3668c2ecf20Sopenharmony_ci	of_node_put(slave);
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	/* Disable all interrupts in all controllers */
3698c2ecf20Sopenharmony_ci	for (i = 0; i * 32 < max_irqs; ++i)
3708c2ecf20Sopenharmony_ci		out_le32(&pmac_irq_hw[i]->enable, 0);
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	/* Hookup cascade irq */
3738c2ecf20Sopenharmony_ci	if (slave && pmac_irq_cascade) {
3748c2ecf20Sopenharmony_ci		if (request_irq(pmac_irq_cascade, gatwick_action,
3758c2ecf20Sopenharmony_ci				IRQF_NO_THREAD, "cascade", NULL))
3768c2ecf20Sopenharmony_ci			pr_err("Failed to register cascade interrupt\n");
3778c2ecf20Sopenharmony_ci	}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs);
3808c2ecf20Sopenharmony_ci#ifdef CONFIG_XMON
3818c2ecf20Sopenharmony_ci	i = irq_create_mapping(NULL, 20);
3828c2ecf20Sopenharmony_ci	if (request_irq(i, xmon_irq, IRQF_NO_THREAD, "NMI - XMON", NULL))
3838c2ecf20Sopenharmony_ci		pr_err("Failed to register NMI-XMON interrupt\n");
3848c2ecf20Sopenharmony_ci#endif
3858c2ecf20Sopenharmony_ci}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ciint of_irq_parse_oldworld(struct device_node *device, int index,
3888c2ecf20Sopenharmony_ci			struct of_phandle_args *out_irq)
3898c2ecf20Sopenharmony_ci{
3908c2ecf20Sopenharmony_ci	const u32 *ints = NULL;
3918c2ecf20Sopenharmony_ci	int intlen;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	/*
3948c2ecf20Sopenharmony_ci	 * Old machines just have a list of interrupt numbers
3958c2ecf20Sopenharmony_ci	 * and no interrupt-controller nodes. We also have dodgy
3968c2ecf20Sopenharmony_ci	 * cases where the APPL,interrupts property is completely
3978c2ecf20Sopenharmony_ci	 * missing behind pci-pci bridges and we have to get it
3988c2ecf20Sopenharmony_ci	 * from the parent (the bridge itself, as apple just wired
3998c2ecf20Sopenharmony_ci	 * everything together on these)
4008c2ecf20Sopenharmony_ci	 */
4018c2ecf20Sopenharmony_ci	while (device) {
4028c2ecf20Sopenharmony_ci		ints = of_get_property(device, "AAPL,interrupts", &intlen);
4038c2ecf20Sopenharmony_ci		if (ints != NULL)
4048c2ecf20Sopenharmony_ci			break;
4058c2ecf20Sopenharmony_ci		device = device->parent;
4068c2ecf20Sopenharmony_ci		if (!of_node_is_type(device, "pci"))
4078c2ecf20Sopenharmony_ci			break;
4088c2ecf20Sopenharmony_ci	}
4098c2ecf20Sopenharmony_ci	if (ints == NULL)
4108c2ecf20Sopenharmony_ci		return -EINVAL;
4118c2ecf20Sopenharmony_ci	intlen /= sizeof(u32);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	if (index >= intlen)
4148c2ecf20Sopenharmony_ci		return -EINVAL;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	out_irq->np = NULL;
4178c2ecf20Sopenharmony_ci	out_irq->args[0] = ints[index];
4188c2ecf20Sopenharmony_ci	out_irq->args_count = 1;
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	return 0;
4218c2ecf20Sopenharmony_ci}
4228c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC32 */
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_cistatic void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
4278c2ecf20Sopenharmony_ci	struct device_node* pswitch;
4288c2ecf20Sopenharmony_ci	int nmi_irq;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	pswitch = of_find_node_by_name(NULL, "programmer-switch");
4318c2ecf20Sopenharmony_ci	if (pswitch) {
4328c2ecf20Sopenharmony_ci		nmi_irq = irq_of_parse_and_map(pswitch, 0);
4338c2ecf20Sopenharmony_ci		if (nmi_irq) {
4348c2ecf20Sopenharmony_ci			mpic_irq_set_priority(nmi_irq, 9);
4358c2ecf20Sopenharmony_ci			if (request_irq(nmi_irq, xmon_irq, IRQF_NO_THREAD,
4368c2ecf20Sopenharmony_ci					"NMI - XMON", NULL))
4378c2ecf20Sopenharmony_ci				pr_err("Failed to register NMI-XMON interrupt\n");
4388c2ecf20Sopenharmony_ci		}
4398c2ecf20Sopenharmony_ci		of_node_put(pswitch);
4408c2ecf20Sopenharmony_ci	}
4418c2ecf20Sopenharmony_ci#endif	/* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */
4428c2ecf20Sopenharmony_ci}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_cistatic struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
4458c2ecf20Sopenharmony_ci						int master)
4468c2ecf20Sopenharmony_ci{
4478c2ecf20Sopenharmony_ci	const char *name = master ? " MPIC 1   " : " MPIC 2   ";
4488c2ecf20Sopenharmony_ci	struct mpic *mpic;
4498c2ecf20Sopenharmony_ci	unsigned int flags = master ? 0 : MPIC_SECONDARY;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	if (of_get_property(np, "big-endian", NULL))
4548c2ecf20Sopenharmony_ci		flags |= MPIC_BIG_ENDIAN;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	/* Primary Big Endian means HT interrupts. This is quite dodgy
4578c2ecf20Sopenharmony_ci	 * but works until I find a better way
4588c2ecf20Sopenharmony_ci	 */
4598c2ecf20Sopenharmony_ci	if (master && (flags & MPIC_BIG_ENDIAN))
4608c2ecf20Sopenharmony_ci		flags |= MPIC_U3_HT_IRQS;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	mpic = mpic_alloc(np, 0, flags, 0, 0, name);
4638c2ecf20Sopenharmony_ci	if (mpic == NULL)
4648c2ecf20Sopenharmony_ci		return NULL;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	mpic_init(mpic);
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	return mpic;
4698c2ecf20Sopenharmony_ci }
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_cistatic int __init pmac_pic_probe_mpic(void)
4728c2ecf20Sopenharmony_ci{
4738c2ecf20Sopenharmony_ci	struct mpic *mpic1, *mpic2;
4748c2ecf20Sopenharmony_ci	struct device_node *np, *master = NULL, *slave = NULL;
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	/* We can have up to 2 MPICs cascaded */
4778c2ecf20Sopenharmony_ci	for_each_node_by_type(np, "open-pic") {
4788c2ecf20Sopenharmony_ci		if (master == NULL &&
4798c2ecf20Sopenharmony_ci		    of_get_property(np, "interrupts", NULL) == NULL)
4808c2ecf20Sopenharmony_ci			master = of_node_get(np);
4818c2ecf20Sopenharmony_ci		else if (slave == NULL)
4828c2ecf20Sopenharmony_ci			slave = of_node_get(np);
4838c2ecf20Sopenharmony_ci		if (master && slave) {
4848c2ecf20Sopenharmony_ci			of_node_put(np);
4858c2ecf20Sopenharmony_ci			break;
4868c2ecf20Sopenharmony_ci		}
4878c2ecf20Sopenharmony_ci	}
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	/* Check for bogus setups */
4908c2ecf20Sopenharmony_ci	if (master == NULL && slave != NULL) {
4918c2ecf20Sopenharmony_ci		master = slave;
4928c2ecf20Sopenharmony_ci		slave = NULL;
4938c2ecf20Sopenharmony_ci	}
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	/* Not found, default to good old pmac pic */
4968c2ecf20Sopenharmony_ci	if (master == NULL)
4978c2ecf20Sopenharmony_ci		return -ENODEV;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	/* Set master handler */
5008c2ecf20Sopenharmony_ci	ppc_md.get_irq = mpic_get_irq;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	/* Setup master */
5038c2ecf20Sopenharmony_ci	mpic1 = pmac_setup_one_mpic(master, 1);
5048c2ecf20Sopenharmony_ci	BUG_ON(mpic1 == NULL);
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	/* Install NMI if any */
5078c2ecf20Sopenharmony_ci	pmac_pic_setup_mpic_nmi(mpic1);
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	of_node_put(master);
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	/* Set up a cascaded controller, if present */
5128c2ecf20Sopenharmony_ci	if (slave) {
5138c2ecf20Sopenharmony_ci		mpic2 = pmac_setup_one_mpic(slave, 0);
5148c2ecf20Sopenharmony_ci		if (mpic2 == NULL)
5158c2ecf20Sopenharmony_ci			printk(KERN_ERR "Failed to setup slave MPIC\n");
5168c2ecf20Sopenharmony_ci		of_node_put(slave);
5178c2ecf20Sopenharmony_ci	}
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	return 0;
5208c2ecf20Sopenharmony_ci}
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_civoid __init pmac_pic_init(void)
5248c2ecf20Sopenharmony_ci{
5258c2ecf20Sopenharmony_ci	/* We configure the OF parsing based on our oldworld vs. newworld
5268c2ecf20Sopenharmony_ci	 * platform type and whether we were booted by BootX.
5278c2ecf20Sopenharmony_ci	 */
5288c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC32
5298c2ecf20Sopenharmony_ci	if (!pmac_newworld)
5308c2ecf20Sopenharmony_ci		of_irq_workarounds |= OF_IMAP_OLDWORLD_MAC;
5318c2ecf20Sopenharmony_ci	if (of_get_property(of_chosen, "linux,bootx", NULL) != NULL)
5328c2ecf20Sopenharmony_ci		of_irq_workarounds |= OF_IMAP_NO_PHANDLE;
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	/* If we don't have phandles on a newworld, then try to locate a
5358c2ecf20Sopenharmony_ci	 * default interrupt controller (happens when booting with BootX).
5368c2ecf20Sopenharmony_ci	 * We do a first match here, hopefully, that only ever happens on
5378c2ecf20Sopenharmony_ci	 * machines with one controller.
5388c2ecf20Sopenharmony_ci	 */
5398c2ecf20Sopenharmony_ci	if (pmac_newworld && (of_irq_workarounds & OF_IMAP_NO_PHANDLE)) {
5408c2ecf20Sopenharmony_ci		struct device_node *np;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci		for_each_node_with_property(np, "interrupt-controller") {
5438c2ecf20Sopenharmony_ci			/* Skip /chosen/interrupt-controller */
5448c2ecf20Sopenharmony_ci			if (of_node_name_eq(np, "chosen"))
5458c2ecf20Sopenharmony_ci				continue;
5468c2ecf20Sopenharmony_ci			/* It seems like at least one person wants
5478c2ecf20Sopenharmony_ci			 * to use BootX on a machine with an AppleKiwi
5488c2ecf20Sopenharmony_ci			 * controller which happens to pretend to be an
5498c2ecf20Sopenharmony_ci			 * interrupt controller too. */
5508c2ecf20Sopenharmony_ci			if (of_node_name_eq(np, "AppleKiwi"))
5518c2ecf20Sopenharmony_ci				continue;
5528c2ecf20Sopenharmony_ci			/* I think we found one ! */
5538c2ecf20Sopenharmony_ci			of_irq_dflt_pic = np;
5548c2ecf20Sopenharmony_ci			break;
5558c2ecf20Sopenharmony_ci		}
5568c2ecf20Sopenharmony_ci	}
5578c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC32 */
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	/* We first try to detect Apple's new Core99 chipset, since mac-io
5608c2ecf20Sopenharmony_ci	 * is quite different on those machines and contains an IBM MPIC2.
5618c2ecf20Sopenharmony_ci	 */
5628c2ecf20Sopenharmony_ci	if (pmac_pic_probe_mpic() == 0)
5638c2ecf20Sopenharmony_ci		return;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC32
5668c2ecf20Sopenharmony_ci	pmac_pic_probe_oldstyle();
5678c2ecf20Sopenharmony_ci#endif
5688c2ecf20Sopenharmony_ci}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
5718c2ecf20Sopenharmony_ci/*
5728c2ecf20Sopenharmony_ci * These procedures are used in implementing sleep on the powerbooks.
5738c2ecf20Sopenharmony_ci * sleep_save_intrs() saves the states of all interrupt enables
5748c2ecf20Sopenharmony_ci * and disables all interrupts except for the nominated one.
5758c2ecf20Sopenharmony_ci * sleep_restore_intrs() restores the states of all interrupt enables.
5768c2ecf20Sopenharmony_ci */
5778c2ecf20Sopenharmony_ciunsigned long sleep_save_mask[2];
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci/* This used to be passed by the PMU driver but that link got
5808c2ecf20Sopenharmony_ci * broken with the new driver model. We use this tweak for now...
5818c2ecf20Sopenharmony_ci * We really want to do things differently though...
5828c2ecf20Sopenharmony_ci */
5838c2ecf20Sopenharmony_cistatic int pmacpic_find_viaint(void)
5848c2ecf20Sopenharmony_ci{
5858c2ecf20Sopenharmony_ci	int viaint = -1;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci#ifdef CONFIG_ADB_PMU
5888c2ecf20Sopenharmony_ci	struct device_node *np;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	if (pmu_get_model() != PMU_OHARE_BASED)
5918c2ecf20Sopenharmony_ci		goto not_found;
5928c2ecf20Sopenharmony_ci	np = of_find_node_by_name(NULL, "via-pmu");
5938c2ecf20Sopenharmony_ci	if (np == NULL)
5948c2ecf20Sopenharmony_ci		goto not_found;
5958c2ecf20Sopenharmony_ci	viaint = irq_of_parse_and_map(np, 0);
5968c2ecf20Sopenharmony_ci	of_node_put(np);
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cinot_found:
5998c2ecf20Sopenharmony_ci#endif /* CONFIG_ADB_PMU */
6008c2ecf20Sopenharmony_ci	return viaint;
6018c2ecf20Sopenharmony_ci}
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_cistatic int pmacpic_suspend(void)
6048c2ecf20Sopenharmony_ci{
6058c2ecf20Sopenharmony_ci	int viaint = pmacpic_find_viaint();
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	sleep_save_mask[0] = ppc_cached_irq_mask[0];
6088c2ecf20Sopenharmony_ci	sleep_save_mask[1] = ppc_cached_irq_mask[1];
6098c2ecf20Sopenharmony_ci	ppc_cached_irq_mask[0] = 0;
6108c2ecf20Sopenharmony_ci	ppc_cached_irq_mask[1] = 0;
6118c2ecf20Sopenharmony_ci	if (viaint > 0)
6128c2ecf20Sopenharmony_ci		set_bit(viaint, ppc_cached_irq_mask);
6138c2ecf20Sopenharmony_ci	out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
6148c2ecf20Sopenharmony_ci	if (max_real_irqs > 32)
6158c2ecf20Sopenharmony_ci		out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
6168c2ecf20Sopenharmony_ci	(void)in_le32(&pmac_irq_hw[0]->event);
6178c2ecf20Sopenharmony_ci	/* make sure mask gets to controller before we return to caller */
6188c2ecf20Sopenharmony_ci	mb();
6198c2ecf20Sopenharmony_ci        (void)in_le32(&pmac_irq_hw[0]->enable);
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci        return 0;
6228c2ecf20Sopenharmony_ci}
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_cistatic void pmacpic_resume(void)
6258c2ecf20Sopenharmony_ci{
6268c2ecf20Sopenharmony_ci	int i;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	out_le32(&pmac_irq_hw[0]->enable, 0);
6298c2ecf20Sopenharmony_ci	if (max_real_irqs > 32)
6308c2ecf20Sopenharmony_ci		out_le32(&pmac_irq_hw[1]->enable, 0);
6318c2ecf20Sopenharmony_ci	mb();
6328c2ecf20Sopenharmony_ci	for (i = 0; i < max_real_irqs; ++i)
6338c2ecf20Sopenharmony_ci		if (test_bit(i, sleep_save_mask))
6348c2ecf20Sopenharmony_ci			pmac_unmask_irq(irq_get_irq_data(i));
6358c2ecf20Sopenharmony_ci}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_cistatic struct syscore_ops pmacpic_syscore_ops = {
6388c2ecf20Sopenharmony_ci	.suspend	= pmacpic_suspend,
6398c2ecf20Sopenharmony_ci	.resume		= pmacpic_resume,
6408c2ecf20Sopenharmony_ci};
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_cistatic int __init init_pmacpic_syscore(void)
6438c2ecf20Sopenharmony_ci{
6448c2ecf20Sopenharmony_ci	if (pmac_irq_hw[0])
6458c2ecf20Sopenharmony_ci		register_syscore_ops(&pmacpic_syscore_ops);
6468c2ecf20Sopenharmony_ci	return 0;
6478c2ecf20Sopenharmony_ci}
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_cimachine_subsys_initcall(powermac, init_pmacpic_syscore);
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci#endif /* CONFIG_PM && CONFIG_PPC32 */
652