aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh/intc/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sh/intc/core.c')
-rw-r--r--drivers/sh/intc/core.c95
1 files changed, 47 insertions, 48 deletions
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
index 9739431092d1..5833afbf08d7 100644
--- a/drivers/sh/intc/core.c
+++ b/drivers/sh/intc/core.c
@@ -25,6 +25,7 @@
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/sh_intc.h> 26#include <linux/sh_intc.h>
27#include <linux/sysdev.h> 27#include <linux/sysdev.h>
28#include <linux/syscore_ops.h>
28#include <linux/list.h> 29#include <linux/list.h>
29#include <linux/spinlock.h> 30#include <linux/spinlock.h>
30#include <linux/radix-tree.h> 31#include <linux/radix-tree.h>
@@ -376,91 +377,89 @@ err0:
376 return -ENOMEM; 377 return -ENOMEM;
377} 378}
378 379
379static ssize_t 380static int intc_suspend(void)
380show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf)
381{ 381{
382 struct intc_desc_int *d; 382 struct intc_desc_int *d;
383 383
384 d = container_of(dev, struct intc_desc_int, sysdev); 384 list_for_each_entry(d, &intc_list, list) {
385 int irq;
385 386
386 return sprintf(buf, "%s\n", d->chip.name); 387 /* enable wakeup irqs belonging to this intc controller */
387} 388 for_each_active_irq(irq) {
389 struct irq_data *data;
390 struct irq_desc *desc;
391 struct irq_chip *chip;
388 392
389static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL); 393 data = irq_get_irq_data(irq);
394 chip = irq_data_get_irq_chip(data);
395 if (chip != &d->chip)
396 continue;
397 desc = irq_to_desc(irq);
398 if ((desc->status & IRQ_WAKEUP))
399 chip->irq_enable(data);
400 }
401 }
402
403 return 0;
404}
390 405
391static int intc_suspend(struct sys_device *dev, pm_message_t state) 406static void intc_resume(void)
392{ 407{
393 struct intc_desc_int *d; 408 struct intc_desc_int *d;
394 struct irq_data *data;
395 struct irq_desc *desc;
396 struct irq_chip *chip;
397 int irq;
398
399 /* get intc controller associated with this sysdev */
400 d = container_of(dev, struct intc_desc_int, sysdev);
401 409
402 switch (state.event) { 410 list_for_each_entry(d, &intc_list, list) {
403 case PM_EVENT_ON: 411 int irq;
404 if (d->state.event != PM_EVENT_FREEZE)
405 break;
406 412
407 for_each_active_irq(irq) { 413 for_each_active_irq(irq) {
408 desc = irq_to_desc(irq); 414 struct irq_data *data;
415 struct irq_desc *desc;
416 struct irq_chip *chip;
417
409 data = irq_get_irq_data(irq); 418 data = irq_get_irq_data(irq);
410 chip = irq_data_get_irq_chip(data); 419 chip = irq_data_get_irq_chip(data);
411
412 /* 420 /*
413 * This will catch the redirect and VIRQ cases 421 * This will catch the redirect and VIRQ cases
414 * due to the dummy_irq_chip being inserted. 422 * due to the dummy_irq_chip being inserted.
415 */ 423 */
416 if (chip != &d->chip) 424 if (chip != &d->chip)
417 continue; 425 continue;
426 desc = irq_to_desc(irq);
418 if (desc->status & IRQ_DISABLED) 427 if (desc->status & IRQ_DISABLED)
419 chip->irq_disable(data); 428 chip->irq_disable(data);
420 else 429 else
421 chip->irq_enable(data); 430 chip->irq_enable(data);
422 } 431 }
423 break;
424 case PM_EVENT_FREEZE:
425 /* nothing has to be done */
426 break;
427 case PM_EVENT_SUSPEND:
428 /* enable wakeup irqs belonging to this intc controller */
429 for_each_active_irq(irq) {
430 desc = irq_to_desc(irq);
431 data = irq_get_irq_data(irq);
432 chip = irq_data_get_irq_chip(data);
433
434 if (chip != &d->chip)
435 continue;
436 if ((desc->status & IRQ_WAKEUP))
437 chip->irq_enable(data);
438 }
439 break;
440 } 432 }
441
442 d->state = state;
443
444 return 0;
445} 433}
446 434
447static int intc_resume(struct sys_device *dev) 435struct syscore_ops intc_syscore_ops = {
448{ 436 .suspend = intc_suspend,
449 return intc_suspend(dev, PMSG_ON); 437 .resume = intc_resume,
450} 438};
451 439
452struct sysdev_class intc_sysdev_class = { 440struct sysdev_class intc_sysdev_class = {
453 .name = "intc", 441 .name = "intc",
454 .suspend = intc_suspend,
455 .resume = intc_resume,
456}; 442};
457 443
458/* register this intc as sysdev to allow suspend/resume */ 444static ssize_t
445show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf)
446{
447 struct intc_desc_int *d;
448
449 d = container_of(dev, struct intc_desc_int, sysdev);
450
451 return sprintf(buf, "%s\n", d->chip.name);
452}
453
454static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL);
455
459static int __init register_intc_sysdevs(void) 456static int __init register_intc_sysdevs(void)
460{ 457{
461 struct intc_desc_int *d; 458 struct intc_desc_int *d;
462 int error; 459 int error;
463 460
461 register_syscore_ops(&intc_syscore_ops);
462
464 error = sysdev_class_register(&intc_sysdev_class); 463 error = sysdev_class_register(&intc_sysdev_class);
465 if (!error) { 464 if (!error) {
466 list_for_each_entry(d, &intc_list, list) { 465 list_for_each_entry(d, &intc_list, list) {