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