c3b4085df73879c7a23d4086f9392b295564b378
[linux-2.6.git] / drivers / video / tegra / host / nvhost_acm.c
1 /*
2  * drivers/video/tegra/host/nvhost_acm.c
3  *
4  * Tegra Graphics Host Automatic Clock Management
5  *
6  * Copyright (c) 2010-2011, NVIDIA Corporation.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  */
22
23 #include "nvhost_acm.h"
24 #include "dev.h"
25 #include <linux/slab.h>
26 #include <linux/string.h>
27 #include <linux/sched.h>
28 #include <linux/err.h>
29 #include <linux/device.h>
30 #include <linux/delay.h>
31 #include <mach/powergate.h>
32 #include <mach/clk.h>
33 #include <mach/hardware.h>
34
35 #define ACM_SUSPEND_WAIT_FOR_IDLE_TIMEOUT (2 * HZ)
36 #define POWERGATE_DELAY 10
37 #define MAX_DEVID_LENGTH 16
38
39 DEFINE_MUTEX(client_list_lock);
40
41 struct nvhost_module_client {
42         struct list_head node;
43         unsigned long rate[NVHOST_MODULE_MAX_CLOCKS];
44         void *priv;
45 };
46
47 static void do_powergate_locked(int id)
48 {
49         if (id != -1 && tegra_powergate_is_powered(id))
50                 tegra_powergate_partition(id);
51 }
52
53 static void do_unpowergate_locked(int id)
54 {
55         if (id != -1)
56                 tegra_unpowergate_partition(id);
57 }
58
59 void nvhost_module_reset(struct device *dev, struct nvhost_module *mod)
60 {
61         dev_dbg(dev,
62                 "%s: asserting %s module reset (id %d, id2 %d)\n",
63                 __func__, mod->name,
64                 mod->desc->powergate_ids[0], mod->desc->powergate_ids[1]);
65
66         mutex_lock(&mod->lock);
67
68         /* assert module and mc client reset */
69         if (mod->desc->powergate_ids[0] != -1) {
70                 tegra_powergate_mc_disable(mod->desc->powergate_ids[0]);
71                 tegra_periph_reset_assert(mod->clk[0]);
72                 tegra_powergate_mc_flush(mod->desc->powergate_ids[0]);
73         }
74         if (mod->desc->powergate_ids[1] != -1) {
75                 tegra_powergate_mc_disable(mod->desc->powergate_ids[1]);
76                 tegra_periph_reset_assert(mod->clk[1]);
77                 tegra_powergate_mc_flush(mod->desc->powergate_ids[1]);
78         }
79
80         udelay(POWERGATE_DELAY);
81
82         /* deassert reset */
83         if (mod->desc->powergate_ids[0] != -1) {
84                 tegra_powergate_mc_flush_done(mod->desc->powergate_ids[0]);
85                 tegra_periph_reset_deassert(mod->clk[0]);
86                 tegra_powergate_mc_enable(mod->desc->powergate_ids[0]);
87         }
88         if (mod->desc->powergate_ids[1] != -1) {
89                 tegra_powergate_mc_flush_done(mod->desc->powergate_ids[1]);
90                 tegra_periph_reset_deassert(mod->clk[1]);
91                 tegra_powergate_mc_enable(mod->desc->powergate_ids[1]);
92         }
93
94         mutex_unlock(&mod->lock);
95
96         dev_dbg(dev, "%s: module %s out of reset\n",
97                 __func__, mod->name);
98 }
99
100 static void to_state_clockgated_locked(struct nvhost_module *mod)
101 {
102         const struct nvhost_moduledesc *desc = mod->desc;
103         if (mod->powerstate == NVHOST_POWER_STATE_RUNNING) {
104                 int i;
105                 for (i = 0; i < mod->num_clks; i++)
106                         clk_disable(mod->clk[i]);
107                 if (mod->parent)
108                         nvhost_module_idle(mod->parent);
109         } else if (mod->powerstate == NVHOST_POWER_STATE_POWERGATED
110                         && mod->desc->can_powergate) {
111                 do_unpowergate_locked(desc->powergate_ids[0]);
112                 do_unpowergate_locked(desc->powergate_ids[1]);
113         }
114         mod->powerstate = NVHOST_POWER_STATE_CLOCKGATED;
115 }
116
117 static void to_state_running_locked(struct nvhost_module *mod)
118 {
119         int prev_state = mod->powerstate;
120         if (mod->powerstate == NVHOST_POWER_STATE_POWERGATED)
121                 to_state_clockgated_locked(mod);
122         if (mod->powerstate == NVHOST_POWER_STATE_CLOCKGATED) {
123                 int i;
124
125                 if (mod->parent)
126                         nvhost_module_busy(mod->parent);
127
128                 for (i = 0; i < mod->num_clks; i++) {
129                         int err = clk_enable(mod->clk[i]);
130                         BUG_ON(err);
131                 }
132
133                 if (prev_state == NVHOST_POWER_STATE_POWERGATED
134                                 && mod->desc->finalize_poweron)
135                         mod->desc->finalize_poweron(mod);
136         }
137         mod->powerstate = NVHOST_POWER_STATE_RUNNING;
138 }
139
140 /* This gets called from powergate_handler() and from module suspend.
141  * Module suspend is done for all modules, runtime power gating only
142  * for modules with can_powergate set.
143  */
144 static int to_state_powergated_locked(struct nvhost_module *mod)
145 {
146         int err = 0;
147
148         if (mod->desc->prepare_poweroff
149                         && mod->powerstate != NVHOST_POWER_STATE_POWERGATED) {
150                 /* Clock needs to be on in prepare_poweroff */
151                 to_state_running_locked(mod);
152                 err = mod->desc->prepare_poweroff(mod);
153                 if (err)
154                         return err;
155         }
156
157         if (mod->powerstate == NVHOST_POWER_STATE_RUNNING)
158                 to_state_clockgated_locked(mod);
159
160         if (mod->desc->can_powergate) {
161                 do_powergate_locked(mod->desc->powergate_ids[0]);
162                 do_powergate_locked(mod->desc->powergate_ids[1]);
163         }
164
165         mod->powerstate = NVHOST_POWER_STATE_POWERGATED;
166         return 0;
167 }
168
169 static void schedule_powergating_locked(struct nvhost_module *mod)
170 {
171         if (mod->desc->can_powergate)
172                 schedule_delayed_work(&mod->powerstate_down,
173                                 msecs_to_jiffies(mod->desc->powergate_delay));
174 }
175
176 static void schedule_clockgating_locked(struct nvhost_module *mod)
177 {
178         schedule_delayed_work(&mod->powerstate_down,
179                         msecs_to_jiffies(mod->desc->clockgate_delay));
180 }
181
182 void nvhost_module_busy(struct nvhost_module *mod)
183 {
184         if (mod->desc->busy)
185                 mod->desc->busy(mod);
186
187         mutex_lock(&mod->lock);
188         cancel_delayed_work(&mod->powerstate_down);
189
190         mod->refcount++;
191         if (mod->refcount > 0 && !nvhost_module_powered(mod))
192                 to_state_running_locked(mod);
193         mutex_unlock(&mod->lock);
194 }
195
196 static void powerstate_down_handler(struct work_struct *work)
197 {
198         struct nvhost_module *mod;
199
200         mod = container_of(to_delayed_work(work),
201                         struct nvhost_module,
202                         powerstate_down);
203
204         mutex_lock(&mod->lock);
205         if (mod->refcount == 0) {
206                 switch (mod->powerstate) {
207                 case NVHOST_POWER_STATE_RUNNING:
208                         to_state_clockgated_locked(mod);
209                         schedule_powergating_locked(mod);
210                         break;
211                 case NVHOST_POWER_STATE_CLOCKGATED:
212                         if (to_state_powergated_locked(mod))
213                                 schedule_powergating_locked(mod);
214                         break;
215                 default:
216                         break;
217                 }
218         }
219         mutex_unlock(&mod->lock);
220 }
221
222
223 void nvhost_module_idle_mult(struct nvhost_module *mod, int refs)
224 {
225         bool kick = false;
226
227         mutex_lock(&mod->lock);
228         mod->refcount -= refs;
229         if (mod->refcount == 0) {
230                 if (nvhost_module_powered(mod))
231                         schedule_clockgating_locked(mod);
232                 kick = true;
233         }
234         mutex_unlock(&mod->lock);
235
236         if (kick) {
237                 wake_up(&mod->idle);
238
239                 if (mod->desc->idle)
240                         mod->desc->idle(mod);
241         }
242 }
243
244 int nvhost_module_get_rate(struct nvhost_master *host,
245                 struct nvhost_module *mod, unsigned long *rate,
246                 int index)
247 {
248         struct clk *c;
249
250         c = mod->clk[index];
251         if (IS_ERR_OR_NULL(c))
252                 return -EINVAL;
253
254         /* Need to enable client to get correct rate */
255         nvhost_module_busy(mod);
256         *rate = clk_get_rate(c);
257         nvhost_module_idle(mod);
258         return 0;
259
260 }
261
262 static int nvhost_module_update_rate(struct nvhost_module *mod, int index)
263 {
264         unsigned long rate = 0;
265         struct nvhost_module_client *m;
266
267         if (!mod->clk[index])
268                 return -EINVAL;
269
270         list_for_each_entry(m, &mod->client_list, node) {
271                 rate = max(m->rate[index], rate);
272         }
273         if (!rate)
274                 rate = clk_round_rate(mod->clk[index],
275                                 mod->desc->clocks[index].default_rate);
276
277         return clk_set_rate(mod->clk[index], rate);
278 }
279
280 int nvhost_module_set_rate(struct nvhost_master *host,
281                 struct nvhost_module *mod, void *priv,
282                 unsigned long rate, int index)
283 {
284         struct nvhost_module_client *m;
285         int ret;
286
287         mutex_lock(&client_list_lock);
288         list_for_each_entry(m, &mod->client_list, node) {
289                 if (m->priv == priv) {
290                         rate = clk_round_rate(mod->clk[index], rate);
291                         m->rate[index] = rate;
292                         break;
293                 }
294         }
295         ret = nvhost_module_update_rate(mod, index);
296         mutex_unlock(&client_list_lock);
297         return ret;
298
299 }
300
301 int nvhost_module_add_client(struct nvhost_master *host,
302                 struct nvhost_module *mod, void *priv)
303 {
304         int i;
305         unsigned long rate;
306         struct nvhost_module_client *client;
307
308         client = kzalloc(sizeof(*client), GFP_KERNEL);
309         if (!client)
310                 return -ENOMEM;
311
312         INIT_LIST_HEAD(&client->node);
313         client->priv = priv;
314
315         for (i = 0; i < mod->num_clks; i++) {
316                 rate = clk_round_rate(mod->clk[i],
317                                 mod->desc->clocks[i].default_rate);
318                 client->rate[i] = rate;
319         }
320         mutex_lock(&client_list_lock);
321         list_add_tail(&client->node, &mod->client_list);
322         mutex_unlock(&client_list_lock);
323         return 0;
324 }
325
326 void nvhost_module_remove_client(struct nvhost_master *host,
327                 struct nvhost_module *mod, void *priv)
328 {
329         int i;
330         struct nvhost_module_client *m;
331
332         mutex_lock(&client_list_lock);
333         list_for_each_entry(m, &mod->client_list, node) {
334                 if (priv == m->priv) {
335                         list_del(&m->node);
336                         break;
337                 }
338         }
339         if (m) {
340                 kfree(m);
341                 for (i = 0; i < mod->num_clks; i++)
342                         nvhost_module_update_rate(mod, i);
343         }
344         mutex_unlock(&client_list_lock);
345 }
346
347 void nvhost_module_preinit(const char *name,
348                 const struct nvhost_moduledesc *desc)
349 {
350         int i = 0;
351
352         /* initialize clocks to known state */
353         while (desc->clocks[i].name && i < NVHOST_MODULE_MAX_CLOCKS) {
354                 char devname[MAX_DEVID_LENGTH];
355                 long rate = desc->clocks[i].default_rate;
356                 struct clk *c;
357
358                 snprintf(devname, MAX_DEVID_LENGTH, "tegra_%s", name);
359                 c = clk_get_sys(devname, desc->clocks[i].name);
360                 BUG_ON(IS_ERR_OR_NULL(c));
361
362                 rate = clk_round_rate(c, rate);
363                 clk_enable(c);
364                 clk_set_rate(c, rate);
365                 clk_disable(c);
366                 i++;
367         }
368
369         if (desc->can_powergate) {
370                 do_powergate_locked(desc->powergate_ids[0]);
371                 do_powergate_locked(desc->powergate_ids[1]);
372         } else {
373                 do_unpowergate_locked(desc->powergate_ids[0]);
374                 do_unpowergate_locked(desc->powergate_ids[1]);
375         }
376 }
377
378 int nvhost_module_init(struct nvhost_module *mod, const char *name,
379                 const struct nvhost_moduledesc *desc,
380                 struct nvhost_module *parent,
381                 struct device *dev)
382 {
383         int i = 0;
384         int err;
385
386         /* register to kernel */
387         mod->drv.driver.name = name;
388         mod->drv.driver.owner = THIS_MODULE;
389         err = nvhost_driver_register(&mod->drv);
390         if (err)
391                 return err;
392
393         nvhost_module_preinit(name, desc);
394         mod->name = name;
395
396         INIT_LIST_HEAD(&mod->client_list);
397         while (desc->clocks[i].name && i < NVHOST_MODULE_MAX_CLOCKS) {
398                 char devname[MAX_DEVID_LENGTH];
399
400                 snprintf(devname, MAX_DEVID_LENGTH, "tegra_%s", name);
401                 mod->clk[i] = clk_get_sys(devname, desc->clocks[i].name);
402                 BUG_ON(IS_ERR_OR_NULL(mod->clk[i]));
403                 i++;
404         }
405         mod->num_clks = i;
406         mod->desc = desc;
407         mod->parent = parent;
408
409         mutex_init(&mod->lock);
410         init_waitqueue_head(&mod->idle);
411         INIT_DELAYED_WORK(&mod->powerstate_down, powerstate_down_handler);
412
413         if (desc->can_powergate) {
414                 mod->powerstate = NVHOST_POWER_STATE_POWERGATED;
415         } else {
416                 mod->powerstate = NVHOST_POWER_STATE_CLOCKGATED;
417         }
418
419         if (desc->init)
420                 desc->init(dev, mod);
421
422         return 0;
423 }
424
425 static int is_module_idle(struct nvhost_module *mod)
426 {
427         int count;
428         mutex_lock(&mod->lock);
429         count = mod->refcount;
430         mutex_unlock(&mod->lock);
431         return (count == 0);
432 }
433
434 static void debug_not_idle(struct nvhost_master *dev)
435 {
436         int i;
437         bool lock_released = true;
438
439         for (i = 0; i < dev->nb_channels; i++) {
440                 struct nvhost_module *mod = &dev->channels[i].mod;
441                 mutex_lock(&mod->lock);
442                 if (mod->name)
443                         dev_warn(&dev->pdev->dev,
444                                         "tegra_grhost: %s: refcnt %d\n",
445                                         mod->name, mod->refcount);
446                 mutex_unlock(&mod->lock);
447         }
448
449         for (i = 0; i < dev->nb_mlocks; i++) {
450                 int c = atomic_read(&dev->cpuaccess.lock_counts[i]);
451                 if (c) {
452                         dev_warn(&dev->pdev->dev,
453                                 "tegra_grhost: lock id %d: refcnt %d\n",
454                                 i, c);
455                         lock_released = false;
456                 }
457         }
458         if (lock_released)
459                 dev_dbg(&dev->pdev->dev, "tegra_grhost: all locks released\n");
460 }
461
462 int nvhost_module_suspend(struct nvhost_module *mod, bool system_suspend)
463 {
464         int ret;
465         struct nvhost_master *dev;
466
467         if (system_suspend) {
468                 dev = container_of(mod, struct nvhost_master, mod);
469                 if (!is_module_idle(mod))
470                         debug_not_idle(dev);
471         } else {
472                 dev = container_of(mod, struct nvhost_channel, mod)->dev;
473         }
474
475         ret = wait_event_timeout(mod->idle, is_module_idle(mod),
476                         ACM_SUSPEND_WAIT_FOR_IDLE_TIMEOUT);
477         if (ret == 0) {
478                 dev_info(&dev->pdev->dev, "%s prevented suspend\n", mod->name);
479                 return -EBUSY;
480         }
481
482         if (system_suspend)
483                 dev_dbg(&dev->pdev->dev, "tegra_grhost: entered idle\n");
484
485         mutex_lock(&mod->lock);
486         cancel_delayed_work(&mod->powerstate_down);
487         to_state_powergated_locked(mod);
488         mutex_unlock(&mod->lock);
489
490         if (mod->desc->suspend)
491                 mod->desc->suspend(mod);
492
493         return 0;
494 }
495
496 void nvhost_module_deinit(struct device *dev, struct nvhost_module *mod)
497 {
498         int i;
499
500         nvhost_driver_unregister(&mod->drv);
501
502         if (mod->desc->deinit)
503                 mod->desc->deinit(dev, mod);
504
505         nvhost_module_suspend(mod, false);
506         for (i = 0; i < mod->num_clks; i++)
507                 clk_put(mod->clk[i]);
508         mod->powerstate = NVHOST_POWER_STATE_DEINIT;
509 }
510