a1fd6fd5a4667a7c5bcab334ca40186009a341d2
[pandora-kernel.git] / arch / arm / mach-omap2 / clockdomain2xxx_3xxx.c
1 /*
2  * OMAP2 and OMAP3 clockdomain control
3  *
4  * Copyright (C) 2008-2010 Texas Instruments, Inc.
5  * Copyright (C) 2008-2010 Nokia Corporation
6  *
7  * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
8  * Rajendra Nayak <rnayak@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
15 #include <linux/types.h>
16 #include <plat/prcm.h>
17 #include "prm.h"
18 #include "prm2xxx_3xxx.h"
19 #include "cm.h"
20 #include "cm2xxx_3xxx.h"
21 #include "cm-regbits-24xx.h"
22 #include "cm-regbits-34xx.h"
23 #include "clockdomain.h"
24
25 static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
26                                                 struct clockdomain *clkdm2)
27 {
28         omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
29                                 clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
30         return 0;
31 }
32
33 static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
34                                                  struct clockdomain *clkdm2)
35 {
36         omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
37                                 clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
38         return 0;
39 }
40
41 static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
42                                                  struct clockdomain *clkdm2)
43 {
44         return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
45                                 PM_WKDEP, (1 << clkdm2->dep_bit));
46 }
47
48 static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
49 {
50         struct clkdm_dep *cd;
51         u32 mask = 0;
52
53         for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
54                 if (!omap_chip_is(cd->omap_chip))
55                         continue;
56                 if (!cd->clkdm)
57                         continue; /* only happens if data is erroneous */
58
59                 /* PRM accesses are slow, so minimize them */
60                 mask |= 1 << cd->clkdm->dep_bit;
61                 atomic_set(&cd->wkdep_usecount, 0);
62         }
63
64         omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
65                                  PM_WKDEP);
66         return 0;
67 }
68
69 static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1,
70                                                  struct clockdomain *clkdm2)
71 {
72         omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
73                                 clkdm1->pwrdm.ptr->prcm_offs,
74                                 OMAP3430_CM_SLEEPDEP);
75         return 0;
76 }
77
78 static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1,
79                                                  struct clockdomain *clkdm2)
80 {
81         omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
82                                 clkdm1->pwrdm.ptr->prcm_offs,
83                                 OMAP3430_CM_SLEEPDEP);
84         return 0;
85 }
86
87 static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1,
88                                                  struct clockdomain *clkdm2)
89 {
90         return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
91                                 OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit));
92 }
93
94 static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
95 {
96         struct clkdm_dep *cd;
97         u32 mask = 0;
98
99         for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
100                 if (!omap_chip_is(cd->omap_chip))
101                         continue;
102                 if (!cd->clkdm)
103                         continue; /* only happens if data is erroneous */
104
105                 /* PRM accesses are slow, so minimize them */
106                 mask |= 1 << cd->clkdm->dep_bit;
107                 atomic_set(&cd->sleepdep_usecount, 0);
108         }
109         omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
110                                 OMAP3430_CM_SLEEPDEP);
111         return 0;
112 }
113
114 struct clkdm_ops omap2_clkdm_operations = {
115         .clkdm_add_wkdep        = omap2_clkdm_add_wkdep,
116         .clkdm_del_wkdep        = omap2_clkdm_del_wkdep,
117         .clkdm_read_wkdep       = omap2_clkdm_read_wkdep,
118         .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps,
119 };
120
121 struct clkdm_ops omap3_clkdm_operations = {
122         .clkdm_add_wkdep        = omap2_clkdm_add_wkdep,
123         .clkdm_del_wkdep        = omap2_clkdm_del_wkdep,
124         .clkdm_read_wkdep       = omap2_clkdm_read_wkdep,
125         .clkdm_clear_all_wkdeps = omap2_clkdm_clear_all_wkdeps,
126         .clkdm_add_sleepdep     = omap3_clkdm_add_sleepdep,
127         .clkdm_del_sleepdep     = omap3_clkdm_del_sleepdep,
128         .clkdm_read_sleepdep    = omap3_clkdm_read_sleepdep,
129         .clkdm_clear_all_sleepdeps      = omap3_clkdm_clear_all_sleepdeps,
130 };