aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sh')
-rw-r--r--drivers/sh/clk/core.c68
-rw-r--r--drivers/sh/intc/core.c95
-rw-r--r--drivers/sh/intc/internals.h1
3 files changed, 65 insertions, 99 deletions
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c
index 5f63c3b83828..4f64183b27fa 100644
--- a/drivers/sh/clk/core.c
+++ b/drivers/sh/clk/core.c
@@ -21,7 +21,7 @@
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <linux/list.h> 23#include <linux/list.h>
24#include <linux/sysdev.h> 24#include <linux/syscore_ops.h>
25#include <linux/seq_file.h> 25#include <linux/seq_file.h>
26#include <linux/err.h> 26#include <linux/err.h>
27#include <linux/io.h> 27#include <linux/io.h>
@@ -630,68 +630,36 @@ long clk_round_parent(struct clk *clk, unsigned long target,
630EXPORT_SYMBOL_GPL(clk_round_parent); 630EXPORT_SYMBOL_GPL(clk_round_parent);
631 631
632#ifdef CONFIG_PM 632#ifdef CONFIG_PM
633static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) 633static void clks_core_resume(void)
634{ 634{
635 static pm_message_t prev_state;
636 struct clk *clkp; 635 struct clk *clkp;
637 636
638 switch (state.event) { 637 list_for_each_entry(clkp, &clock_list, node) {
639 case PM_EVENT_ON: 638 if (likely(clkp->ops)) {
640 /* Resumeing from hibernation */ 639 unsigned long rate = clkp->rate;
641 if (prev_state.event != PM_EVENT_FREEZE) 640
642 break; 641 if (likely(clkp->ops->set_parent))
643 642 clkp->ops->set_parent(clkp,
644 list_for_each_entry(clkp, &clock_list, node) { 643 clkp->parent);
645 if (likely(clkp->ops)) { 644 if (likely(clkp->ops->set_rate))
646 unsigned long rate = clkp->rate; 645 clkp->ops->set_rate(clkp, rate);
647 646 else if (likely(clkp->ops->recalc))
648 if (likely(clkp->ops->set_parent)) 647 clkp->rate = clkp->ops->recalc(clkp);
649 clkp->ops->set_parent(clkp,
650 clkp->parent);
651 if (likely(clkp->ops->set_rate))
652 clkp->ops->set_rate(clkp, rate);
653 else if (likely(clkp->ops->recalc))
654 clkp->rate = clkp->ops->recalc(clkp);
655 }
656 } 648 }
657 break;
658 case PM_EVENT_FREEZE:
659 break;
660 case PM_EVENT_SUSPEND:
661 break;
662 } 649 }
663
664 prev_state = state;
665 return 0;
666}
667
668static int clks_sysdev_resume(struct sys_device *dev)
669{
670 return clks_sysdev_suspend(dev, PMSG_ON);
671} 650}
672 651
673static struct sysdev_class clks_sysdev_class = { 652static struct syscore_ops clks_syscore_ops = {
674 .name = "clks", 653 .resume = clks_core_resume,
675};
676
677static struct sysdev_driver clks_sysdev_driver = {
678 .suspend = clks_sysdev_suspend,
679 .resume = clks_sysdev_resume,
680};
681
682static struct sys_device clks_sysdev_dev = {
683 .cls = &clks_sysdev_class,
684}; 654};
685 655
686static int __init clk_sysdev_init(void) 656static int __init clk_syscore_init(void)
687{ 657{
688 sysdev_class_register(&clks_sysdev_class); 658 register_syscore_ops(&clks_syscore_ops);
689 sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver);
690 sysdev_register(&clks_sysdev_dev);
691 659
692 return 0; 660 return 0;
693} 661}
694subsys_initcall(clk_sysdev_init); 662subsys_initcall(clk_syscore_init);
695#endif 663#endif
696 664
697/* 665/*
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) {
diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h
index 0cf8260971d4..df36a421e675 100644
--- a/drivers/sh/intc/internals.h
+++ b/drivers/sh/intc/internals.h
@@ -53,7 +53,6 @@ struct intc_desc_int {
53 struct list_head list; 53 struct list_head list;
54 struct sys_device sysdev; 54 struct sys_device sysdev;
55 struct radix_tree_root tree; 55 struct radix_tree_root tree;
56 pm_message_t state;
57 raw_spinlock_t lock; 56 raw_spinlock_t lock;
58 unsigned int index; 57 unsigned int index;
59 unsigned long *reg; 58 unsigned long *reg;