sh: Use struct syscore_ops instead of sysdevs

Convert the SuperH clocks framework and shared interrupt handling
code to using struct syscore_ops instead of a sysdev classes and
sysdevs for power managment.

This reduces the code size significantly and simplifies it. The
optimizations causing things not to be restored after creating a
hibernation image are removed, but they might lead to undesirable
effects during resume from hibernation (e.g. the clocks would be left
as the boot kernel set them, which might be not the same way as the
hibernated kernel had seen them before the hibernation).

This also is necessary for removing sysdevs from the kernel entirely
in the future.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>

authored by Rafael J. Wysocki and committed by Paul Mundt a696b89c f47adbb9

+86 -120
+19 -51
drivers/sh/clk/core.c
··· 21 21 #include <linux/module.h> 22 22 #include <linux/mutex.h> 23 23 #include <linux/list.h> 24 - #include <linux/sysdev.h> 24 + #include <linux/syscore_ops.h> 25 25 #include <linux/seq_file.h> 26 26 #include <linux/err.h> 27 27 #include <linux/io.h> ··· 630 630 EXPORT_SYMBOL_GPL(clk_round_parent); 631 631 632 632 #ifdef CONFIG_PM 633 - static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) 633 + static void clks_core_resume(void) 634 634 { 635 - static pm_message_t prev_state; 636 635 struct clk *clkp; 637 636 638 - switch (state.event) { 639 - case PM_EVENT_ON: 640 - /* Resumeing from hibernation */ 641 - if (prev_state.event != PM_EVENT_FREEZE) 642 - break; 637 + list_for_each_entry(clkp, &clock_list, node) { 638 + if (likely(clkp->ops)) { 639 + unsigned long rate = clkp->rate; 643 640 644 - list_for_each_entry(clkp, &clock_list, node) { 645 - if (likely(clkp->ops)) { 646 - unsigned long rate = clkp->rate; 647 - 648 - if (likely(clkp->ops->set_parent)) 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 - } 641 + if (likely(clkp->ops->set_parent)) 642 + clkp->ops->set_parent(clkp, 643 + clkp->parent); 644 + if (likely(clkp->ops->set_rate)) 645 + clkp->ops->set_rate(clkp, rate); 646 + else if (likely(clkp->ops->recalc)) 647 + clkp->rate = clkp->ops->recalc(clkp); 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 650 } 667 651 668 - static int clks_sysdev_resume(struct sys_device *dev) 652 + static struct syscore_ops clks_syscore_ops = { 653 + .resume = clks_core_resume, 654 + }; 655 + 656 + static int __init clk_syscore_init(void) 669 657 { 670 - return clks_sysdev_suspend(dev, PMSG_ON); 671 - } 672 - 673 - static struct sysdev_class clks_sysdev_class = { 674 - .name = "clks", 675 - }; 676 - 677 - static struct sysdev_driver clks_sysdev_driver = { 678 - .suspend = clks_sysdev_suspend, 679 - .resume = clks_sysdev_resume, 680 - }; 681 - 682 - static struct sys_device clks_sysdev_dev = { 683 - .cls = &clks_sysdev_class, 684 - }; 685 - 686 - static int __init clk_sysdev_init(void) 687 - { 688 - sysdev_class_register(&clks_sysdev_class); 689 - sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver); 690 - sysdev_register(&clks_sysdev_dev); 658 + register_syscore_ops(&clks_syscore_ops); 691 659 692 660 return 0; 693 661 } 694 - subsys_initcall(clk_sysdev_init); 662 + subsys_initcall(clk_syscore_init); 695 663 #endif 696 664 697 665 /*
+67 -68
drivers/sh/intc/core.c
··· 25 25 #include <linux/interrupt.h> 26 26 #include <linux/sh_intc.h> 27 27 #include <linux/sysdev.h> 28 + #include <linux/syscore_ops.h> 28 29 #include <linux/list.h> 29 30 #include <linux/spinlock.h> 30 31 #include <linux/radix-tree.h> ··· 377 376 return -ENOMEM; 378 377 } 379 378 379 + static int intc_suspend(void) 380 + { 381 + struct intc_desc_int *d; 382 + 383 + list_for_each_entry(d, &intc_list, list) { 384 + int irq; 385 + 386 + /* enable wakeup irqs belonging to this intc controller */ 387 + for_each_active_irq(irq) { 388 + struct irq_data *data; 389 + struct irq_desc *desc; 390 + struct irq_chip *chip; 391 + 392 + data = irq_get_irq_data(irq); 393 + chip = irq_data_get_irq_chip(data); 394 + if (chip != &d->chip) 395 + continue; 396 + desc = irq_to_desc(irq); 397 + if ((desc->status & IRQ_WAKEUP)) 398 + chip->irq_enable(data); 399 + } 400 + } 401 + 402 + return 0; 403 + } 404 + 405 + static void intc_resume(void) 406 + { 407 + struct intc_desc_int *d; 408 + 409 + list_for_each_entry(d, &intc_list, list) { 410 + int irq; 411 + 412 + for_each_active_irq(irq) { 413 + struct irq_data *data; 414 + struct irq_desc *desc; 415 + struct irq_chip *chip; 416 + 417 + data = irq_get_irq_data(irq); 418 + chip = irq_data_get_irq_chip(data); 419 + /* 420 + * This will catch the redirect and VIRQ cases 421 + * due to the dummy_irq_chip being inserted. 422 + */ 423 + if (chip != &d->chip) 424 + continue; 425 + desc = irq_to_desc(irq); 426 + if (desc->status & IRQ_DISABLED) 427 + chip->irq_disable(data); 428 + else 429 + chip->irq_enable(data); 430 + } 431 + } 432 + } 433 + 434 + struct syscore_ops intc_syscore_ops = { 435 + .suspend = intc_suspend, 436 + .resume = intc_resume, 437 + }; 438 + 439 + struct sysdev_class intc_sysdev_class = { 440 + .name = "intc", 441 + }; 442 + 380 443 static ssize_t 381 444 show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) 382 445 { ··· 453 388 454 389 static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL); 455 390 456 - static int intc_suspend(struct sys_device *dev, pm_message_t state) 457 - { 458 - struct intc_desc_int *d; 459 - struct irq_data *data; 460 - struct irq_desc *desc; 461 - struct irq_chip *chip; 462 - int irq; 463 - 464 - /* get intc controller associated with this sysdev */ 465 - d = container_of(dev, struct intc_desc_int, sysdev); 466 - 467 - switch (state.event) { 468 - case PM_EVENT_ON: 469 - if (d->state.event != PM_EVENT_FREEZE) 470 - break; 471 - 472 - for_each_active_irq(irq) { 473 - desc = irq_to_desc(irq); 474 - data = irq_get_irq_data(irq); 475 - chip = irq_data_get_irq_chip(data); 476 - 477 - /* 478 - * This will catch the redirect and VIRQ cases 479 - * due to the dummy_irq_chip being inserted. 480 - */ 481 - if (chip != &d->chip) 482 - continue; 483 - if (desc->status & IRQ_DISABLED) 484 - chip->irq_disable(data); 485 - else 486 - chip->irq_enable(data); 487 - } 488 - break; 489 - case PM_EVENT_FREEZE: 490 - /* nothing has to be done */ 491 - break; 492 - case PM_EVENT_SUSPEND: 493 - /* enable wakeup irqs belonging to this intc controller */ 494 - for_each_active_irq(irq) { 495 - desc = irq_to_desc(irq); 496 - data = irq_get_irq_data(irq); 497 - chip = irq_data_get_irq_chip(data); 498 - 499 - if (chip != &d->chip) 500 - continue; 501 - if ((desc->status & IRQ_WAKEUP)) 502 - chip->irq_enable(data); 503 - } 504 - break; 505 - } 506 - 507 - d->state = state; 508 - 509 - return 0; 510 - } 511 - 512 - static int intc_resume(struct sys_device *dev) 513 - { 514 - return intc_suspend(dev, PMSG_ON); 515 - } 516 - 517 - struct sysdev_class intc_sysdev_class = { 518 - .name = "intc", 519 - .suspend = intc_suspend, 520 - .resume = intc_resume, 521 - }; 522 - 523 - /* register this intc as sysdev to allow suspend/resume */ 524 391 static int __init register_intc_sysdevs(void) 525 392 { 526 393 struct intc_desc_int *d; 527 394 int error; 395 + 396 + register_syscore_ops(&intc_syscore_ops); 528 397 529 398 error = sysdev_class_register(&intc_sysdev_class); 530 399 if (!error) {
-1
drivers/sh/intc/internals.h
··· 53 53 struct list_head list; 54 54 struct sys_device sysdev; 55 55 struct radix_tree_root tree; 56 - pm_message_t state; 57 56 raw_spinlock_t lock; 58 57 unsigned int index; 59 58 unsigned long *reg;