OMAP3 SRF: Add virt clk nodes for VDD1/VDD2
[linux-ginger.git] / arch / arm / plat-omap / omap-pm-srf.c
blob43ad1bc3c5e17ac8ca55ad06d8b644e786d8671a
1 /*
2 * omap-pm-srf.c - OMAP power management interface implemented
3 * using Shared resource framework
5 * This code implements the OMAP power management interface to
6 * drivers, CPUIdle, CPUFreq, and DSP Bridge. It is strictly for
7 * debug/demonstration use, as it does nothing but printk() whenever a
8 * function is called (when DEBUG is defined, below)
10 * Copyright (C) 2008 Texas Instruments, Inc.
11 * Copyright (C) 2008 Nokia Corporation
12 * Paul Walmsley
14 * Interface developed by (in alphabetical order):
15 * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan
16 * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff
19 #undef DEBUG
21 #include <linux/init.h>
22 #include <linux/cpufreq.h>
23 #include <linux/device.h>
25 #include <plat/omap-pm.h>
26 #include <plat/powerdomain.h>
27 #include <plat/resource.h>
28 #include <plat/omapdev.h>
30 struct omap_opp *dsp_opps;
31 struct omap_opp *mpu_opps;
32 struct omap_opp *l3_opps;
34 #define LAT_RES_POSTAMBLE "_latency"
35 #define MAX_LATENCY_RES_NAME 30
37 /**
38 * get_lat_res_name - gets the latency resource name given a power domain name
39 * @pwrdm_name: Name of the power domain.
40 * @lat_name: Buffer in which latency resource name is populated
41 * @size: Max size of the latency resource name
43 * Returns the latency resource name populated in lat_name.
45 void get_lat_res_name(const char *pwrdm_name, char **lat_name, int size)
47 strcpy(*lat_name, "");
48 WARN_ON(strlen(pwrdm_name) + strlen(LAT_RES_POSTAMBLE) > size);
49 strcpy(*lat_name, pwrdm_name);
50 strcat(*lat_name, LAT_RES_POSTAMBLE);
51 return;
55 * Device-driver-originated constraints (via board-*.c files)
58 void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
60 if (!dev || t < -1) {
61 WARN_ON(1);
62 return;
65 if (t == -1) {
66 pr_debug("OMAP PM: remove max MPU wakeup latency constraint: "
67 "dev %s\n", dev_name(dev));
68 resource_release("mpu_latency", dev);
69 } else {
70 pr_debug("OMAP PM: add max MPU wakeup latency constraint: "
71 "dev %s, t = %ld usec\n", dev_name(dev), t);
72 resource_request("mpu_latency", dev, t);
76 void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
78 if (!dev || agent_id != OCP_INITIATOR_AGENT ||
79 agent_id != OCP_TARGET_AGENT) {
80 WARN_ON(1);
81 return;
84 if (r == 0)
85 pr_debug("OMAP PM: remove min bus tput constraint: "
86 "dev %s for agent_id %d\n", dev_name(dev), agent_id);
87 else
88 pr_debug("OMAP PM: add min bus tput constraint: "
89 "dev %s for agent_id %d: rate %ld KiB\n",
90 dev_name(dev), agent_id, r);
93 * This code should model the interconnect and compute the
94 * required clock frequency, convert that to a VDD2 OPP ID, then
95 * set the VDD2 OPP appropriately.
97 * TI CDP code can call constraint_set here on the VDD2 OPP.
101 void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t)
103 struct omapdev *odev;
104 struct powerdomain *pwrdm_dev;
105 struct platform_device *pdev;
106 char *lat_res_name;
108 if (!dev || t < -1) {
109 WARN_ON(1);
110 return;
112 /* Look for the devices Power Domain */
114 * WARNING! If device is not a platform device, container_of will
115 * return a pointer to unknown memory!
116 * TODO: Either change omap-pm interface to support only platform
117 * devices, or change the underlying omapdev implementation to
118 * support normal devices.
120 pdev = container_of(dev, struct platform_device, dev);
122 /* Try to catch non platform devices. */
123 if (pdev->name == NULL) {
124 printk(KERN_ERR "OMAP-PM: Error: platform device not valid\n");
125 return;
128 odev = omapdev_find_pdev(pdev);
129 if (odev) {
130 pwrdm_dev = omapdev_get_pwrdm(odev);
131 } else {
132 printk(KERN_ERR "OMAP-PM: Error: Could not find omapdev "
133 "for %s\n", pdev->name);
134 return;
137 lat_res_name = kmalloc(MAX_LATENCY_RES_NAME, GFP_KERNEL);
138 if (!lat_res_name) {
139 printk(KERN_ERR "OMAP-PM: FATAL ERROR: kmalloc failed\n");
140 return;
142 get_lat_res_name(pwrdm_dev->name, &lat_res_name, MAX_LATENCY_RES_NAME);
144 if (t == -1) {
145 pr_debug("OMAP PM: remove max device latency constraint: "
146 "dev %s\n", dev_name(dev));
147 resource_release(lat_res_name, dev);
148 } else {
149 pr_debug("OMAP PM: add max device latency constraint: "
150 "dev %s, t = %ld usec\n", dev_name(dev), t);
151 resource_request(lat_res_name, dev, t);
154 kfree(lat_res_name);
155 return;
158 void omap_pm_set_max_sdma_lat(struct device *dev, long t)
160 if (!dev || t < -1) {
161 WARN_ON(1);
162 return;
165 if (t == -1) {
166 pr_debug("OMAP PM: remove max DMA latency constraint: "
167 "dev %s\n", dev_name(dev));
168 resource_release("core_latency", dev);
169 } else {
170 pr_debug("OMAP PM: add max DMA latency constraint: "
171 "dev %s, t = %ld usec\n", dev_name(dev), t);
172 resource_request("core_latency", dev, t);
178 * DSP Bridge-specific constraints
180 const struct omap_opp *omap_pm_dsp_get_opp_table(void)
182 pr_debug("OMAP PM: DSP request for OPP table\n");
185 * Return DSP frequency table here: The final item in the
186 * array should have .rate = .opp_id = 0.
189 return NULL;
192 void omap_pm_dsp_set_min_opp(u8 opp_id)
194 if (opp_id == 0) {
195 WARN_ON(1);
196 return;
199 pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id);
203 * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we
204 * can just test to see which is higher, the CPU's desired OPP
205 * ID or the DSP's desired OPP ID, and use whichever is
206 * highest.
208 * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP
209 * rate is keyed on MPU speed, not the OPP ID. So we need to
210 * map the OPP ID to the MPU speed for use with clk_set_rate()
211 * if it is higher than the current OPP clock rate.
216 u8 omap_pm_dsp_get_opp(void)
218 pr_debug("OMAP PM: DSP requests current DSP OPP ID\n");
221 * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock
223 * CDP12.14+:
224 * Call clk_get_rate() on the OPP custom clock, map that to an
225 * OPP ID using the tables defined in board-*.c/chip-*.c files.
228 return 0;
232 * CPUFreq-originated constraint
234 * In the future, this should be handled by custom OPP clocktype
235 * functions.
238 struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void)
240 pr_debug("OMAP PM: CPUFreq request for frequency table\n");
243 * Return CPUFreq frequency table here: loop over
244 * all VDD1 clkrates, pull out the mpu_ck frequencies, build
245 * table
248 return NULL;
251 void omap_pm_cpu_set_freq(unsigned long f)
253 if (f == 0) {
254 WARN_ON(1);
255 return;
258 pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n",
262 * For l-o dev tree, determine whether MPU freq or DSP OPP id
263 * freq is higher. Find the OPP ID corresponding to the
264 * higher frequency. Call clk_round_rate() and clk_set_rate()
265 * on the OPP custom clock.
267 * CDP should just be able to set the VDD1 OPP clock rate here.
271 unsigned long omap_pm_cpu_get_freq(void)
273 pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n");
276 * Call clk_get_rate() on the mpu_ck.
279 return 0;
283 * Device context loss tracking
286 int omap_pm_get_dev_context_loss_count(struct device *dev)
288 if (!dev) {
289 WARN_ON(1);
290 return -EINVAL;
293 pr_debug("OMAP PM: returning context loss count for dev %s\n",
294 dev_name(dev));
297 * Map the device to the powerdomain. Return the powerdomain
298 * off counter.
301 return 0;
305 * Powerdomain usecounting hooks
308 void omap_pm_pwrdm_active(struct powerdomain *pwrdm)
310 if (!pwrdm) {
311 WARN_ON(1);
312 return;
315 pr_debug("OMAP PM: powerdomain %s is becoming active\n", pwrdm->name);
318 * CDP code apparently will need these for the enable_power_domain()
319 * and disable_power_domain() functions.
323 void omap_pm_pwrdm_inactive(struct powerdomain *pwrdm)
325 if (!pwrdm) {
326 WARN_ON(1);
327 return;
330 pr_debug("OMAP PM: powerdomain %s is becoming inactive\n",
331 pwrdm->name);
334 * CDP code apparently will need these for the enable_power_domain()
335 * and disable_power_domain() functions.
340 * Should be called before clk framework since clk fw will call
341 * omap_pm_pwrdm_{in,}active()
343 int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table,
344 struct omap_opp *dsp_opp_table,
345 struct omap_opp *l3_opp_table)
347 mpu_opps = mpu_opp_table;
348 dsp_opps = dsp_opp_table;
349 l3_opps = l3_opp_table;
350 return 0;
353 /* Must be called after clock framework is initialized */
354 int __init omap_pm_if_init(void)
356 resource_init(resources_omap);
357 return 0;
360 void omap_pm_if_exit(void)
362 /* Deallocate CPUFreq frequency table here */