clockdomain.c (59fb659b065f52fcc2deed293cfbfc58f890376c) clockdomain.c (c4d7e58fb52c632d8e33cd23a4917d7a7f8302ac)
1/*
2 * OMAP2/3/4 clockdomain framework functions
3 *
4 * Copyright (C) 2008-2010 Texas Instruments, Inc.
5 * Copyright (C) 2008-2010 Nokia Corporation
6 *
7 * Written by Paul Walmsley and Jouni Högander
8 * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#undef DEBUG
15
1/*
2 * OMAP2/3/4 clockdomain framework functions
3 *
4 * Copyright (C) 2008-2010 Texas Instruments, Inc.
5 * Copyright (C) 2008-2010 Nokia Corporation
6 *
7 * Written by Paul Walmsley and Jouni Högander
8 * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#undef DEBUG
15
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/device.h>
19#include <linux/list.h>
20#include <linux/errno.h>
21#include <linux/delay.h>
22#include <linux/clk.h>
23#include <linux/limits.h>
24#include <linux/err.h>
25
26#include <linux/io.h>
27
28#include <linux/bitops.h>
29
30#include "prm2xxx_3xxx.h"
31#include "prm-regbits-24xx.h"
32#include "cm2xxx_3xxx.h"
16#include <linux/kernel.h>
17#include <linux/device.h>
18#include <linux/list.h>
19#include <linux/errno.h>
20#include <linux/delay.h>
21#include <linux/clk.h>
22#include <linux/limits.h>
23#include <linux/err.h>
24
25#include <linux/io.h>
26
27#include <linux/bitops.h>
28
29#include "prm2xxx_3xxx.h"
30#include "prm-regbits-24xx.h"
31#include "cm2xxx_3xxx.h"
33#include "cm2xxx_3xxx.h"
34
35#include <plat/clock.h>
36#include <plat/powerdomain.h>
37#include <plat/clockdomain.h>
38#include <plat/prcm.h>
39
40/* clkdm_list contains all registered struct clockdomains */
41static LIST_HEAD(clkdm_list);

--- 363 unchanged lines hidden (view full) ---

405 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
406 return PTR_ERR(cd);
407 }
408
409 if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
410 pr_debug("clockdomain: hardware will wake up %s when %s wakes "
411 "up\n", clkdm1->name, clkdm2->name);
412
32
33#include <plat/clock.h>
34#include <plat/powerdomain.h>
35#include <plat/clockdomain.h>
36#include <plat/prcm.h>
37
38/* clkdm_list contains all registered struct clockdomains */
39static LIST_HEAD(clkdm_list);

--- 363 unchanged lines hidden (view full) ---

403 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
404 return PTR_ERR(cd);
405 }
406
407 if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
408 pr_debug("clockdomain: hardware will wake up %s when %s wakes "
409 "up\n", clkdm1->name, clkdm2->name);
410
413 prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
411 omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
414 clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
415 }
416
417 return 0;
418}
419
420/**
421 * clkdm_del_wkdep - remove a wakeup dependency from clkdm2 to clkdm1

--- 18 unchanged lines hidden (view full) ---

440 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
441 return PTR_ERR(cd);
442 }
443
444 if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
445 pr_debug("clockdomain: hardware will no longer wake up %s "
446 "after %s wakes up\n", clkdm1->name, clkdm2->name);
447
412 clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
413 }
414
415 return 0;
416}
417
418/**
419 * clkdm_del_wkdep - remove a wakeup dependency from clkdm2 to clkdm1

--- 18 unchanged lines hidden (view full) ---

438 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
439 return PTR_ERR(cd);
440 }
441
442 if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
443 pr_debug("clockdomain: hardware will no longer wake up %s "
444 "after %s wakes up\n", clkdm1->name, clkdm2->name);
445
448 prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
446 omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
449 clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
450 }
451
452 return 0;
453}
454
455/**
456 * clkdm_read_wkdep - read wakeup dependency state from clkdm2 to clkdm1

--- 19 unchanged lines hidden (view full) ---

476 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
477 if (IS_ERR(cd)) {
478 pr_debug("clockdomain: hardware cannot set/clear wake up of "
479 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
480 return PTR_ERR(cd);
481 }
482
483 /* XXX It's faster to return the atomic wkdep_usecount */
447 clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
448 }
449
450 return 0;
451}
452
453/**
454 * clkdm_read_wkdep - read wakeup dependency state from clkdm2 to clkdm1

--- 19 unchanged lines hidden (view full) ---

474 cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
475 if (IS_ERR(cd)) {
476 pr_debug("clockdomain: hardware cannot set/clear wake up of "
477 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
478 return PTR_ERR(cd);
479 }
480
481 /* XXX It's faster to return the atomic wkdep_usecount */
484 return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
482 return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
485 (1 << clkdm2->dep_bit));
486}
487
488/**
489 * clkdm_clear_all_wkdeps - remove all wakeup dependencies from target clkdm
490 * @clkdm: struct clockdomain * to remove all wakeup dependencies from
491 *
492 * Remove all inter-clockdomain wakeup dependencies that could cause

--- 17 unchanged lines hidden (view full) ---

510 if (!cd->clkdm && cd->clkdm_name)
511 cd->clkdm = _clkdm_lookup(cd->clkdm_name);
512
513 /* PRM accesses are slow, so minimize them */
514 mask |= 1 << cd->clkdm->dep_bit;
515 atomic_set(&cd->wkdep_usecount, 0);
516 }
517
483 (1 << clkdm2->dep_bit));
484}
485
486/**
487 * clkdm_clear_all_wkdeps - remove all wakeup dependencies from target clkdm
488 * @clkdm: struct clockdomain * to remove all wakeup dependencies from
489 *
490 * Remove all inter-clockdomain wakeup dependencies that could cause

--- 17 unchanged lines hidden (view full) ---

508 if (!cd->clkdm && cd->clkdm_name)
509 cd->clkdm = _clkdm_lookup(cd->clkdm_name);
510
511 /* PRM accesses are slow, so minimize them */
512 mask |= 1 << cd->clkdm->dep_bit;
513 atomic_set(&cd->wkdep_usecount, 0);
514 }
515
518 prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
516 omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
519
520 return 0;
521}
522
523/**
524 * clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1
525 * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
526 * @clkdm2: when this struct clockdomain * is active (source)

--- 22 unchanged lines hidden (view full) ---

549 clkdm2->name);
550 return PTR_ERR(cd);
551 }
552
553 if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
554 pr_debug("clockdomain: will prevent %s from sleeping if %s "
555 "is active\n", clkdm1->name, clkdm2->name);
556
517
518 return 0;
519}
520
521/**
522 * clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1
523 * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
524 * @clkdm2: when this struct clockdomain * is active (source)

--- 22 unchanged lines hidden (view full) ---

547 clkdm2->name);
548 return PTR_ERR(cd);
549 }
550
551 if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
552 pr_debug("clockdomain: will prevent %s from sleeping if %s "
553 "is active\n", clkdm1->name, clkdm2->name);
554
557 cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
555 omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
558 clkdm1->pwrdm.ptr->prcm_offs,
559 OMAP3430_CM_SLEEPDEP);
560 }
561
562 return 0;
563}
564
565/**

--- 26 unchanged lines hidden (view full) ---

592 return PTR_ERR(cd);
593 }
594
595 if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
596 pr_debug("clockdomain: will no longer prevent %s from "
597 "sleeping if %s is active\n", clkdm1->name,
598 clkdm2->name);
599
556 clkdm1->pwrdm.ptr->prcm_offs,
557 OMAP3430_CM_SLEEPDEP);
558 }
559
560 return 0;
561}
562
563/**

--- 26 unchanged lines hidden (view full) ---

590 return PTR_ERR(cd);
591 }
592
593 if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
594 pr_debug("clockdomain: will no longer prevent %s from "
595 "sleeping if %s is active\n", clkdm1->name,
596 clkdm2->name);
597
600 cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
598 omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
601 clkdm1->pwrdm.ptr->prcm_offs,
602 OMAP3430_CM_SLEEPDEP);
603 }
604
605 return 0;
606}
607
608/**

--- 26 unchanged lines hidden (view full) ---

635 if (IS_ERR(cd)) {
636 pr_debug("clockdomain: hardware cannot set/clear sleep "
637 "dependency affecting %s from %s\n", clkdm1->name,
638 clkdm2->name);
639 return PTR_ERR(cd);
640 }
641
642 /* XXX It's faster to return the atomic sleepdep_usecount */
599 clkdm1->pwrdm.ptr->prcm_offs,
600 OMAP3430_CM_SLEEPDEP);
601 }
602
603 return 0;
604}
605
606/**

--- 26 unchanged lines hidden (view full) ---

633 if (IS_ERR(cd)) {
634 pr_debug("clockdomain: hardware cannot set/clear sleep "
635 "dependency affecting %s from %s\n", clkdm1->name,
636 clkdm2->name);
637 return PTR_ERR(cd);
638 }
639
640 /* XXX It's faster to return the atomic sleepdep_usecount */
643 return prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
641 return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
644 OMAP3430_CM_SLEEPDEP,
645 (1 << clkdm2->dep_bit));
646}
647
648/**
649 * clkdm_clear_all_sleepdeps - remove all sleep dependencies from target clkdm
650 * @clkdm: struct clockdomain * to remove all sleep dependencies from
651 *

--- 21 unchanged lines hidden (view full) ---

673 if (!cd->clkdm && cd->clkdm_name)
674 cd->clkdm = _clkdm_lookup(cd->clkdm_name);
675
676 /* PRM accesses are slow, so minimize them */
677 mask |= 1 << cd->clkdm->dep_bit;
678 atomic_set(&cd->sleepdep_usecount, 0);
679 }
680
642 OMAP3430_CM_SLEEPDEP,
643 (1 << clkdm2->dep_bit));
644}
645
646/**
647 * clkdm_clear_all_sleepdeps - remove all sleep dependencies from target clkdm
648 * @clkdm: struct clockdomain * to remove all sleep dependencies from
649 *

--- 21 unchanged lines hidden (view full) ---

671 if (!cd->clkdm && cd->clkdm_name)
672 cd->clkdm = _clkdm_lookup(cd->clkdm_name);
673
674 /* PRM accesses are slow, so minimize them */
675 mask |= 1 << cd->clkdm->dep_bit;
676 atomic_set(&cd->sleepdep_usecount, 0);
677 }
678
681 prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
679 omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
682 OMAP3430_CM_SLEEPDEP);
683
684 return 0;
685}
686
687/**
688 * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
689 * @clkdm: struct clkdm * of a clockdomain

--- 35 unchanged lines hidden (view full) ---

725 "sleep via software\n", clkdm->name);
726 return -EINVAL;
727 }
728
729 pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
730
731 if (cpu_is_omap24xx()) {
732
680 OMAP3430_CM_SLEEPDEP);
681
682 return 0;
683}
684
685/**
686 * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
687 * @clkdm: struct clkdm * of a clockdomain

--- 35 unchanged lines hidden (view full) ---

723 "sleep via software\n", clkdm->name);
724 return -EINVAL;
725 }
726
727 pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
728
729 if (cpu_is_omap24xx()) {
730
733 cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
731 omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
734 clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
735
736 } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
737
738 u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_SLEEP <<
739 __ffs(clkdm->clktrctrl_mask));
740
741 u32 v = __raw_readl(clkdm->clkstctrl_reg);

--- 27 unchanged lines hidden (view full) ---

769 "wakeup via software\n", clkdm->name);
770 return -EINVAL;
771 }
772
773 pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
774
775 if (cpu_is_omap24xx()) {
776
732 clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
733
734 } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
735
736 u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_SLEEP <<
737 __ffs(clkdm->clktrctrl_mask));
738
739 u32 v = __raw_readl(clkdm->clkstctrl_reg);

--- 27 unchanged lines hidden (view full) ---

767 "wakeup via software\n", clkdm->name);
768 return -EINVAL;
769 }
770
771 pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
772
773 if (cpu_is_omap24xx()) {
774
777 cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
775 omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
778 clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
779
780 } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
781
782 u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_WAKEUP <<
783 __ffs(clkdm->clktrctrl_mask));
784
785 u32 v = __raw_readl(clkdm->clkstctrl_reg);

--- 209 unchanged lines hidden ---
776 clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
777
778 } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
779
780 u32 bits = (OMAP34XX_CLKSTCTRL_FORCE_WAKEUP <<
781 __ffs(clkdm->clktrctrl_mask));
782
783 u32 v = __raw_readl(clkdm->clkstctrl_reg);

--- 209 unchanged lines hidden ---