ARM: tegra: power gate disable
[linux-3.10.git] / arch / arm / mach-tegra / powergate.c
1 /*
2  * drivers/powergate/tegra-powergate.c
3  *
4  * Copyright (c) 2010 Google, Inc
5  * Copyright (C) 2011-2012 NVIDIA Corporation.
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
35 #include <mach/powergate.h>
36
37 #include "clock.h"
38 #include "fuse.h"
39 #include "iomap.h"
40
41 #if defined(DEBUG_T11x_POWERGATE)
42 static void test_powergate_parts(void);
43 #endif
44 #if defined(DEBUG_T11x_POWERUNGATE)
45 static void test_powerungate_parts(void);
46 #endif
47 #if defined(DEBUG_T11x_POWERGATE_CLK_OFF)
48 static void test_powergate_clk_off_parts(void);
49 #endif
50 #if defined(DEBUG_T11x_POWERUNGATE_CLK_OFF)
51 static void test_unpowergate_clk_on_parts(void);
52 #endif
53
54 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
55 static int tegra11x_check_partition_pug_seq(int id);
56 #endif
57
58 #define PWRGATE_TOGGLE          0x30
59 #define PWRGATE_TOGGLE_START    (1 << 8)
60
61 #define REMOVE_CLAMPING         0x34
62
63 #define PWRGATE_STATUS          0x38
64
65 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
66 enum mc_client {
67         MC_CLIENT_AFI           = 0,
68         MC_CLIENT_AVPC          = 1,
69         MC_CLIENT_DC            = 2,
70         MC_CLIENT_DCB           = 3,
71         MC_CLIENT_EPP           = 4,
72         MC_CLIENT_G2            = 5,
73         MC_CLIENT_HC            = 6,
74         MC_CLIENT_HDA           = 7,
75         MC_CLIENT_ISP           = 8,
76         MC_CLIENT_MPCORE        = 9,
77         MC_CLIENT_MPCORELP      = 10,
78         MC_CLIENT_MPE           = 11,
79         MC_CLIENT_NV            = 12,
80         MC_CLIENT_NV2           = 13,
81         MC_CLIENT_PPCS          = 14,
82         MC_CLIENT_SATA          = 15,
83         MC_CLIENT_VDE           = 16,
84         MC_CLIENT_VI            = 17,
85         MC_CLIENT_LAST          = -1,
86 };
87 #elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
88 enum mc_client {
89         MC_CLIENT_AVPC          = 0,
90         MC_CLIENT_DC            = 1,
91         MC_CLIENT_DCB           = 2,
92         MC_CLIENT_EPP           = 3,
93         MC_CLIENT_G2            = 4,
94         MC_CLIENT_HC            = 5,
95         MC_CLIENT_ISP           = 6,
96         MC_CLIENT_MPCORE        = 7,
97         MC_CLIENT_MPEA          = 8,
98         MC_CLIENT_MPEB          = 9,
99         MC_CLIENT_MPEC          = 10,
100         MC_CLIENT_NV            = 11,
101         MC_CLIENT_PPCS          = 12,
102         MC_CLIENT_VDE           = 13,
103         MC_CLIENT_VI            = 14,
104         MC_CLIENT_LAST          = -1,
105         MC_CLIENT_AFI           = MC_CLIENT_LAST,
106 };
107 #else
108 /* bit positions are specific to chip */
109 enum mc_client {
110         MC_CLIENT_AVPC          = 1,
111         MC_CLIENT_DC            = 2,
112         MC_CLIENT_DCB           = 3,
113         MC_CLIENT_EPP           = 4,
114         MC_CLIENT_G2            = 5,
115         MC_CLIENT_HC            = 6,
116         MC_CLIENT_HDA           = 7,
117         MC_CLIENT_ISP           = 8,
118         MC_CLIENT_MPCORE        = 9,
119         MC_CLIENT_MPCORELP      = 10,
120         MC_CLIENT_MSENC         = 11,
121         MC_CLIENT_NV            = 12,
122         MC_CLIENT_PPCS          = 14,
123         MC_CLIENT_VDE           = 16,
124         MC_CLIENT_VI            = 17,
125         MC_CLIENT_XUSB_HOST     = 19,
126         MC_CLIENT_XUSB_DEV      = 20,
127         MC_CLIENT_EMUCIF        = 21,
128         MC_CLIENT_TSEC          = 22,
129         MC_CLIENT_LAST          = -1,
130         MC_CLIENT_AFI           = MC_CLIENT_LAST,
131         MC_CLIENT_MPE           = MC_CLIENT_LAST,
132         MC_CLIENT_NV2           = MC_CLIENT_LAST,
133         MC_CLIENT_SATA          = MC_CLIENT_LAST,
134 };
135 #endif
136
137 #define MAX_CLK_EN_NUM                  9
138
139 static int tegra_num_powerdomains;
140 static int tegra_num_cpu_domains;
141 static u8 *tegra_cpu_domains;
142 static u8 tegra_quad_cpu_domains[] = {
143         TEGRA_POWERGATE_CPU0,
144         TEGRA_POWERGATE_CPU1,
145         TEGRA_POWERGATE_CPU2,
146         TEGRA_POWERGATE_CPU3,
147 };
148
149 static DEFINE_SPINLOCK(tegra_powergate_lock);
150
151 #define MAX_HOTRESET_CLIENT_NUM         4
152
153 enum clk_type {
154         CLK_AND_RST,
155         RST_ONLY,
156         CLK_ONLY,
157 };
158
159 struct partition_clk_info {
160         const char *clk_name;
161         enum clk_type clk_type;
162         /* true if clk is only used in assert/deassert reset and not while enable-den*/
163         struct clk *clk_ptr;
164 };
165
166 struct powergate_partition {
167         const char *name;
168         enum mc_client hot_reset_clients[MAX_HOTRESET_CLIENT_NUM];
169         struct partition_clk_info clk_info[MAX_CLK_EN_NUM];
170 };
171
172 static struct powergate_partition powergate_partition_info[TEGRA_NUM_POWERGATE] = {
173         [TEGRA_POWERGATE_CPU]   = { "cpu0",     {MC_CLIENT_LAST}, },
174         [TEGRA_POWERGATE_L2]    = { "l2",       {MC_CLIENT_LAST}, },
175 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
176         [TEGRA_POWERGATE_3D]    = { "3d0",
177 #else
178         [TEGRA_POWERGATE_3D]    = { "3d",
179 #endif
180                                                 {MC_CLIENT_NV, MC_CLIENT_LAST},
181                                                 {{"3d", CLK_AND_RST} }, },
182 /* T11x does not have pcie */
183 #if !defined(CONFIG_ARCH_TEGRA_11x_SOC)
184 #ifdef CONFIG_ARCH_TEGRA_HAS_PCIE
185         [TEGRA_POWERGATE_PCIE]  = { "pcie",
186                                                 {MC_CLIENT_AFI, MC_CLIENT_LAST},
187                                                 {{"afi", CLK_AND_RST},
188                                                 {"pcie", CLK_AND_RST},
189 #ifndef CONFIG_ARCH_TEGRA_2x_SOC
190                                                 {"cml0", CLK_ONLY},
191 #endif
192                                                 {"pciex", RST_ONLY} }, },
193 #endif
194 #endif
195         [TEGRA_POWERGATE_VDEC]  = { "vde",
196                                                 {MC_CLIENT_VDE, MC_CLIENT_LAST},
197                                                 {{"vde", CLK_AND_RST} }, },
198         [TEGRA_POWERGATE_MPE]   = { "mpe",
199 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
200                                         {
201                                                 MC_CLIENT_MPE,
202                                                 MC_CLIENT_LAST
203                                         },
204 #elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
205                                                 {MC_CLIENT_MPEA, MC_CLIENT_MPEB,
206                                                  MC_CLIENT_MPEC, MC_CLIENT_LAST},
207 #else
208                                         {
209                                                 MC_CLIENT_MSENC,
210                                                 MC_CLIENT_LAST
211                                         },
212 #endif
213 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
214                                         {
215                                                 {"mpe", CLK_AND_RST}
216                                         },
217 #else
218                                         {
219                                                 {"msenc", CLK_AND_RST}
220                                         },
221 #endif
222                                 },
223         [TEGRA_POWERGATE_VENC]  = { "ve",
224                                         {
225                                                 MC_CLIENT_ISP,
226                                                 MC_CLIENT_VI,
227                                                 MC_CLIENT_LAST
228                                         },
229                                         {
230                                                 {"isp", CLK_AND_RST},
231                                                 {"vi", CLK_AND_RST},
232                                                 {"csi", CLK_AND_RST}
233                                         },
234                                 },
235 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
236         [TEGRA_POWERGATE_CPU1]  = { "cpu1",     {MC_CLIENT_LAST}, },
237         [TEGRA_POWERGATE_CPU2]  = { "cpu2",     {MC_CLIENT_LAST}, },
238         [TEGRA_POWERGATE_CPU3]  = { "cpu3",     {MC_CLIENT_LAST}, },
239         [TEGRA_POWERGATE_CELP]  = { "celp",     {MC_CLIENT_LAST}, },
240 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
241 #ifdef CONFIG_ARCH_TEGRA_HAS_SATA
242         [TEGRA_POWERGATE_SATA]  = { "sata",     {MC_CLIENT_SATA, MC_CLIENT_LAST},
243                                                 {{"sata", CLK_AND_RST},
244                                                 {"sata_oob", CLK_AND_RST},
245                                                 {"cml1", CLK_ONLY},
246                                                 {"sata_cold", RST_ONLY} }, },
247 #endif
248 #ifdef CONFIG_ARCH_TEGRA_HAS_DUAL_3D
249         [TEGRA_POWERGATE_3D1]   = { "3d1",
250                                                 {MC_CLIENT_NV2, MC_CLIENT_LAST},
251                                                 {{"3d2", CLK_AND_RST} }, },
252 #endif
253 #endif
254         [TEGRA_POWERGATE_HEG]   = { "heg",
255                                         {
256                                                 MC_CLIENT_G2,
257                                                 MC_CLIENT_EPP,
258 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
259                                                 MC_CLIENT_HC,
260 #endif
261                                                 MC_CLIENT_LAST
262                                         },
263                                         {
264                                                 {"2d", CLK_AND_RST},
265                                                 {"epp", CLK_AND_RST},
266 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
267                                                 {"host1x", CLK_AND_RST},
268                                                 {"3d", RST_ONLY}
269 #endif
270                                         },
271                                 },
272 #endif
273 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
274         [TEGRA_POWERGATE_CRAIL] = { "crail",    {MC_CLIENT_LAST}, },
275         [TEGRA_POWERGATE_C0NC]  = { "c0nc",     {MC_CLIENT_LAST}, },
276         [TEGRA_POWERGATE_C1NC]  = { "c1nc",     {MC_CLIENT_LAST}, },
277         [TEGRA_POWERGATE_DISA]  = { "disa",
278                                         {
279                                                 MC_CLIENT_DC,
280                                                 MC_CLIENT_LAST
281                                         },
282                                         {
283                                                 {"disp1", CLK_AND_RST},
284                                                 {"dsia", CLK_AND_RST},
285                                                 {"dsib", CLK_AND_RST},
286                                                 {"csi", CLK_AND_RST},
287                                                 {"mipi-cal", CLK_AND_RST}
288                                         },
289                                 },
290         [TEGRA_POWERGATE_DISB]  = { "disb",
291                                         {
292                                                 MC_CLIENT_DCB,
293                                                 MC_CLIENT_LAST
294                                         },
295                                         {
296                                                 {"disp2", CLK_AND_RST},
297                                                 {"hdmi", CLK_AND_RST}
298                                         },
299                                 },
300         [TEGRA_POWERGATE_XUSBA] = { "xusba",
301                                         { MC_CLIENT_LAST },
302                                         {
303                                                 {"xusb_ss", CLK_AND_RST}
304                                         },
305                                 },
306         [TEGRA_POWERGATE_XUSBB] = { "xusbb",
307                                         {
308                                                 MC_CLIENT_XUSB_DEV,
309                                                 MC_CLIENT_LAST
310                                         },
311                                         {
312                                                 {"xusb_dev", CLK_AND_RST},
313                                         },
314                                 },
315         [TEGRA_POWERGATE_XUSBC] = { "xusbc",
316                                         {
317                                                 MC_CLIENT_XUSB_HOST,
318                                                 MC_CLIENT_LAST
319                                         },
320                                         {
321                                                 {"xusb_host", CLK_AND_RST},
322                                         },
323                                 },
324 #endif
325
326 };
327
328 static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
329
330 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
331 static void __iomem *mipi_cal = IO_ADDRESS(TEGRA_MIPI_CAL_BASE);
332
333 static u32 mipi_cal_read(unsigned long reg)
334 {
335         return readl(mipi_cal + reg);
336 }
337
338 static void mipi_cal_write(u32 val, unsigned long reg)
339 {
340         writel(val, mipi_cal + reg);
341 }
342
343 static void __iomem *clk_rst = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
344
345 static u32 clk_rst_read(unsigned long reg)
346 {
347         return readl(clk_rst + reg);
348 }
349 #endif
350
351 static u32 pmc_read(unsigned long reg)
352 {
353         return readl(pmc + reg);
354 }
355
356 static void pmc_write(u32 val, unsigned long reg)
357 {
358         writel(val, pmc + reg);
359 }
360
361 static void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE);
362
363 static u32 mc_read(unsigned long reg)
364 {
365         return readl(mc + reg);
366 }
367
368 static void mc_write(u32 val, unsigned long reg)
369 {
370         writel(val, mc + reg);
371 }
372
373 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && \
374         !defined(CONFIG_TEGRA_SIMULATION_PLATFORM)
375
376 #define MC_CLIENT_HOTRESET_CTRL 0x200
377 #define MC_CLIENT_HOTRESET_STAT 0x204
378
379 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && \
380         !defined(CONFIG_ARCH_TEGRA_3x_SOC)
381 /* FIXME: this is sw workaround for unstable hotreset status
382  * for T11x.
383  */
384 #define HOTRESET_READ_COUNT 5
385 static bool tegra11x_stable_hotreset_check(u32 *stat)
386 {
387         int i;
388         u32 cur_stat;
389         u32 prv_stat;
390         unsigned long flags;
391
392         spin_lock_irqsave(&tegra_powergate_lock, flags);
393         prv_stat = mc_read(MC_CLIENT_HOTRESET_STAT);
394         for (i = 0; i < HOTRESET_READ_COUNT; i++) {
395                 cur_stat = mc_read(MC_CLIENT_HOTRESET_STAT);
396                 if (cur_stat != prv_stat) {
397                         spin_unlock_irqrestore(&tegra_powergate_lock, flags);
398                         return false;
399                 }
400         }
401         *stat = cur_stat;
402         spin_unlock_irqrestore(&tegra_powergate_lock, flags);
403         return true;
404 }
405 #endif
406
407 static void mc_flush(int id)
408 {
409         u32 idx, rst_ctrl, rst_stat;
410         enum mc_client mcClientBit;
411         unsigned long flags;
412 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && \
413         !defined(CONFIG_ARCH_TEGRA_3x_SOC)
414         bool ret;
415 #endif
416
417         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
418
419         for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
420                 mcClientBit =
421                         powergate_partition_info[id].hot_reset_clients[idx];
422                 if (mcClientBit == MC_CLIENT_LAST)
423                         break;
424
425                 spin_lock_irqsave(&tegra_powergate_lock, flags);
426                 rst_ctrl = mc_read(MC_CLIENT_HOTRESET_CTRL);
427                 rst_ctrl |= (1 << mcClientBit);
428                 mc_write(rst_ctrl, MC_CLIENT_HOTRESET_CTRL);
429
430                 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
431
432                 do {
433                         udelay(10);
434 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
435                         rst_stat = mc_read(MC_CLIENT_HOTRESET_STAT);
436 #else
437                         rst_stat = 0;
438                         ret = tegra11x_stable_hotreset_check(&rst_stat);
439                         if (!ret)
440                                 continue;
441 #endif
442                 } while (!(rst_stat & (1 << mcClientBit)));
443         }
444 }
445
446 static void mc_flush_done(int id)
447 {
448         u32 idx, rst_ctrl;
449         enum mc_client mcClientBit;
450         unsigned long flags;
451
452         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
453
454         for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
455                 mcClientBit =
456                         powergate_partition_info[id].hot_reset_clients[idx];
457                 if (mcClientBit == MC_CLIENT_LAST)
458                         break;
459
460                 spin_lock_irqsave(&tegra_powergate_lock, flags);
461
462                 rst_ctrl = mc_read(MC_CLIENT_HOTRESET_CTRL);
463                 rst_ctrl &= ~(1 << mcClientBit);
464                 mc_write(rst_ctrl, MC_CLIENT_HOTRESET_CTRL);
465
466                 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
467         }
468
469         wmb();
470 }
471
472 int tegra_powergate_mc_flush(int id)
473 {
474         if (id < 0 || id >= TEGRA_NUM_POWERGATE)
475                 return -EINVAL;
476         mc_flush(id);
477         return 0;
478 }
479
480 int tegra_powergate_mc_flush_done(int id)
481 {
482         if (id < 0 || id >= TEGRA_NUM_POWERGATE)
483                 return -EINVAL;
484         mc_flush_done(id);
485         return 0;
486 }
487
488 int tegra_powergate_mc_disable(int id)
489 {
490         return 0;
491 }
492
493 int tegra_powergate_mc_enable(int id)
494 {
495         return 0;
496 }
497
498 #else
499
500 #define MC_CLIENT_CTRL          0x100
501 #define MC_CLIENT_HOTRESETN     0x104
502 #define MC_CLIENT_ORRC_BASE     0x140
503
504 int tegra_powergate_mc_disable(int id)
505 {
506         u32 idx, clt_ctrl, orrc_reg;
507         enum mc_client mcClientBit;
508         unsigned long flags;
509
510         if (id < 0 || id >= TEGRA_NUM_POWERGATE) {
511                 WARN_ON(1);
512                 return -EINVAL;
513         }
514
515         for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
516                 mcClientBit =
517                         powergate_partition_info[id].hot_reset_clients[idx];
518                 if (mcClientBit == MC_CLIENT_LAST)
519                         break;
520
521                 spin_lock_irqsave(&tegra_powergate_lock, flags);
522
523                 /* clear client enable bit */
524                 clt_ctrl = mc_read(MC_CLIENT_CTRL);
525                 clt_ctrl &= ~(1 << mcClientBit);
526                 mc_write(clt_ctrl, MC_CLIENT_CTRL);
527
528                 /* read back to flush write */
529                 clt_ctrl = mc_read(MC_CLIENT_CTRL);
530
531                 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
532
533                 /* wait for outstanding requests to reach 0 */
534                 orrc_reg = MC_CLIENT_ORRC_BASE + (mcClientBit * 4);
535                 while (mc_read(orrc_reg) != 0)
536                         udelay(10);
537         }
538         return 0;
539 }
540
541 int tegra_powergate_mc_flush(int id)
542 {
543         u32 idx, hot_rstn;
544         enum mc_client mcClientBit;
545         unsigned long flags;
546
547         if (id < 0 || id >= TEGRA_NUM_POWERGATE) {
548                 WARN_ON(1);
549                 return -EINVAL;
550         }
551
552         for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
553                 mcClientBit =
554                         powergate_partition_info[id].hot_reset_clients[idx];
555                 if (mcClientBit == MC_CLIENT_LAST)
556                         break;
557
558                 spin_lock_irqsave(&tegra_powergate_lock, flags);
559
560                 /* assert hotreset (client module is currently in reset) */
561                 hot_rstn = mc_read(MC_CLIENT_HOTRESETN);
562                 hot_rstn &= ~(1 << mcClientBit);
563                 mc_write(hot_rstn, MC_CLIENT_HOTRESETN);
564
565                 /* read back to flush write */
566                 hot_rstn = mc_read(MC_CLIENT_HOTRESETN);
567
568                 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
569         }
570         return 0;
571 }
572
573 int tegra_powergate_mc_flush_done(int id)
574 {
575         u32 idx, hot_rstn;
576         enum mc_client mcClientBit;
577         unsigned long flags;
578
579         if (id < 0 || id >= TEGRA_NUM_POWERGATE) {
580                 WARN_ON(1);
581                 return -EINVAL;
582         }
583
584         for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
585                 mcClientBit =
586                         powergate_partition_info[id].hot_reset_clients[idx];
587                 if (mcClientBit == MC_CLIENT_LAST)
588                         break;
589
590                 spin_lock_irqsave(&tegra_powergate_lock, flags);
591
592                 /* deassert hotreset */
593                 hot_rstn = mc_read(MC_CLIENT_HOTRESETN);
594                 hot_rstn |= (1 << mcClientBit);
595                 mc_write(hot_rstn, MC_CLIENT_HOTRESETN);
596
597                 /* read back to flush write */
598                 hot_rstn = mc_read(MC_CLIENT_HOTRESETN);
599
600                 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
601         }
602         return 0;
603 }
604
605 int tegra_powergate_mc_enable(int id)
606 {
607         u32 idx, clt_ctrl;
608         enum mc_client mcClientBit;
609         unsigned long flags;
610
611         if (id < 0 || id >= TEGRA_NUM_POWERGATE) {
612                 WARN_ON(1);
613                 return -EINVAL;
614         }
615
616         for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
617                 mcClientBit =
618                         powergate_partition_info[id].hot_reset_clients[idx];
619                 if (mcClientBit == MC_CLIENT_LAST)
620                         break;
621
622                 spin_lock_irqsave(&tegra_powergate_lock, flags);
623
624                 /* enable client */
625                 clt_ctrl = mc_read(MC_CLIENT_CTRL);
626                 clt_ctrl |= (1 << mcClientBit);
627                 mc_write(clt_ctrl, MC_CLIENT_CTRL);
628
629                 /* read back to flush write */
630                 clt_ctrl = mc_read(MC_CLIENT_CTRL);
631
632                 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
633         }
634         return 0;
635 }
636
637 static void mc_flush(int id) {}
638 static void mc_flush_done(int id) {}
639 #endif
640
641 static int tegra_powergate_set(int id, bool new_state)
642 {
643 #ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
644         bool status;
645         unsigned long flags;
646         /* 10us timeout for toggle operation if it takes affect*/
647         int toggle_timeout = 10;
648         /* 100 * 10 = 1000us timeout for toggle command to take affect in case
649            of contention with h/w initiated CPU power gating */
650         int contention_timeout = 100;
651
652         spin_lock_irqsave(&tegra_powergate_lock, flags);
653
654         status = !!(pmc_read(PWRGATE_STATUS) & (1 << id));
655
656         if (status == new_state) {
657                 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
658                 return 0;
659         }
660
661         if (TEGRA_IS_CPU_POWERGATE_ID(id)) {
662                 /* CPU ungated in s/w only during boot/resume with outer
663                    waiting loop and no contention from other CPUs */
664                 pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
665                 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
666                 return 0;
667         }
668
669         do {
670                 pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
671                 do {
672                         udelay(1);
673                         status = !!(pmc_read(PWRGATE_STATUS) & (1 << id));
674
675                         toggle_timeout--;
676                 } while ((status != new_state) && (toggle_timeout > 0));
677
678                 contention_timeout--;
679         } while ((status != new_state) && (contention_timeout > 0));
680
681         spin_unlock_irqrestore(&tegra_powergate_lock, flags);
682
683         if (status != new_state) {
684                 WARN(1, "Could not set powergate %d to %d", id, new_state);
685                 return -EBUSY;
686         }
687
688         trace_power_domain_target(powergate_partition_info[id].name, new_state,
689                         smp_processor_id());
690 #endif
691
692         return 0;
693 }
694
695 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
696 static bool tegra11x_check_plld_plld2_disable(void)
697 {
698         /* FIXME:
699          * add check for plld and plld2 disable
700          */
701 #define CLK_RST_CONTROLLER_PLLD_BASE_0 0xd0
702 #define CLK_RST_CONTROLLER_PLLD_BASE_0_PLLD_ENABLE_LSB 30
703 #define CLK_RST_CONTROLLER_PLLD2_BASE_0 0x4b8
704 #define CLK_RST_CONTROLLER_PLLD2_BASE_0_PLLD2_ENABLE_LSB 30
705         u32 status;
706         status = clk_rst_read(CLK_RST_CONTROLLER_PLLD_BASE_0);
707         if (status & (1 << CLK_RST_CONTROLLER_PLLD_BASE_0_PLLD_ENABLE_LSB))
708                 return false;
709         status = clk_rst_read(CLK_RST_CONTROLLER_PLLD2_BASE_0);
710         if (status & (1 << CLK_RST_CONTROLLER_PLLD2_BASE_0_PLLD2_ENABLE_LSB))
711                 return false;
712         return true;
713 }
714
715 static bool tegra11x_pg_sw_war_missing(int id)
716 {
717         bool ret;
718
719         switch (id) {
720         case TEGRA_POWERGATE_DISA:
721                 /* FIXME:
722                  * [SW WAR bug 954988]:
723                  * Disable PLLD and PLLD2 by clearing bits:
724 a.      CLK_RST_CONTROLLER_PLLD_BASE_0_PLLD_ENABLE
725 b.      CLK_RST_CONTROLLER_PLLD2_BASE_0_PLLD2_ENABLE
726                  * We should not need to disable PLLD and PLLD2
727                  * for linux/android implementation
728                  * adding check in case PLLD or PLLD2 is/are ON
729                  */
730                 ret = tegra11x_check_plld_plld2_disable();
731                 if (!ret)
732                         return true;
733
734                 break;
735         }
736         return false;
737 }
738 #endif
739
740 static int unpowergate_module(int id)
741 {
742         if (id < 0 || id >= tegra_num_powerdomains)
743                 return -EINVAL;
744         return tegra_powergate_set(id, true);
745 }
746
747 static int powergate_module(int id)
748 {
749 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
750         bool need_sw_war;
751 #endif
752         if (id < 0 || id >= tegra_num_powerdomains)
753                 return -EINVAL;
754
755         mc_flush(id);
756 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
757         need_sw_war = tegra11x_pg_sw_war_missing(id);
758         if (need_sw_war) {
759                 pr_err("Error: missing powergate sw war in file: %s, func: %s, line=%d\n",
760                 __FILE__, __func__, __LINE__);
761                 return -1;
762         }
763 #endif
764         return tegra_powergate_set(id, false);
765 }
766
767 bool tegra_powergate_is_powered(int id)
768 {
769         u32 status;
770
771         if (id < 0 || id >= tegra_num_powerdomains)
772                 return -EINVAL;
773
774         status = pmc_read(PWRGATE_STATUS) & (1 << id);
775         return !!status;
776 }
777 EXPORT_SYMBOL(tegra_powergate_is_powered);
778
779 int tegra_powergate_remove_clamping(int id)
780 {
781         u32 mask;
782
783         if (id < 0 || id >= tegra_num_powerdomains)
784                 return -EINVAL;
785
786         /*
787          * PCIE and VDE clamping masks are swapped with respect to their
788          * partition ids
789          */
790         if (id ==  TEGRA_POWERGATE_VDEC)
791                 mask = (1 << TEGRA_POWERGATE_PCIE);
792         else if (id == TEGRA_POWERGATE_PCIE)
793                 mask = (1 << TEGRA_POWERGATE_VDEC);
794         else
795                 mask = (1 << id);
796
797         pmc_write(mask, REMOVE_CLAMPING);
798
799         return 0;
800 }
801
802 static void get_clk_info(int id)
803 {
804         int idx;
805
806         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
807                 if (!powergate_partition_info[id].clk_info[idx].clk_name)
808                         break;
809                 powergate_partition_info[id].
810                                 clk_info[idx].clk_ptr =
811                                         tegra_get_clock_by_name(
812                         powergate_partition_info[id].clk_info[idx].clk_name);
813         }
814 }
815
816 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
817 static bool tegra11x_pug_clk_n_rst_skip(int id, u32 idx)
818 {
819         switch (id) {
820         case TEGRA_POWERGATE_VENC:
821                 if ((powergate_partition_info[id].clk_info[idx].clk_name) &&
822                         (!(strncmp("csi",
823                         powergate_partition_info[id].clk_info[idx].clk_name,
824                         3)))) {
825                                 /* DIS powered ON then do clk enable CSI */
826                                 if (!tegra_powergate_is_powered(
827                                                 TEGRA_POWERGATE_DISA))
828                                         return true;
829                 }
830                 break;
831         case TEGRA_POWERGATE_DISA:
832                 if ((powergate_partition_info[id].clk_info[idx].clk_name) &&
833                         (!(strncmp("csi",
834                         powergate_partition_info[id].clk_info[idx].clk_name,
835                         3)))) {
836                                 /* DIS powered ON then do clk enable CSI */
837                                 if (!tegra_powergate_is_powered(
838                                                 TEGRA_POWERGATE_VENC))
839                                         return true;
840                 }
841                 break;
842         }
843         return false;
844 }
845 #endif
846
847 static int partition_clk_enable(int id)
848 {
849         int ret;
850         u32 idx;
851         struct clk *clk;
852         struct partition_clk_info *clk_info;
853 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
854         bool skip_enable;
855 #endif
856
857         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
858
859         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
860 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
861                 skip_enable = tegra11x_pug_clk_n_rst_skip(id, idx);
862                 if (skip_enable)
863                         continue;
864 #endif
865                 clk_info = &powergate_partition_info[id].clk_info[idx];
866                 clk = clk_info->clk_ptr;
867                 if (!clk)
868                         break;
869
870                 if (clk_info->clk_type != RST_ONLY) {
871                         ret = clk_prepare_enable(clk);
872                         if (ret)
873                                 goto err_clk_en;
874                 }
875         }
876
877         return 0;
878
879 err_clk_en:
880         WARN(1, "Could not enable clk %s", clk->name);
881         while (idx--) {
882                 clk_info = &powergate_partition_info[id].clk_info[idx];
883                 if (clk_info->clk_type != RST_ONLY)
884                         clk_disable_unprepare(clk_info->clk_ptr);
885         }
886
887         return ret;
888 }
889
890 static int is_partition_clk_disabled(int id)
891 {
892         u32 idx;
893         struct clk *clk;
894         struct partition_clk_info *clk_info;
895         int ret = 0;
896
897         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
898
899         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
900                 clk_info = &powergate_partition_info[id].clk_info[idx];
901                 clk = clk_info->clk_ptr;
902                 if (!clk)
903                         break;
904
905                 if (clk_info->clk_type != RST_ONLY) {
906                         if (tegra_is_clk_enabled(clk)) {
907                                 ret = -1;
908                                 break;
909                         }
910                 }
911         }
912
913         return ret;
914 }
915
916 static void partition_clk_disable(int id)
917 {
918         u32 idx;
919         struct clk *clk;
920         struct partition_clk_info *clk_info;
921 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
922         bool skip_disable;
923 #endif
924
925         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
926
927         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
928 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
929                 if (id == TEGRA_POWERGATE_DISA) {
930                         skip_disable = tegra11x_pug_clk_n_rst_skip(id, idx);
931                         if (skip_disable)
932                                 continue;
933                 }
934 #endif
935                 clk_info = &powergate_partition_info[id].clk_info[idx];
936                 clk = clk_info->clk_ptr;
937                 if (!clk)
938                         break;
939
940                 if (clk_info->clk_type != RST_ONLY)
941                         clk_disable_unprepare(clk);
942         }
943 }
944
945 static void powergate_partition_assert_reset(int id)
946 {
947         u32 idx;
948         struct clk *clk_ptr;
949         struct partition_clk_info *clk_info;
950 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
951         bool skip_reset;
952 #endif
953
954         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
955
956         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
957 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
958                 if (id == TEGRA_POWERGATE_DISA) {
959                         skip_reset = tegra11x_pug_clk_n_rst_skip(id, idx);
960                         if (skip_reset)
961                                 continue;
962                 }
963 #endif
964                 clk_info = &powergate_partition_info[id].clk_info[idx];
965                 clk_ptr = clk_info->clk_ptr;
966                 if (!clk_ptr)
967                         break;
968                 if (clk_info->clk_type != CLK_ONLY)
969                         tegra_periph_reset_assert(clk_ptr);
970         }
971 }
972
973 static void powergate_partition_deassert_reset(int id)
974 {
975         u32 idx;
976         struct clk *clk_ptr;
977         struct partition_clk_info *clk_info;
978 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
979         bool skip_reset;
980 #endif
981
982         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
983
984         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
985 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
986                 skip_reset = tegra11x_pug_clk_n_rst_skip(id, idx);
987                 if (skip_reset)
988                         continue;
989 #endif
990                 clk_info = &powergate_partition_info[id].clk_info[idx];
991                 clk_ptr = clk_info->clk_ptr;
992                 if (!clk_ptr)
993                         break;
994                 if (clk_info->clk_type != CLK_ONLY)
995                         tegra_periph_reset_deassert(clk_ptr);
996         }
997 }
998
999 /* Must be called with clk disabled, and returns with clk disabled */
1000 static int tegra_powergate_reset_module(int id)
1001 {
1002         int ret;
1003
1004         powergate_partition_assert_reset(id);
1005
1006         udelay(10);
1007
1008         ret = partition_clk_enable(id);
1009         if (ret)
1010                 return ret;
1011
1012         udelay(10);
1013
1014         powergate_partition_deassert_reset(id);
1015
1016         partition_clk_disable(id);
1017
1018         return 0;
1019 }
1020
1021 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1022 /*
1023  * FIXME: sw war for mipi-cal calibration when unpowergating DISA partition
1024  */
1025 static void tegra11x_mipical_calibrate(int id)
1026 {
1027         struct reg_offset_val {
1028                 u32 offset;
1029                 u32 por_value;
1030         };
1031         u32 status;
1032         unsigned long flags;
1033 #define MIPI_CAL_MIPI_CAL_CTRL_0 0x0
1034 #define MIPI_CAL_CIL_MIPI_CAL_STATUS_0 0x8
1035 #define MIPI_CAL_CILA_MIPI_CAL_CONFIG_0 0x14
1036 #define MIPI_CAL_CILB_MIPI_CAL_CONFIG_0 0x18
1037 #define MIPI_CAL_CILC_MIPI_CAL_CONFIG_0 0x1c
1038 #define MIPI_CAL_CILD_MIPI_CAL_CONFIG_0 0x20
1039 #define MIPI_CAL_CILE_MIPI_CAL_CONFIG_0 0x24
1040 #define MIPI_CAL_DSIA_MIPI_CAL_CONFIG_0 0x38
1041 #define MIPI_CAL_DSIB_MIPI_CAL_CONFIG_0 0x3c
1042 #define MIPI_CAL_DSIC_MIPI_CAL_CONFIG_0 0x40
1043 #define MIPI_CAL_DSID_MIPI_CAL_CONFIG_0 0x44
1044         static struct reg_offset_val mipi_cal_por_values[] = {
1045                 { MIPI_CAL_MIPI_CAL_CTRL_0, 0x2a000000 },
1046                 { MIPI_CAL_CILA_MIPI_CAL_CONFIG_0, 0x00200000 },
1047                 { MIPI_CAL_CILB_MIPI_CAL_CONFIG_0, 0x00200000 },
1048                 { MIPI_CAL_CILC_MIPI_CAL_CONFIG_0, 0x00200000 },
1049                 { MIPI_CAL_CILD_MIPI_CAL_CONFIG_0, 0x00200000 },
1050                 { MIPI_CAL_CILE_MIPI_CAL_CONFIG_0, 0x00000000 },
1051                 { MIPI_CAL_DSIA_MIPI_CAL_CONFIG_0, 0x00200000 },
1052                 { MIPI_CAL_DSIB_MIPI_CAL_CONFIG_0, 0x00200000 },
1053                 { MIPI_CAL_DSIC_MIPI_CAL_CONFIG_0, 0x00200000 },
1054                 { MIPI_CAL_DSID_MIPI_CAL_CONFIG_0, 0x00200000 },
1055         };
1056         int i;
1057
1058         if (id != TEGRA_POWERGATE_DISA)
1059                 return;
1060         spin_lock_irqsave(&tegra_powergate_lock, flags);
1061         /* mipi cal por restore */
1062         for (i = 0; i < ARRAY_SIZE(mipi_cal_por_values); i++) {
1063                 mipi_cal_write(mipi_cal_por_values[i].por_value,
1064                         mipi_cal_por_values[i].offset);
1065         }
1066         /* mipi cal status clear */
1067         status = mipi_cal_read(MIPI_CAL_CIL_MIPI_CAL_STATUS_0);
1068         mipi_cal_write(status, MIPI_CAL_CIL_MIPI_CAL_STATUS_0);
1069         /* mipi cal status read - to flush writes */
1070         status = mipi_cal_read(MIPI_CAL_CIL_MIPI_CAL_STATUS_0);
1071         spin_unlock_irqrestore(&tegra_powergate_lock, flags);
1072         if (status)
1073                 pr_err("Error: mipi_cal calibration failed at file: %s, func: %s, line=%d\n",
1074                 __FILE__, __func__, __LINE__);
1075 }
1076 #endif
1077
1078 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1079 static bool skip_pg_check(int id, bool is_unpowergate)
1080 {
1081         /*
1082          * FIXME: need to stress test partition power gating before
1083          * enabling power gating for T11x
1084          * List of T11x partition id which skip power gating
1085          */
1086         static int skip_pg_t11x_list[] = {
1087                 0,
1088                 1,
1089                 2,
1090                 3,
1091                 4,
1092                 5,
1093                 6,
1094                 7,
1095                 8,
1096                 9,
1097                 10,
1098                 11,
1099                 12,
1100                 13,
1101                 14,
1102                 15,
1103                 16,
1104                 17,
1105                 18,
1106                 19,
1107                 20,
1108                 21,
1109                 22,
1110         };
1111         int i;
1112
1113         if ((tegra_powergate_is_powered(id) &&
1114                 is_unpowergate) ||
1115                 (!(tegra_powergate_is_powered(id)) &&
1116                 (!is_unpowergate))) {
1117                 pr_err("Partition %s already powered-%s and %spowergate skipped\n",
1118                         tegra_powergate_get_name(id),
1119                         (tegra_powergate_is_powered(id)) ?
1120                         "on" : "off",
1121                         (is_unpowergate) ? "un" : "");
1122                 return true;
1123         }
1124         /* unpowergate is needed initially for cpus */
1125         if (!tegra_powergate_is_powered(id) &&
1126                 is_unpowergate) {
1127                 pr_err("Partition %s already powered-%s unpowergating\n",
1128                         tegra_powergate_get_name(id),
1129                         (tegra_powergate_is_powered(id)) ?
1130                         "on" : "off");
1131                 return false;
1132         }
1133         for (i = 0; i < tegra_num_powerdomains; i++) {
1134                 if (id == skip_pg_t11x_list[i]) {
1135                         pr_err("Partition %s %spowergate skipped\n",
1136                                 tegra_powergate_get_name(id),
1137                                 (is_unpowergate) ? "un" : "");
1138                         return true;
1139                 }
1140         }
1141
1142         return false;
1143 }
1144 #endif
1145
1146 /*
1147  * Must be called with clk disabled, and returns with clk disabled
1148  * Drivers should enable clks for partition. Unpowergates only the
1149  * partition.
1150  */
1151 int tegra_unpowergate_partition(int id)
1152 {
1153         int ret;
1154 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1155         bool is_pg_skip;
1156
1157         is_pg_skip = skip_pg_check(id, true);
1158         if (is_pg_skip)
1159                 return 0;
1160         ret = tegra11x_check_partition_pug_seq(id);
1161         if (ret)
1162                 return ret;
1163 #endif
1164         /* If first clk_ptr is null, fill clk info for the partition */
1165         if (!powergate_partition_info[id].clk_info[0].clk_ptr)
1166                 get_clk_info(id);
1167
1168         if (tegra_powergate_is_powered(id))
1169                 return tegra_powergate_reset_module(id);
1170
1171         ret = unpowergate_module(id);
1172         if (ret)
1173                 goto err_power;
1174
1175         powergate_partition_assert_reset(id);
1176
1177         /* Un-Powergating fails if all clks are not enabled */
1178         ret = partition_clk_enable(id);
1179         if (ret)
1180                 goto err_clk_on;
1181
1182         udelay(10);
1183
1184         ret = tegra_powergate_remove_clamping(id);
1185         if (ret)
1186                 goto err_clamp;
1187
1188         udelay(10);
1189
1190 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1191         tegra11x_mipical_calibrate(id);
1192 #endif
1193         powergate_partition_deassert_reset(id);
1194
1195         mc_flush_done(id);
1196
1197         /* Disable all clks enabled earlier. Drivers should enable clks */
1198         partition_clk_disable(id);
1199
1200         return 0;
1201
1202 err_clamp:
1203         partition_clk_disable(id);
1204 err_clk_on:
1205         powergate_module(id);
1206 err_power:
1207         WARN(1, "Could not Un-Powergate %d", id);
1208         return ret;
1209 }
1210
1211 int tegra_cpu_powergate_id(int cpuid)
1212 {
1213         if (cpuid > 0 && cpuid < tegra_num_cpu_domains)
1214                 return tegra_cpu_domains[cpuid];
1215
1216         return -EINVAL;
1217 }
1218
1219 int __init tegra_powergate_init(void)
1220 {
1221         switch (tegra_chip_id) {
1222         case TEGRA20:
1223                 tegra_num_powerdomains = 7;
1224                 break;
1225         case TEGRA30:
1226                 tegra_num_powerdomains = 14;
1227                 tegra_num_cpu_domains = 4;
1228                 tegra_cpu_domains = tegra_quad_cpu_domains;
1229                 break;
1230         case TEGRA11X:
1231                 tegra_num_powerdomains = 23;
1232                 tegra_num_cpu_domains = 4;
1233                 tegra_cpu_domains = tegra_quad_cpu_domains;
1234                 break;
1235         default:
1236                 /* Unknown Tegra variant. Disable powergating */
1237                 tegra_num_powerdomains = 0;
1238                 break;
1239         }
1240
1241 #if defined(DEBUG_T11x_POWERGATE)
1242         test_powergate_parts();
1243 #endif
1244 #if defined(DEBUG_T11x_POWERUNGATE)
1245         test_unpowergate_parts();
1246 #endif
1247 #if defined(DEBUG_T11x_POWERGATE_CLK_OFF)
1248         test_powergate_clk_off_parts();
1249 #endif
1250 #if defined(DEBUG_T11x_POWERUNGATE_CLK_ON)
1251         test_unpowergate_clk_on_parts();
1252 #endif
1253         return 0;
1254 }
1255
1256 /*
1257  * Must be called with clk disabled, and returns with clk enabled
1258  * Unpowergates the partition and enables all required clks.
1259  */
1260 int tegra_unpowergate_partition_with_clk_on(int id)
1261 {
1262         int ret = 0;
1263 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1264         bool is_pg_skip;
1265
1266         is_pg_skip = skip_pg_check(id, true);
1267         if (is_pg_skip)
1268                 return 0;
1269 #endif
1270 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
1271         /* Restrict this functions use to few partitions */
1272         BUG_ON(id != TEGRA_POWERGATE_SATA && id != TEGRA_POWERGATE_PCIE);
1273 #elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
1274         /* Restrict this functions use to few partitions */
1275         BUG_ON(id != TEGRA_POWERGATE_PCIE);
1276 #endif
1277
1278         ret = tegra_unpowergate_partition(id);
1279         if (ret)
1280                 goto err_unpowergating;
1281
1282         /* Enable clks for the partition */
1283         ret = partition_clk_enable(id);
1284         if (ret)
1285                 goto err_unpowergate_clk;
1286
1287         return ret;
1288
1289 err_unpowergate_clk:
1290         tegra_powergate_partition(id);
1291         WARN(1, "Could not Un-Powergate %d, err in enabling clk", id);
1292 err_unpowergating:
1293         WARN(1, "Could not Un-Powergate %d", id);
1294         return ret;
1295 }
1296
1297 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1298 static int tegra11x_powergate_partition(int id)
1299 {
1300         int ret;
1301
1302         if (tegra_powergate_is_powered(id)) {
1303                 ret = is_partition_clk_disabled(id);
1304                 if (ret < 0) {
1305                         /* clock enabled */
1306                         ret = tegra_powergate_partition_with_clk_off(id);
1307                         if (ret < 0)
1308                                 return ret;
1309                 } else {
1310                         ret = tegra_powergate_partition(id);
1311                         if (ret < 0)
1312                                 return ret;
1313                 }
1314         }
1315         return 0;
1316 }
1317
1318 static int tegra11x_unpowergate_partition(int id)
1319 {
1320         int ret;
1321
1322         if (!tegra_powergate_is_powered(id)) {
1323                 ret = is_partition_clk_disabled(id);
1324                 if (ret) {
1325                         /* clock disabled */
1326                         ret = tegra_unpowergate_partition_with_clk_on(id);
1327                         if (ret < 0)
1328                                 return ret;
1329                 } else {
1330                         ret = tegra_unpowergate_partition(id);
1331                         if (ret < 0)
1332                                 return ret;
1333                 }
1334         }
1335         return 0;
1336 }
1337
1338 static int tegra11x_check_partition_pg_seq(int id)
1339 {
1340         int ret;
1341
1342         switch (id) {
1343         case TEGRA_POWERGATE_DISA:
1344                 ret = tegra11x_powergate_partition(TEGRA_POWERGATE_VENC);
1345                 if (ret < 0)
1346                         return ret;
1347                 ret = tegra11x_powergate_partition(TEGRA_POWERGATE_DISB);
1348                 if (ret < 0)
1349                         return ret;
1350
1351                 break;
1352         }
1353         return 0;
1354 }
1355
1356 static int tegra11x_check_partition_pug_seq(int id)
1357 {
1358         int ret;
1359
1360         switch (id) {
1361         case TEGRA_POWERGATE_DISB:
1362         case TEGRA_POWERGATE_VENC:
1363                 ret = tegra11x_unpowergate_partition(TEGRA_POWERGATE_DISA);
1364                 if (ret < 0)
1365                         return ret;
1366
1367                 break;
1368         }
1369         return 0;
1370 }
1371 #endif
1372
1373 /*
1374  * Must be called with clk disabled. Powergates the partition only
1375  */
1376 int tegra_powergate_partition(int id)
1377 {
1378         int ret;
1379 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1380         bool is_pg_skip;
1381
1382         is_pg_skip = skip_pg_check(id, false);
1383         if (is_pg_skip)
1384                 return 0;
1385
1386         ret = tegra11x_check_partition_pg_seq(id);
1387         if (ret)
1388                 return ret;
1389 #endif
1390         /* If first clk_ptr is null, fill clk info for the partition */
1391         if (powergate_partition_info[id].clk_info[0].clk_ptr)
1392                 get_clk_info(id);
1393         powergate_partition_assert_reset(id);
1394
1395         /* Powergating is done only if refcnt of all clks is 0 */
1396         ret = is_partition_clk_disabled(id);
1397         if (ret)
1398                 goto err_clk_off;
1399
1400         ret = powergate_module(id);
1401         if (ret)
1402                 goto err_power_off;
1403
1404         return 0;
1405
1406 err_power_off:
1407         WARN(1, "Could not Powergate Partition %d", id);
1408 err_clk_off:
1409         WARN(1, "Could not Powergate Partition %d, all clks not disabled", id);
1410         return ret;
1411 }
1412
1413 int tegra_powergate_partition_with_clk_off(int id)
1414 {
1415         int ret = 0;
1416 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1417         bool is_pg_skip;
1418
1419         is_pg_skip = skip_pg_check(id, false);
1420         if (is_pg_skip)
1421                 return 0;
1422 #endif
1423 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
1424         /* Restrict functions use to selected partitions */
1425         BUG_ON(id != TEGRA_POWERGATE_PCIE && id != TEGRA_POWERGATE_SATA);
1426 #elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
1427         /* Restrict functions use to selected partitions */
1428         BUG_ON(id != TEGRA_POWERGATE_PCIE);
1429 #endif
1430         /* Disable clks for the partition */
1431         partition_clk_disable(id);
1432
1433         ret = is_partition_clk_disabled(id);
1434         if (ret)
1435                 goto err_powergate_clk;
1436
1437         ret = tegra_powergate_partition(id);
1438         if (ret)
1439                 goto err_powergating;
1440
1441         return ret;
1442
1443 err_powergate_clk:
1444         WARN(1, "Could not Powergate Partition %d, all clks not disabled", id);
1445 err_powergating:
1446         partition_clk_enable(id);
1447         WARN(1, "Could not Powergate Partition %d", id);
1448         return ret;
1449 }
1450
1451 #if defined(DEBUG_T11x_POWERGATE)
1452 static void test_powergate_parts(void)
1453 {
1454         int i;
1455
1456         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1457                 tegra_powergate_partition(i);
1458 }
1459 #endif
1460
1461 #if defined(DEBUG_T11x_POWERUNGATE)
1462 static void test_powerungate_parts(void)
1463 {
1464         int i;
1465
1466         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1467                 tegra_unpowergate_partition(i);
1468 }
1469 #endif
1470
1471 #if defined(DEBUG_T11x_POWERGATE_CLK_OFF)
1472 static void test_powergate_clk_off_parts(void)
1473 {
1474         int i;
1475
1476         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1477                 tegra_powergate_partition_with_clk_off(i);
1478 }
1479 #endif
1480
1481 #if defined(DEBUG_T11x_POWERUNGATE_CLK_OFF)
1482 static void test_unpowergate_clk_on_parts(void)
1483 {
1484         int i;
1485
1486         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1487                 tegra_unpowergate_partition_with_clk_on(i);
1488 }
1489 #endif
1490
1491 const char *tegra_powergate_get_name(int id)
1492 {
1493         if (id < 0 || id >= TEGRA_NUM_POWERGATE)
1494                 return "invalid";
1495
1496         return powergate_partition_info[id].name;
1497 }
1498
1499 #ifdef CONFIG_DEBUG_FS
1500
1501 static int powergate_show(struct seq_file *s, void *data)
1502 {
1503         int i;
1504         const char *name;
1505
1506         seq_printf(s, " powergate powered\n");
1507         seq_printf(s, "------------------\n");
1508
1509         for (i = 0; i < tegra_num_powerdomains; i++) {
1510                 name = tegra_powergate_get_name(i);
1511                 if (name)
1512                         seq_printf(s, " %9s %7s\n", name,
1513                                 tegra_powergate_is_powered(i) ? "yes" : "no");
1514         }
1515
1516         return 0;
1517 }
1518
1519 static int powergate_open(struct inode *inode, struct file *file)
1520 {
1521         return single_open(file, powergate_show, inode->i_private);
1522 }
1523
1524 static const struct file_operations powergate_fops = {
1525         .open           = powergate_open,
1526         .read           = seq_read,
1527         .llseek         = seq_lseek,
1528         .release        = single_release,
1529 };
1530
1531 int __init tegra_powergate_debugfs_init(void)
1532 {
1533         struct dentry *d;
1534
1535         if (powergate_name) {
1536                 d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
1537                         &powergate_fops);
1538                 if (!d)
1539                         return -ENOMEM;
1540         }
1541
1542         return 0;
1543 }
1544
1545 #endif