pic.c 17.8 KB
Newer Older
1 2 3 4 5 6 7
/*
 *  Support for the interrupt controllers found on Power Macintosh,
 *  currently Apple's "Grand Central" interrupt controller in all
 *  it's incarnations. OpenPIC support used on newer machines is
 *  in a separate file
 *
 *  Copyright (C) 1997 Paul Mackerras (paulus@samba.org)
8 9
 *  Copyright (C) 2005 Benjamin Herrenschmidt (benh@kernel.crashing.org)
 *                     IBM, Corp.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 *  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.
 *
 */

#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/sysdev.h>
#include <linux/adb.h>
#include <linux/pmu.h>
27
#include <linux/module.h>
28 29 30 31 32 33 34 35 36

#include <asm/sections.h>
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/time.h>
#include <asm/pmac_feature.h>
#include <asm/mpic.h>
37
#include <asm/xmon.h>
38

39
#include "pmac.h"
40

41
#ifdef CONFIG_PPC32
42 43 44 45 46 47 48 49
struct pmac_irq_hw {
        unsigned int    event;
        unsigned int    enable;
        unsigned int    ack;
        unsigned int    level;
};

/* Default addresses */
50
static volatile struct pmac_irq_hw __iomem *pmac_irq_hw[4];
51 52 53 54 55 56 57 58 59 60 61

#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_SPINLOCK(pmac_pic_lock);

S
Stephen Rothwell 已提交
62 63
#define NR_MASK_WORDS	((NR_IRQS + 31) / 32)
static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
64 65
static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
static int pmac_irq_cascade = -1;
66
static struct irq_host *pmac_pic_host;
S
Stephen Rothwell 已提交
67

68
static void __pmac_retrigger(unsigned int irq_nr)
69
{
70 71 72 73 74 75
	if (irq_nr >= max_real_irqs && pmac_irq_cascade > 0) {
		__set_bit(irq_nr, ppc_lost_interrupts);
		irq_nr = pmac_irq_cascade;
		mb();
	}
	if (!__test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
76
		atomic_inc(&ppc_n_lost_interrupts);
77
		set_dec(1);
78 79 80
	}
}

81
static void pmac_mask_and_ack_irq(unsigned int virq)
82
{
83
	unsigned int src = irq_map[virq].hwirq;
84 85
        unsigned long bit = 1UL << (src & 0x1f);
        int i = src >> 5;
86 87 88
        unsigned long flags;

	spin_lock_irqsave(&pmac_pic_lock, flags);
89 90
        __clear_bit(src, ppc_cached_irq_mask);
        if (__test_and_clear_bit(src, ppc_lost_interrupts))
91
                atomic_dec(&ppc_n_lost_interrupts);
92 93 94 95 96 97 98 99 100 101 102
        out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
        out_le32(&pmac_irq_hw[i]->ack, bit);
        do {
                /* make sure ack gets to controller before we enable
                   interrupts */
                mb();
        } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
                != (ppc_cached_irq_mask[i] & bit));
	spin_unlock_irqrestore(&pmac_pic_lock, flags);
}

103
static void pmac_ack_irq(unsigned int virq)
104
{
105 106 107
	unsigned int src = irq_map[virq].hwirq;
        unsigned long bit = 1UL << (src & 0x1f);
        int i = src >> 5;
108 109
        unsigned long flags;

110
  	spin_lock_irqsave(&pmac_pic_lock, flags);
111
	if (__test_and_clear_bit(src, ppc_lost_interrupts))
112 113 114 115 116 117 118 119 120 121 122 123 124 125
                atomic_dec(&ppc_n_lost_interrupts);
        out_le32(&pmac_irq_hw[i]->ack, bit);
        (void)in_le32(&pmac_irq_hw[i]->ack);
	spin_unlock_irqrestore(&pmac_pic_lock, flags);
}

static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
{
        unsigned long bit = 1UL << (irq_nr & 0x1f);
        int i = irq_nr >> 5;

        if ((unsigned)irq_nr >= max_irqs)
                return;

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
        /* enable unmasked interrupts */
        out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);

        do {
                /* make sure mask gets to controller before we
                   return to user */
                mb();
        } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
                != (ppc_cached_irq_mask[i] & bit));

        /*
         * Unfortunately, setting the bit in the enable register
         * when the device interrupt is already on *doesn't* set
         * the bit in the flag register or request another interrupt.
         */
        if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))
142
		__pmac_retrigger(irq_nr);
143 144 145 146 147
}

/* When an irq gets requested for the first client, if it's an
 * edge interrupt, we clear any previous one on the controller
 */
148
static unsigned int pmac_startup_irq(unsigned int virq)
149
{
150
	unsigned long flags;
151 152 153
	unsigned int src = irq_map[virq].hwirq;
        unsigned long bit = 1UL << (src & 0x1f);
        int i = src >> 5;
154

M
Michael Ellerman 已提交
155 156
	spin_lock_irqsave(&pmac_pic_lock, flags);
	if ((irq_to_desc(virq)->status & IRQ_LEVEL) == 0)
157
		out_le32(&pmac_irq_hw[i]->ack, bit);
158 159
        __set_bit(src, ppc_cached_irq_mask);
        __pmac_set_irq_mask(src, 0);
M
Michael Ellerman 已提交
160
	spin_unlock_irqrestore(&pmac_pic_lock, flags);
161 162 163 164

	return 0;
}

165
static void pmac_mask_irq(unsigned int virq)
166
{
167
	unsigned long flags;
168
	unsigned int src = irq_map[virq].hwirq;
169 170

  	spin_lock_irqsave(&pmac_pic_lock, flags);
171
        __clear_bit(src, ppc_cached_irq_mask);
172
        __pmac_set_irq_mask(src, 1);
173
  	spin_unlock_irqrestore(&pmac_pic_lock, flags);
174 175
}

176
static void pmac_unmask_irq(unsigned int virq)
177
{
178
	unsigned long flags;
179
	unsigned int src = irq_map[virq].hwirq;
180 181

	spin_lock_irqsave(&pmac_pic_lock, flags);
182 183
	__set_bit(src, ppc_cached_irq_mask);
        __pmac_set_irq_mask(src, 0);
184
  	spin_unlock_irqrestore(&pmac_pic_lock, flags);
185 186
}

187
static int pmac_retrigger(unsigned int virq)
188
{
189
	unsigned long flags;
190

191
  	spin_lock_irqsave(&pmac_pic_lock, flags);
192
	__pmac_retrigger(irq_map[virq].hwirq);
193 194 195
  	spin_unlock_irqrestore(&pmac_pic_lock, flags);
	return 1;
}
196

197
static struct irq_chip pmac_pic = {
198 199
	.typename	= " PMAC-PIC ",
	.startup	= pmac_startup_irq,
200 201 202 203 204
	.mask		= pmac_mask_irq,
	.ack		= pmac_ack_irq,
	.mask_ack	= pmac_mask_and_ack_irq,
	.unmask		= pmac_unmask_irq,
	.retrigger	= pmac_retrigger,
205 206
};

O
Olaf Hering 已提交
207
static irqreturn_t gatwick_action(int cpl, void *dev_id)
208
{
209
	unsigned long flags;
210
	int irq, bits;
211
	int rc = IRQ_NONE;
212

213
  	spin_lock_irqsave(&pmac_pic_lock, flags);
214 215 216 217 218 219 220 221 222
	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 &= ppc_cached_irq_mask[i];
		if (bits == 0)
			continue;
		irq += __ilog2(bits);
223
		spin_unlock_irqrestore(&pmac_pic_lock, flags);
224
		generic_handle_irq(irq);
225 226
		spin_lock_irqsave(&pmac_pic_lock, flags);
		rc = IRQ_HANDLED;
227
	}
228 229
  	spin_unlock_irqrestore(&pmac_pic_lock, flags);
	return rc;
230 231
}

O
Olaf Hering 已提交
232
static unsigned int pmac_pic_get_irq(void)
233 234 235
{
	int irq;
	unsigned long bits = 0;
236
	unsigned long flags;
237 238

#ifdef CONFIG_SMP
O
Olaf Hering 已提交
239
	void psurge_smp_message_recv(void);
240 241 242

       	/* IPI's are a hack on the powersurge -- Cort */
       	if ( smp_processor_id() != 0 ) {
O
Olaf Hering 已提交
243
		psurge_smp_message_recv();
244
		return NO_IRQ_IGNORE;	/* ignore, already handled */
245 246
        }
#endif /* CONFIG_SMP */
247
  	spin_lock_irqsave(&pmac_pic_lock, flags);
248 249 250 251 252 253 254 255 256 257 258
	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 &= ppc_cached_irq_mask[i];
		if (bits == 0)
			continue;
		irq += __ilog2(bits);
		break;
	}
259
  	spin_unlock_irqrestore(&pmac_pic_lock, flags);
260 261 262
	if (unlikely(irq < 0))
		return NO_IRQ;
	return irq_linear_revmap(pmac_pic_host, irq);
263 264 265 266 267 268 269 270 271 272 273 274
}

#ifdef CONFIG_XMON
static struct irqaction xmon_action = {
	.handler	= xmon_irq,
	.flags		= 0,
	.name		= "NMI - XMON"
};
#endif

static struct irqaction gatwick_cascade_action = {
	.handler	= gatwick_action,
275
	.flags		= IRQF_DISABLED,
276 277
	.name		= "cascade",
};
278

279 280 281 282 283 284 285
static int pmac_pic_host_match(struct irq_host *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,
286
			     irq_hw_number_t hw)
287
{
M
Michael Ellerman 已提交
288
	struct irq_desc *desc = irq_to_desc(virq);
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
	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,
			       u32 *intspec, unsigned int intsize,
			       irq_hw_number_t *out_hwirq,
			       unsigned int *out_flags)

{
311
	*out_flags = IRQ_TYPE_NONE;
312 313 314 315 316 317 318 319 320 321
	*out_hwirq = *intspec;
	return 0;
}

static struct irq_host_ops pmac_pic_host_ops = {
	.match = pmac_pic_host_match,
	.map = pmac_pic_host_map,
	.xlate = pmac_pic_host_xlate,
};

322
static void __init pmac_pic_probe_oldstyle(void)
323 324
{
        int i;
325 326 327 328
        struct device_node *master = NULL;
	struct device_node *slave = NULL;
	u8 __iomem *addr;
	struct resource r;
329

330
	/* Set our get_irq function */
331
	ppc_md.get_irq = pmac_pic_get_irq;
332

333 334
	/*
	 * Find the interrupt controller type & node
335
	 */
336 337 338

	if ((master = of_find_node_by_name(NULL, "gc")) != NULL) {
		max_irqs = max_real_irqs = 32;
339
		level_mask[0] = GC_LEVEL_MASK;
340 341
	} else if ((master = of_find_node_by_name(NULL, "ohare")) != NULL) {
		max_irqs = max_real_irqs = 32;
342
		level_mask[0] = OHARE_LEVEL_MASK;
343

344
		/* We might have a second cascaded ohare */
345 346 347 348 349 350 351
		slave = of_find_node_by_name(NULL, "pci106b,7");
		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;
352 353
		level_mask[0] = HEATHROW_LEVEL_MASK;
		level_mask[1] = 0;
354

355
		/* We might have a second cascaded heathrow */
356 357 358
		slave = of_find_node_by_name(master, "mac-io");

		/* Check ordering of master & slave */
359
		if (of_device_is_compatible(master, "gatwick")) {
360 361 362 363 364 365
			struct device_node *tmp;
			BUG_ON(slave == NULL);
			tmp = master;
			master = slave;
			slave = tmp;
		}
366

367 368
		/* We found a slave */
		if (slave) {
369
			max_irqs = 128;
370 371 372
			level_mask[2] = HEATHROW_LEVEL_MASK;
			level_mask[3] = 0;
		}
373
	}
374 375
	BUG_ON(master == NULL);

376 377 378
	/*
	 * Allocate an irq host
	 */
379
	pmac_pic_host = irq_alloc_host(master, IRQ_HOST_MAP_LINEAR, max_irqs,
380 381 382 383
				       &pmac_pic_host_ops,
				       max_irqs);
	BUG_ON(pmac_pic_host == NULL);
	irq_set_default_host(pmac_pic_host);
384

385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
	/* Get addresses of first controller if we have a node for it */
	BUG_ON(of_address_to_resource(master, 0, &r));

	/* Map interrupts of primary controller */
	addr = (u8 __iomem *) ioremap(r.start, 0x40);
	i = 0;
	pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)
		(addr + 0x20);
	if (max_real_irqs > 32)
		pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)
			(addr + 0x10);
	of_node_put(master);

	printk(KERN_INFO "irq: Found primary Apple PIC %s for %d irqs\n",
	       master->full_name, max_real_irqs);

	/* Map interrupts of cascaded controller */
	if (slave && !of_address_to_resource(slave, 0, &r)) {
		addr = (u8 __iomem *)ioremap(r.start, 0x40);
		pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)
			(addr + 0x20);
		if (max_irqs > 64)
			pmac_irq_hw[i++] =
				(volatile struct pmac_irq_hw __iomem *)
				(addr + 0x10);
410
		pmac_irq_cascade = irq_of_parse_and_map(slave, 0);
411 412 413

		printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs"
		       " cascade: %d\n", slave->full_name,
414
		       max_irqs - max_real_irqs, pmac_irq_cascade);
415
	}
416
	of_node_put(slave);
417

418
	/* Disable all interrupts in all controllers */
419 420
	for (i = 0; i * 32 < max_irqs; ++i)
		out_le32(&pmac_irq_hw[i]->enable, 0);
421

422
	/* Hookup cascade irq */
423
	if (slave && pmac_irq_cascade != NO_IRQ)
424
		setup_irq(pmac_irq_cascade, &gatwick_cascade_action);
425

426
	printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs);
427
#ifdef CONFIG_XMON
428
	setup_irq(irq_create_mapping(NULL, 20), &xmon_action);
429 430 431 432
#endif
}
#endif /* CONFIG_PPC32 */

433
static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
434
{
435 436
	struct mpic *mpic = desc->handler_data;

O
Olaf Hering 已提交
437
	unsigned int cascade_irq = mpic_get_one_irq(mpic);
438
	if (cascade_irq != NO_IRQ)
439
		generic_handle_irq(cascade_irq);
440
	desc->chip->eoi(irq);
441 442 443 444 445 446 447 448 449
}

static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
{
#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
	struct device_node* pswitch;
	int nmi_irq;

	pswitch = of_find_node_by_name(NULL, "programmer-switch");
450 451 452 453 454 455 456
	if (pswitch) {
		nmi_irq = irq_of_parse_and_map(pswitch, 0);
		if (nmi_irq != NO_IRQ) {
			mpic_irq_set_priority(nmi_irq, 9);
			setup_irq(nmi_irq, &xmon_action);
		}
		of_node_put(pswitch);
457 458 459 460
	}
#endif	/* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */
}

461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
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;

	pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);

	flags |= MPIC_WANTS_RESET;
477
	if (of_get_property(np, "big-endian", NULL))
478 479 480 481 482 483
		flags |= MPIC_BIG_ENDIAN;

	/* Primary Big Endian means HT interrupts. This is quite dodgy
	 * but works until I find a better way
	 */
	if (master && (flags & MPIC_BIG_ENDIAN))
484
		flags |= MPIC_U3_HT_IRQS;
485

486
	mpic = mpic_alloc(np, r.start, flags, 0, 0, name);
487 488 489 490 491 492 493 494
	if (mpic == NULL)
		return NULL;

	mpic_init(mpic);

	return mpic;
 }

495 496 497 498
static int __init pmac_pic_probe_mpic(void)
{
	struct mpic *mpic1, *mpic2;
	struct device_node *np, *master = NULL, *slave = NULL;
499
	unsigned int cascade;
500 501 502 503 504

	/* We can have up to 2 MPICs cascaded */
	for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
		     != NULL;) {
		if (master == NULL &&
505
		    of_get_property(np, "interrupts", NULL) == NULL)
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
			master = of_node_get(np);
		else if (slave == NULL)
			slave = of_node_get(np);
		if (master && slave)
			break;
	}

	/* Check for bogus setups */
	if (master == NULL && slave != NULL) {
		master = slave;
		slave = NULL;
	}

	/* Not found, default to good old pmac pic */
	if (master == NULL)
		return -ENODEV;

	/* Set master handler */
	ppc_md.get_irq = mpic_get_irq;

	/* Setup master */
527
	mpic1 = pmac_setup_one_mpic(master, 1);
528 529 530 531 532 533 534 535
	BUG_ON(mpic1 == NULL);

	/* Install NMI if any */
	pmac_pic_setup_mpic_nmi(mpic1);

	of_node_put(master);

	/* No slave, let's go out */
536 537 538 539 540 541 542
	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");
543
		return 0;
544
	}
545

546
	mpic2 = pmac_setup_one_mpic(slave, 0);
547
	if (mpic2 == NULL) {
548 549
		printk(KERN_ERR "Failed to setup slave MPIC\n");
		of_node_put(slave);
550 551
		return 0;
	}
552 553
	set_irq_data(cascade, mpic2);
	set_irq_chained_handler(cascade, pmac_u3_cascade);
554 555 556 557 558 559 560 561

	of_node_put(slave);
	return 0;
}


void __init pmac_pic_init(void)
{
562 563 564 565 566 567 568 569
	unsigned int flags = 0;

	/* We configure the OF parsing based on our oldworld vs. newworld
	 * platform type and wether we were booted by BootX.
	 */
#ifdef CONFIG_PPC32
	if (!pmac_newworld)
		flags |= OF_IMAP_OLDWORLD_MAC;
570
	if (of_get_property(of_chosen, "linux,bootx", NULL) != NULL)
571 572 573
		flags |= OF_IMAP_NO_PHANDLE;
#endif /* CONFIG_PPC_32 */

574 575
	of_irq_map_init(flags);

576 577 578 579 580 581 582 583 584
	/* We first try to detect Apple's new Core99 chipset, since mac-io
	 * is quite different on those machines and contains an IBM MPIC2.
	 */
	if (pmac_pic_probe_mpic() == 0)
		return;

#ifdef CONFIG_PPC32
	pmac_pic_probe_oldstyle();
#endif
585 586
}

587
#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
588 589 590 591 592 593 594 595 596 597
/*
 * These procedures are used in implementing sleep on the powerbooks.
 * sleep_save_intrs() saves the states of all interrupt enables
 * and disables all interrupts except for the nominated one.
 * sleep_restore_intrs() restores the states of all interrupt enables.
 */
unsigned long sleep_save_mask[2];

/* This used to be passed by the PMU driver but that link got
 * broken with the new driver model. We use this tweak for now...
598
 * We really want to do things differently though...
599 600 601 602 603 604 605 606 607 608 609 610 611
 */
static int pmacpic_find_viaint(void)
{
	int viaint = -1;

#ifdef CONFIG_ADB_PMU
	struct device_node *np;

	if (pmu_get_model() != PMU_OHARE_BASED)
		goto not_found;
	np = of_find_node_by_name(NULL, "via-pmu");
	if (np == NULL)
		goto not_found;
612
	viaint = irq_of_parse_and_map(np, 0);
613 614

not_found:
615
#endif /* CONFIG_ADB_PMU */
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
	return viaint;
}

static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state)
{
	int viaint = pmacpic_find_viaint();

	sleep_save_mask[0] = ppc_cached_irq_mask[0];
	sleep_save_mask[1] = ppc_cached_irq_mask[1];
	ppc_cached_irq_mask[0] = 0;
	ppc_cached_irq_mask[1] = 0;
	if (viaint > 0)
		set_bit(viaint, ppc_cached_irq_mask);
	out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
	if (max_real_irqs > 32)
		out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
	(void)in_le32(&pmac_irq_hw[0]->event);
	/* make sure mask gets to controller before we return to caller */
	mb();
        (void)in_le32(&pmac_irq_hw[0]->enable);

        return 0;
}

static int pmacpic_resume(struct sys_device *sysdev)
{
	int i;

	out_le32(&pmac_irq_hw[0]->enable, 0);
	if (max_real_irqs > 32)
		out_le32(&pmac_irq_hw[1]->enable, 0);
	mb();
	for (i = 0; i < max_real_irqs; ++i)
		if (test_bit(i, sleep_save_mask))
			pmac_unmask_irq(i);

	return 0;
}

655
#endif /* CONFIG_PM && CONFIG_PPC32 */
656 657

static struct sysdev_class pmacpic_sysclass = {
658
	.name = "pmac_pic",
659 660 661 662 663 664 665 666
};

static struct sys_device device_pmacpic = {
	.id		= 0,
	.cls		= &pmacpic_sysclass,
};

static struct sysdev_driver driver_pmacpic = {
667
#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
668 669
	.suspend	= &pmacpic_suspend,
	.resume		= &pmacpic_resume,
670
#endif /* CONFIG_PM && CONFIG_PPC32 */
671 672 673 674
};

static int __init init_pmacpic_sysfs(void)
{
675
#ifdef CONFIG_PPC32
676 677
	if (max_irqs == 0)
		return -ENODEV;
678
#endif
679 680 681 682 683 684
	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);
	return 0;
}
685
machine_subsys_initcall(powermac, init_pmacpic_sysfs);
686