Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
clockdomain44xx.c
Go to the documentation of this file.
1 /*
2  * OMAP4 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 <[email protected]>
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/kernel.h>
16 #include "clockdomain.h"
17 #include "cminst44xx.h"
18 #include "cm44xx.h"
19 
20 static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1,
21  struct clockdomain *clkdm2)
22 {
24  clkdm1->prcm_partition,
25  clkdm1->cm_inst, clkdm1->clkdm_offs +
27  return 0;
28 }
29 
30 static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1,
31  struct clockdomain *clkdm2)
32 {
34  clkdm1->prcm_partition,
35  clkdm1->cm_inst, clkdm1->clkdm_offs +
37  return 0;
38 }
39 
40 static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1,
41  struct clockdomain *clkdm2)
42 {
44  clkdm1->cm_inst, clkdm1->clkdm_offs +
46  (1 << clkdm2->dep_bit));
47 }
48 
49 static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
50 {
51  struct clkdm_dep *cd;
52  u32 mask = 0;
53 
54  if (!clkdm->prcm_partition)
55  return 0;
56 
57  for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
58  if (!cd->clkdm)
59  continue; /* only happens if data is erroneous */
60 
61  mask |= 1 << cd->clkdm->dep_bit;
62  atomic_set(&cd->wkdep_usecount, 0);
63  }
64 
66  clkdm->cm_inst, clkdm->clkdm_offs +
68  return 0;
69 }
70 
71 static int omap4_clkdm_sleep(struct clockdomain *clkdm)
72 {
74  clkdm->cm_inst, clkdm->clkdm_offs);
75  return 0;
76 }
77 
78 static int omap4_clkdm_wakeup(struct clockdomain *clkdm)
79 {
81  clkdm->cm_inst, clkdm->clkdm_offs);
82  return 0;
83 }
84 
85 static void omap4_clkdm_allow_idle(struct clockdomain *clkdm)
86 {
88  clkdm->cm_inst, clkdm->clkdm_offs);
89 }
90 
91 static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
92 {
93  if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
94  omap4_clkdm_wakeup(clkdm);
95  else
97  clkdm->cm_inst,
98  clkdm->clkdm_offs);
99 }
100 
101 static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
102 {
103  if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
104  return omap4_clkdm_wakeup(clkdm);
105 
106  return 0;
107 }
108 
109 static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
110 {
111  bool hwsup = false;
112 
113  if (!clkdm->prcm_partition)
114  return 0;
115 
116  /*
117  * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
118  * more details on the unpleasant problem this is working
119  * around
120  */
121  if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
122  !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
123  omap4_clkdm_allow_idle(clkdm);
124  return 0;
125  }
126 
128  clkdm->cm_inst, clkdm->clkdm_offs);
129 
130  if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
131  omap4_clkdm_sleep(clkdm);
132 
133  return 0;
134 }
135 
137  .clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep,
138  .clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep,
139  .clkdm_read_wkdep = omap4_clkdm_read_wkup_sleep_dep,
140  .clkdm_clear_all_wkdeps = omap4_clkdm_clear_all_wkup_sleep_deps,
141  .clkdm_add_sleepdep = omap4_clkdm_add_wkup_sleep_dep,
142  .clkdm_del_sleepdep = omap4_clkdm_del_wkup_sleep_dep,
143  .clkdm_read_sleepdep = omap4_clkdm_read_wkup_sleep_dep,
144  .clkdm_clear_all_sleepdeps = omap4_clkdm_clear_all_wkup_sleep_deps,
145  .clkdm_sleep = omap4_clkdm_sleep,
146  .clkdm_wakeup = omap4_clkdm_wakeup,
147  .clkdm_allow_idle = omap4_clkdm_allow_idle,
148  .clkdm_deny_idle = omap4_clkdm_deny_idle,
149  .clkdm_clk_enable = omap4_clkdm_clk_enable,
150  .clkdm_clk_disable = omap4_clkdm_clk_disable,
151 };