ARM: tegra: fix dolak_sim build
[linux-3.10.git] / arch / arm / mach-tegra / powergate.c
1 /*
2  * arch/arm/mach-tegra/powergate.c
3  *
4  * Copyright (c) 2010 Google, Inc
5  * Copyright (c) 2011 - 2013, NVIDIA CORPORATION.  All rights reserved.
6  *
7  * Author:
8  *      Colin Cross <ccross@google.com>
9  *
10  * This software is licensed under the terms of the GNU General Public
11  * License version 2, as published by the Free Software Foundation, and
12  * may be copied, distributed, and modified under those terms.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/clk.h>
24 #include <linux/string.h>
25 #include <linux/debugfs.h>
26 #include <linux/delay.h>
27 #include <linux/err.h>
28 #include <linux/init.h>
29 #include <linux/io.h>
30 #include <linux/seq_file.h>
31 #include <linux/spinlock.h>
32 #include <linux/clk/tegra.h>
33 #include <trace/events/power.h>
34 #include <asm/atomic.h>
35
36 #include <mach/powergate.h>
37
38 #include "clock.h"
39 #include "fuse.h"
40 #include "iomap.h"
41 #include "powergate-priv.h"
42
43 static struct powergate_ops *pg_ops;
44
45 #ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
46 static spinlock_t *tegra_get_powergate_lock(void)
47 {
48         if (pg_ops && pg_ops->get_powergate_lock)
49                 return pg_ops->get_powergate_lock();
50         else
51                 WARN_ON_ONCE("This SOC does not export powergate lock");
52
53         return NULL;
54 }
55 #endif
56
57 int tegra_powergate_set(int id, bool new_state)
58 {
59 #ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
60         bool status;
61         unsigned long flags;
62         spinlock_t *lock = tegra_get_powergate_lock();
63
64         /* 10us timeout for toggle operation if it takes affect*/
65         int toggle_timeout = 10;
66
67         /* 100 * 10 = 1000us timeout for toggle command to take affect in case
68            of contention with h/w initiated CPU power gating */
69         int contention_timeout = 100;
70
71         spin_lock_irqsave(lock, flags);
72
73         status = !!(pmc_read(PWRGATE_STATUS) & (1 << id));
74
75         if (status == new_state) {
76                 spin_unlock_irqrestore(lock, flags);
77                 return 0;
78         }
79
80         if (TEGRA_IS_CPU_POWERGATE_ID(id)) {
81                 /* CPU ungated in s/w only during boot/resume with outer
82                    waiting loop and no contention from other CPUs */
83                 pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
84                 spin_unlock_irqrestore(lock, flags);
85                 return 0;
86         }
87
88         pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
89         do {
90                 do {
91                         udelay(1);
92                         status = !!(pmc_read(PWRGATE_STATUS) & (1 << id));
93
94                         toggle_timeout--;
95                 } while ((status != new_state) && (toggle_timeout > 0));
96
97                 contention_timeout--;
98         } while ((status != new_state) && (contention_timeout > 0));
99
100         spin_unlock_irqrestore(lock, flags);
101
102         if (status != new_state) {
103                 WARN(1, "Could not set powergate %d to %d", id, new_state);
104                 return -EBUSY;
105         }
106
107         trace_power_domain_target(tegra_powergate_get_name(id), new_state,
108                         raw_smp_processor_id());
109 #endif
110
111         return 0;
112 }
113
114 int is_partition_clk_disabled(struct powergate_partition_info *pg_info)
115 {
116         u32 idx;
117         struct clk *clk;
118         struct partition_clk_info *clk_info;
119         int ret = 0;
120
121         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
122                 clk_info = &pg_info->clk_info[idx];
123                 clk = clk_info->clk_ptr;
124
125                 if (!clk)
126                         break;
127
128                 if (clk_info->clk_type != RST_ONLY) {
129                         if (tegra_is_clk_enabled(clk)) {
130                                 ret = -1;
131                                 break;
132                         }
133                 }
134         }
135
136         return ret;
137 }
138
139 int powergate_module(int id)
140 {
141         if (!pg_ops) {
142                 pr_info("This SOC doesn't support powergating\n");
143                 return -EINVAL;
144         }
145
146         if (id < 0 || id >= pg_ops->num_powerdomains)
147                 return -EINVAL;
148
149         tegra_powergate_mc_flush(id);
150
151         return tegra_powergate_set(id, false);
152 }
153
154 int unpowergate_module(int id)
155 {
156         if (!pg_ops) {
157                 pr_info("This SOC doesn't support powergating\n");
158                 return -EINVAL;
159         }
160
161         if (id < 0 || id >= pg_ops->num_powerdomains)
162                 return -EINVAL;
163
164         return tegra_powergate_set(id, true);
165 }
166
167 int partition_clk_enable(struct powergate_partition_info *pg_info)
168 {
169         int ret;
170         u32 idx;
171         struct clk *clk;
172         struct partition_clk_info *clk_info;
173
174         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
175                 clk_info = &pg_info->clk_info[idx];
176                 clk = clk_info->clk_ptr;
177                 if (!clk)
178                         break;
179
180                 if (clk_info->clk_type != RST_ONLY) {
181                         ret = tegra_clk_prepare_enable(clk);
182                         if (ret)
183                                 goto err_clk_en;
184                 }
185         }
186
187         return 0;
188
189 err_clk_en:
190         WARN(1, "Could not enable clk %s, error %d", clk->name, ret);
191         while (idx--) {
192                 clk_info = &pg_info->clk_info[idx];
193                 if (clk_info->clk_type != RST_ONLY)
194                         tegra_clk_disable_unprepare(clk_info->clk_ptr);
195         }
196
197         return ret;
198 }
199
200 void partition_clk_disable(struct powergate_partition_info *pg_info)
201 {
202         u32 idx;
203         struct clk *clk;
204         struct partition_clk_info *clk_info;
205
206         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
207                 clk_info = &pg_info->clk_info[idx];
208                 clk = clk_info->clk_ptr;
209
210                 if (!clk)
211                         break;
212
213                 if (clk_info->clk_type != RST_ONLY)
214                         tegra_clk_disable_unprepare(clk);
215         }
216 }
217
218 void get_clk_info(struct powergate_partition_info *pg_info)
219 {
220         int idx;
221
222         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
223                 if (!pg_info->clk_info[idx].clk_name)
224                         break;
225
226                 pg_info->clk_info[idx].clk_ptr = tegra_get_clock_by_name(
227                         pg_info->clk_info[idx].clk_name);
228         }
229 }
230
231 void powergate_partition_assert_reset(struct powergate_partition_info *pg_info)
232 {
233         u32 idx;
234         struct clk *clk_ptr;
235         struct partition_clk_info *clk_info;
236
237         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
238                 clk_info = &pg_info->clk_info[idx];
239                 clk_ptr = clk_info->clk_ptr;
240
241                 if (!clk_ptr)
242                         break;
243
244                 if (clk_info->clk_type != CLK_ONLY)
245                         tegra_periph_reset_assert(clk_ptr);
246         }
247 }
248
249 void powergate_partition_deassert_reset(struct powergate_partition_info *pg_info)
250 {
251         u32 idx;
252         struct clk *clk_ptr;
253         struct partition_clk_info *clk_info;
254
255         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
256                 clk_info = &pg_info->clk_info[idx];
257                 clk_ptr = clk_info->clk_ptr;
258
259                 if (!clk_ptr)
260                         break;
261
262                 if (clk_info->clk_type != CLK_ONLY)
263                         tegra_periph_reset_deassert(clk_ptr);
264         }
265 }
266
267 int tegra_powergate_reset_module(struct powergate_partition_info *pg_info)
268 {
269         int ret;
270
271         powergate_partition_assert_reset(pg_info);
272
273         udelay(10);
274
275         ret = partition_clk_enable(pg_info);
276         if (ret)
277                 return ret;
278
279         udelay(10);
280
281         powergate_partition_deassert_reset(pg_info);
282
283         partition_clk_disable(pg_info);
284
285         return 0;
286 }
287
288 int tegra_powergate_remove_clamping(int id)
289 {
290         u32 mask;
291         int contention_timeout = 100;
292
293         if (!pg_ops) {
294                 pr_info("This SOC doesn't support powergating\n");
295                 return -EINVAL;
296         }
297
298         if (id < 0 || id >= pg_ops->num_powerdomains)
299                 return -EINVAL;
300
301         /*
302          * PCIE and VDE clamping masks are swapped with respect to their
303          * partition ids
304          */
305         if (id ==  TEGRA_POWERGATE_VDEC)
306                 mask = (1 << TEGRA_POWERGATE_PCIE);
307         else if (id == TEGRA_POWERGATE_PCIE)
308                 mask = (1 << TEGRA_POWERGATE_VDEC);
309         else
310                 mask = (1 << id);
311
312         pmc_write(mask, REMOVE_CLAMPING);
313         /* Wait until clamp is removed */
314         do {
315                 udelay(1);
316                 contention_timeout--;
317         } while ((contention_timeout > 0)
318                         && (pmc_read(REMOVE_CLAMPING) & mask));
319
320         WARN(contention_timeout <= 0, "Couldn't remove clamping");
321
322         return 0;
323 }
324
325 /* EXTERNALY VISIBLE APIS */
326
327 bool tegra_powergate_is_powered(int id)
328 {
329         u32 status;
330
331         if (!pg_ops) {
332                 pr_info("This SOC doesn't support powergating\n");
333                 return -EINVAL;
334         }
335
336         if (id < 0 || id >= pg_ops->num_powerdomains)
337                 return -EINVAL;
338
339         status = pmc_read(PWRGATE_STATUS) & (1 << id);
340
341         return !!status;
342 }
343 EXPORT_SYMBOL(tegra_powergate_is_powered);
344
345 int tegra_cpu_powergate_id(int cpuid)
346 {
347         if (!pg_ops) {
348                 pr_info("This SOC doesn't support powergating\n");
349                 return -EINVAL;
350         }
351
352         if (cpuid < 0 || cpuid >= pg_ops->num_cpu_domains) {
353                 pr_info("%s: invalid powergate id\n", __func__);
354                 return -EINVAL;
355         }
356
357         if (pg_ops->cpu_domains)
358                 return pg_ops->cpu_domains[cpuid];
359         else
360                 WARN_ON_ONCE("This SOC does not support CPU powergate\n");
361
362         return -EINVAL;
363 }
364 EXPORT_SYMBOL(tegra_cpu_powergate_id);
365
366 int tegra_powergate_partition(int id)
367 {
368         if (!pg_ops) {
369                 pr_info("This SOC doesn't support powergating\n");
370                 return -EINVAL;
371         }
372
373         if (id < 0 || id >= pg_ops->num_powerdomains) {
374                 pr_info("%s: invalid powergate id\n", __func__);
375                 return -EINVAL;
376         }
377
378         if (pg_ops->powergate_partition)
379                 return pg_ops->powergate_partition(id);
380         else
381                 WARN_ON_ONCE("This SOC doesn't support powergating");
382
383         return -EINVAL;
384 }
385 EXPORT_SYMBOL(tegra_powergate_partition);
386
387 int tegra_unpowergate_partition(int id)
388 {
389         if (!pg_ops) {
390                 pr_info("This SOC doesn't support powergating\n");
391                 return -EINVAL;
392         }
393
394         if (id < 0 || id >= pg_ops->num_powerdomains) {
395                 pr_info("%s: invalid powergate id\n", __func__);
396                 return -EINVAL;
397         }
398
399         if (pg_ops->unpowergate_partition)
400                 return pg_ops->unpowergate_partition(id);
401         else
402                 WARN_ON_ONCE("This SOC doesn't support un-powergating");
403
404         return -EINVAL;
405 }
406 EXPORT_SYMBOL(tegra_unpowergate_partition);
407
408 int tegra_powergate_partition_with_clk_off(int id)
409 {
410         if (!pg_ops) {
411                 pr_info("This SOC doesn't support powergating\n");
412                 return -EINVAL;
413         }
414
415         if (id < 0 || id >= pg_ops->num_powerdomains) {
416                 pr_info("%s: invalid powergate id\n", __func__);
417                 return -EINVAL;
418         }
419
420         if (pg_ops->powergate_partition_with_clk_off)
421                 return pg_ops->powergate_partition_with_clk_off(id);
422         else
423                 WARN_ON_ONCE("This SOC doesn't support powergating with clk off");
424
425         return -EINVAL;
426 }
427 EXPORT_SYMBOL(tegra_powergate_partition_with_clk_off);
428
429 int tegra_unpowergate_partition_with_clk_on(int id)
430 {
431         if (!pg_ops) {
432                 pr_info("This SOC doesn't support powergating\n");
433                 return -EINVAL;
434         }
435
436         if (id < 0 || id >= pg_ops->num_powerdomains) {
437                 pr_info("%s: invalid powergate id\n", __func__);
438                 return -EINVAL;
439         }
440
441         if (pg_ops->unpowergate_partition_with_clk_on)
442                 return pg_ops->unpowergate_partition_with_clk_on(id);
443         else
444                 WARN_ON_ONCE("This SOC doesn't support power un-gating with clk on");
445
446         return -EINVAL;
447 }
448 EXPORT_SYMBOL(tegra_unpowergate_partition_with_clk_on);
449
450 int tegra_powergate_mc_enable(int id)
451 {
452         if (!pg_ops) {
453                 pr_info("This SOC doesn't support powergating\n");
454                 return -EINVAL;
455         }
456
457         if (id < 0 || id >= pg_ops->num_powerdomains) {
458                 pr_info("%s: invalid powergate id\n", __func__);
459                 return -EINVAL;
460         }
461
462         if (pg_ops->powergate_mc_enable)
463                 return pg_ops->powergate_mc_enable(id);
464         else
465                 WARN_ON_ONCE("This SOC does not support powergate mc enable");
466
467         return -EINVAL;
468 }
469 EXPORT_SYMBOL(tegra_powergate_mc_enable);
470
471 int tegra_powergate_mc_disable(int id)
472 {
473         if (!pg_ops) {
474                 pr_info("This SOC doesn't support powergating\n");
475                 return -EINVAL;
476         }
477
478         if (id < 0 || id >= pg_ops->num_powerdomains) {
479                 pr_info("%s: invalid powergate id\n", __func__);
480                 return -EINVAL;
481         }
482
483         if (pg_ops->powergate_mc_disable)
484                 return pg_ops->powergate_mc_disable(id);
485         else
486                 WARN_ON_ONCE("This SOC does not support powergate mc disable");
487
488         return -EINVAL;
489 }
490 EXPORT_SYMBOL(tegra_powergate_mc_disable);
491
492 int tegra_powergate_mc_flush(int id)
493 {
494         if (!pg_ops) {
495                 pr_info("This SOC doesn't support powergating\n");
496                 return -EINVAL;
497         }
498
499         if (id < 0 || id >= pg_ops->num_powerdomains) {
500                 pr_info("%s: invalid powergate id\n", __func__);
501                 return -EINVAL;
502         }
503
504         if (pg_ops->powergate_mc_flush)
505                 return pg_ops->powergate_mc_flush(id);
506         else
507                 WARN_ON_ONCE("This SOC does not support powergate mc flush");
508
509         return -EINVAL;
510 }
511 EXPORT_SYMBOL(tegra_powergate_mc_flush);
512
513 int tegra_powergate_mc_flush_done(int id)
514 {
515         if (!pg_ops) {
516                 pr_info("This SOC doesn't support powergating\n");
517                 return -EINVAL;
518         }
519
520         if (id < 0 || id >= pg_ops->num_powerdomains) {
521                 pr_info("%s: invalid powergate id\n", __func__);
522                 return -EINVAL;
523         }
524
525         if (pg_ops->powergate_mc_flush_done)
526                 return pg_ops->powergate_mc_flush_done(id);
527         else
528                 WARN_ON_ONCE("This SOC does not support powergate mc flush done");
529
530         return -EINVAL;
531 }
532 EXPORT_SYMBOL(tegra_powergate_mc_flush_done);
533
534 const char *tegra_powergate_get_name(int id)
535 {
536         if (!pg_ops) {
537                 pr_info("This SOC doesn't support powergating\n");
538                 return NULL;
539         }
540
541         if (id < 0 || id >= pg_ops->num_powerdomains) {
542                 pr_info("invalid powergate id\n");
543                 return "invalid";
544         }
545
546         if (pg_ops->get_powergate_domain_name)
547                 return pg_ops->get_powergate_domain_name(id);
548         else
549                 WARN_ON_ONCE("This SOC does not support CPU powergate");
550
551         return "invalid";
552 }
553 EXPORT_SYMBOL(tegra_powergate_get_name);
554
555 int __init tegra_powergate_init(void)
556 {
557         switch (tegra_chip_id) {
558                 case TEGRA20:
559                         pg_ops = tegra2_powergate_init_chip_support();
560                         break;
561
562                 case TEGRA30:
563                         pg_ops = tegra3_powergate_init_chip_support();
564                         break;
565
566                 case TEGRA11X:
567                         pg_ops = tegra11x_powergate_init_chip_support();
568                         break;
569
570                 case TEGRA14X:
571                         pg_ops = tegra14x_powergate_init_chip_support();
572                         break;
573
574                 default:
575                         pg_ops = NULL;
576                         pr_info("%s: Unknown Tegra variant. Disabling powergate\n", __func__);
577                         break;
578         }
579
580         pr_info("%s: DONE\n", __func__);
581
582         return (pg_ops ? 0 : -EINVAL);
583 }
584
585 #ifdef CONFIG_DEBUG_FS
586
587 static int powergate_show(struct seq_file *s, void *data)
588 {
589         int i;
590         const char *name;
591
592         if (!pg_ops) {
593                 seq_printf(s, "This SOC doesn't support powergating\n");
594                 return -EINVAL;
595         }
596
597         seq_printf(s, " powergate powered\n");
598         seq_printf(s, "------------------\n");
599
600         for (i = 0; i < pg_ops->num_powerdomains; i++) {
601                 name = tegra_powergate_get_name(i);
602                 if (name)
603                         seq_printf(s, " %9s %7s\n", name,
604                                 tegra_powergate_is_powered(i) ? "yes" : "no");
605         }
606
607         return 0;
608 }
609
610 static int powergate_open(struct inode *inode, struct file *file)
611 {
612         return single_open(file, powergate_show, inode->i_private);
613 }
614
615 static const struct file_operations powergate_fops = {
616         .open           = powergate_open,
617         .read           = seq_read,
618         .llseek         = seq_lseek,
619         .release        = single_release,
620 };
621
622 int __init tegra_powergate_debugfs_init(void)
623 {
624         struct dentry *d;
625
626         d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
627                 &powergate_fops);
628         if (!d)
629                 return -ENOMEM;
630
631         return 0;
632 }
633
634 #endif