Commit | Line | Data |
---|---|---|
c0407a96 PW |
1 | /* |
2 | * omap-pm-noop.c - OMAP power management interface - dummy version | |
3 | * | |
4 | * This code implements the OMAP power management interface to | |
5 | * drivers, CPUIdle, CPUFreq, and DSP Bridge. It is strictly for | |
6 | * debug/demonstration use, as it does nothing but printk() whenever a | |
7 | * function is called (when DEBUG is defined, below) | |
8 | * | |
9 | * Copyright (C) 2008-2009 Texas Instruments, Inc. | |
10 | * Copyright (C) 2008-2009 Nokia Corporation | |
11 | * Paul Walmsley | |
12 | * | |
13 | * Interface developed by (in alphabetical order): | |
14 | * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan | |
15 | * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff | |
16 | */ | |
17 | ||
18 | #undef DEBUG | |
19 | ||
20 | #include <linux/init.h> | |
21 | #include <linux/cpufreq.h> | |
22 | #include <linux/device.h> | |
23 | ||
24 | /* Interface documentation is in mach/omap-pm.h */ | |
ce491cf8 | 25 | #include <plat/omap-pm.h> |
c0407a96 | 26 | |
ce491cf8 | 27 | #include <plat/powerdomain.h> |
c0407a96 PW |
28 | |
29 | struct omap_opp *dsp_opps; | |
30 | struct omap_opp *mpu_opps; | |
31 | struct omap_opp *l3_opps; | |
32 | ||
33 | /* | |
34 | * Device-driver-originated constraints (via board-*.c files) | |
35 | */ | |
36 | ||
37 | void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t) | |
38 | { | |
39 | if (!dev || t < -1) { | |
40 | WARN_ON(1); | |
41 | return; | |
42 | }; | |
43 | ||
44 | if (t == -1) | |
45 | pr_debug("OMAP PM: remove max MPU wakeup latency constraint: " | |
46 | "dev %s\n", dev_name(dev)); | |
47 | else | |
48 | pr_debug("OMAP PM: add max MPU wakeup latency constraint: " | |
49 | "dev %s, t = %ld usec\n", dev_name(dev), t); | |
50 | ||
51 | /* | |
52 | * For current Linux, this needs to map the MPU to a | |
53 | * powerdomain, then go through the list of current max lat | |
54 | * constraints on the MPU and find the smallest. If | |
55 | * the latency constraint has changed, the code should | |
56 | * recompute the state to enter for the next powerdomain | |
57 | * state. | |
58 | * | |
59 | * TI CDP code can call constraint_set here. | |
60 | */ | |
61 | } | |
62 | ||
63 | void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) | |
64 | { | |
65 | if (!dev || (agent_id != OCP_INITIATOR_AGENT && | |
66 | agent_id != OCP_TARGET_AGENT)) { | |
67 | WARN_ON(1); | |
68 | return; | |
69 | }; | |
70 | ||
71 | if (r == 0) | |
72 | pr_debug("OMAP PM: remove min bus tput constraint: " | |
73 | "dev %s for agent_id %d\n", dev_name(dev), agent_id); | |
74 | else | |
75 | pr_debug("OMAP PM: add min bus tput constraint: " | |
76 | "dev %s for agent_id %d: rate %ld KiB\n", | |
77 | dev_name(dev), agent_id, r); | |
78 | ||
79 | /* | |
80 | * This code should model the interconnect and compute the | |
81 | * required clock frequency, convert that to a VDD2 OPP ID, then | |
82 | * set the VDD2 OPP appropriately. | |
83 | * | |
84 | * TI CDP code can call constraint_set here on the VDD2 OPP. | |
85 | */ | |
86 | } | |
87 | ||
88 | void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t) | |
89 | { | |
90 | if (!dev || t < -1) { | |
91 | WARN_ON(1); | |
92 | return; | |
93 | }; | |
94 | ||
95 | if (t == -1) | |
96 | pr_debug("OMAP PM: remove max device latency constraint: " | |
97 | "dev %s\n", dev_name(dev)); | |
98 | else | |
99 | pr_debug("OMAP PM: add max device latency constraint: " | |
100 | "dev %s, t = %ld usec\n", dev_name(dev), t); | |
101 | ||
102 | /* | |
103 | * For current Linux, this needs to map the device to a | |
104 | * powerdomain, then go through the list of current max lat | |
105 | * constraints on that powerdomain and find the smallest. If | |
106 | * the latency constraint has changed, the code should | |
107 | * recompute the state to enter for the next powerdomain | |
108 | * state. Conceivably, this code should also determine | |
109 | * whether to actually disable the device clocks or not, | |
110 | * depending on how long it takes to re-enable the clocks. | |
111 | * | |
112 | * TI CDP code can call constraint_set here. | |
113 | */ | |
114 | } | |
115 | ||
116 | void omap_pm_set_max_sdma_lat(struct device *dev, long t) | |
117 | { | |
118 | if (!dev || t < -1) { | |
119 | WARN_ON(1); | |
120 | return; | |
121 | }; | |
122 | ||
123 | if (t == -1) | |
124 | pr_debug("OMAP PM: remove max DMA latency constraint: " | |
125 | "dev %s\n", dev_name(dev)); | |
126 | else | |
127 | pr_debug("OMAP PM: add max DMA latency constraint: " | |
128 | "dev %s, t = %ld usec\n", dev_name(dev), t); | |
129 | ||
130 | /* | |
131 | * For current Linux PM QOS params, this code should scan the | |
132 | * list of maximum CPU and DMA latencies and select the | |
133 | * smallest, then set cpu_dma_latency pm_qos_param | |
134 | * accordingly. | |
135 | * | |
136 | * For future Linux PM QOS params, with separate CPU and DMA | |
137 | * latency params, this code should just set the dma_latency param. | |
138 | * | |
139 | * TI CDP code can call constraint_set here. | |
140 | */ | |
141 | ||
142 | } | |
143 | ||
144 | ||
145 | /* | |
146 | * DSP Bridge-specific constraints | |
147 | */ | |
148 | ||
149 | const struct omap_opp *omap_pm_dsp_get_opp_table(void) | |
150 | { | |
151 | pr_debug("OMAP PM: DSP request for OPP table\n"); | |
152 | ||
153 | /* | |
154 | * Return DSP frequency table here: The final item in the | |
155 | * array should have .rate = .opp_id = 0. | |
156 | */ | |
157 | ||
158 | return NULL; | |
159 | } | |
160 | ||
161 | void omap_pm_dsp_set_min_opp(u8 opp_id) | |
162 | { | |
163 | if (opp_id == 0) { | |
164 | WARN_ON(1); | |
165 | return; | |
166 | } | |
167 | ||
168 | pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id); | |
169 | ||
170 | /* | |
171 | * | |
172 | * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we | |
173 | * can just test to see which is higher, the CPU's desired OPP | |
174 | * ID or the DSP's desired OPP ID, and use whichever is | |
175 | * highest. | |
176 | * | |
177 | * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP | |
178 | * rate is keyed on MPU speed, not the OPP ID. So we need to | |
179 | * map the OPP ID to the MPU speed for use with clk_set_rate() | |
180 | * if it is higher than the current OPP clock rate. | |
181 | * | |
182 | */ | |
183 | } | |
184 | ||
185 | ||
186 | u8 omap_pm_dsp_get_opp(void) | |
187 | { | |
188 | pr_debug("OMAP PM: DSP requests current DSP OPP ID\n"); | |
189 | ||
190 | /* | |
191 | * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock | |
192 | * | |
193 | * CDP12.14+: | |
194 | * Call clk_get_rate() on the OPP custom clock, map that to an | |
195 | * OPP ID using the tables defined in board-*.c/chip-*.c files. | |
196 | */ | |
197 | ||
198 | return 0; | |
199 | } | |
200 | ||
201 | /* | |
202 | * CPUFreq-originated constraint | |
203 | * | |
204 | * In the future, this should be handled by custom OPP clocktype | |
205 | * functions. | |
206 | */ | |
207 | ||
208 | struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) | |
209 | { | |
210 | pr_debug("OMAP PM: CPUFreq request for frequency table\n"); | |
211 | ||
212 | /* | |
213 | * Return CPUFreq frequency table here: loop over | |
214 | * all VDD1 clkrates, pull out the mpu_ck frequencies, build | |
215 | * table | |
216 | */ | |
217 | ||
218 | return NULL; | |
219 | } | |
220 | ||
221 | void omap_pm_cpu_set_freq(unsigned long f) | |
222 | { | |
223 | if (f == 0) { | |
224 | WARN_ON(1); | |
225 | return; | |
226 | } | |
227 | ||
228 | pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n", | |
229 | f); | |
230 | ||
231 | /* | |
232 | * For l-o dev tree, determine whether MPU freq or DSP OPP id | |
233 | * freq is higher. Find the OPP ID corresponding to the | |
234 | * higher frequency. Call clk_round_rate() and clk_set_rate() | |
235 | * on the OPP custom clock. | |
236 | * | |
237 | * CDP should just be able to set the VDD1 OPP clock rate here. | |
238 | */ | |
239 | } | |
240 | ||
241 | unsigned long omap_pm_cpu_get_freq(void) | |
242 | { | |
243 | pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n"); | |
244 | ||
245 | /* | |
246 | * Call clk_get_rate() on the mpu_ck. | |
247 | */ | |
248 | ||
249 | return 0; | |
250 | } | |
251 | ||
252 | /* | |
253 | * Device context loss tracking | |
254 | */ | |
255 | ||
256 | int omap_pm_get_dev_context_loss_count(struct device *dev) | |
257 | { | |
258 | if (!dev) { | |
259 | WARN_ON(1); | |
260 | return -EINVAL; | |
261 | }; | |
262 | ||
263 | pr_debug("OMAP PM: returning context loss count for dev %s\n", | |
264 | dev_name(dev)); | |
265 | ||
266 | /* | |
267 | * Map the device to the powerdomain. Return the powerdomain | |
268 | * off counter. | |
269 | */ | |
270 | ||
271 | return 0; | |
272 | } | |
273 | ||
274 | ||
275 | /* Should be called before clk framework init */ | |
276 | int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table, | |
277 | struct omap_opp *dsp_opp_table, | |
278 | struct omap_opp *l3_opp_table) | |
279 | { | |
280 | mpu_opps = mpu_opp_table; | |
281 | dsp_opps = dsp_opp_table; | |
282 | l3_opps = l3_opp_table; | |
283 | return 0; | |
284 | } | |
285 | ||
286 | /* Must be called after clock framework is initialized */ | |
287 | int __init omap_pm_if_init(void) | |
288 | { | |
289 | return 0; | |
290 | } | |
291 | ||
292 | void omap_pm_if_exit(void) | |
293 | { | |
294 | /* Deallocate CPUFreq frequency table here */ | |
295 | } | |
296 |