arm: tegra: power gate update
[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 /*
1079  * Must be called with clk disabled, and returns with clk disabled
1080  * Drivers should enable clks for partition. Unpowergates only the
1081  * partition.
1082  */
1083 int tegra_unpowergate_partition(int id)
1084 {
1085         int ret;
1086
1087 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1088         ret = tegra11x_check_partition_pug_seq(id);
1089         if (ret)
1090                 return ret;
1091 #endif
1092         /* If first clk_ptr is null, fill clk info for the partition */
1093         if (!powergate_partition_info[id].clk_info[0].clk_ptr)
1094                 get_clk_info(id);
1095
1096         if (tegra_powergate_is_powered(id))
1097                 return tegra_powergate_reset_module(id);
1098
1099         ret = unpowergate_module(id);
1100         if (ret)
1101                 goto err_power;
1102
1103         powergate_partition_assert_reset(id);
1104
1105         /* Un-Powergating fails if all clks are not enabled */
1106         ret = partition_clk_enable(id);
1107         if (ret)
1108                 goto err_clk_on;
1109
1110         udelay(10);
1111
1112         ret = tegra_powergate_remove_clamping(id);
1113         if (ret)
1114                 goto err_clamp;
1115
1116         udelay(10);
1117
1118 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1119         tegra11x_mipical_calibrate(id);
1120 #endif
1121         powergate_partition_deassert_reset(id);
1122
1123         mc_flush_done(id);
1124
1125         /* Disable all clks enabled earlier. Drivers should enable clks */
1126         partition_clk_disable(id);
1127
1128         return 0;
1129
1130 err_clamp:
1131         partition_clk_disable(id);
1132 err_clk_on:
1133         powergate_module(id);
1134 err_power:
1135         WARN(1, "Could not Un-Powergate %d", id);
1136         return ret;
1137 }
1138
1139 int tegra_cpu_powergate_id(int cpuid)
1140 {
1141         if (cpuid > 0 && cpuid < tegra_num_cpu_domains)
1142                 return tegra_cpu_domains[cpuid];
1143
1144         return -EINVAL;
1145 }
1146
1147 int __init tegra_powergate_init(void)
1148 {
1149         switch (tegra_chip_id) {
1150         case TEGRA20:
1151                 tegra_num_powerdomains = 7;
1152                 break;
1153         case TEGRA30:
1154                 tegra_num_powerdomains = 14;
1155                 tegra_num_cpu_domains = 4;
1156                 tegra_cpu_domains = tegra_quad_cpu_domains;
1157                 break;
1158         case TEGRA11X:
1159                 tegra_num_powerdomains = 23;
1160                 tegra_num_cpu_domains = 4;
1161                 tegra_cpu_domains = tegra_quad_cpu_domains;
1162                 break;
1163         default:
1164                 /* Unknown Tegra variant. Disable powergating */
1165                 tegra_num_powerdomains = 0;
1166                 break;
1167         }
1168
1169 #if defined(DEBUG_T11x_POWERGATE)
1170         test_powergate_parts();
1171 #endif
1172 #if defined(DEBUG_T11x_POWERUNGATE)
1173         test_unpowergate_parts();
1174 #endif
1175 #if defined(DEBUG_T11x_POWERGATE_CLK_OFF)
1176         test_powergate_clk_off_parts();
1177 #endif
1178 #if defined(DEBUG_T11x_POWERUNGATE_CLK_ON)
1179         test_unpowergate_clk_on_parts();
1180 #endif
1181         return 0;
1182 }
1183
1184 /*
1185  * Must be called with clk disabled, and returns with clk enabled
1186  * Unpowergates the partition and enables all required clks.
1187  */
1188 int tegra_unpowergate_partition_with_clk_on(int id)
1189 {
1190         int ret = 0;
1191
1192 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
1193         /* Restrict this functions use to few partitions */
1194         BUG_ON(id != TEGRA_POWERGATE_SATA && id != TEGRA_POWERGATE_PCIE);
1195 #elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
1196         /* Restrict this functions use to few partitions */
1197         BUG_ON(id != TEGRA_POWERGATE_PCIE);
1198 #endif
1199
1200         ret = tegra_unpowergate_partition(id);
1201         if (ret)
1202                 goto err_unpowergating;
1203
1204         /* Enable clks for the partition */
1205         ret = partition_clk_enable(id);
1206         if (ret)
1207                 goto err_unpowergate_clk;
1208
1209         return ret;
1210
1211 err_unpowergate_clk:
1212         tegra_powergate_partition(id);
1213         WARN(1, "Could not Un-Powergate %d, err in enabling clk", id);
1214 err_unpowergating:
1215         WARN(1, "Could not Un-Powergate %d", id);
1216         return ret;
1217 }
1218
1219 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1220 static int tegra11x_powergate_partition(int id)
1221 {
1222         int ret;
1223
1224         if (tegra_powergate_is_powered(id)) {
1225                 ret = is_partition_clk_disabled(id);
1226                 if (ret < 0) {
1227                         /* clock enabled */
1228                         ret = tegra_powergate_partition_with_clk_off(id);
1229                         if (ret < 0)
1230                                 return ret;
1231                 } else {
1232                         ret = tegra_powergate_partition(id);
1233                         if (ret < 0)
1234                                 return ret;
1235                 }
1236         }
1237         return 0;
1238 }
1239
1240 static int tegra11x_unpowergate_partition(int id)
1241 {
1242         int ret;
1243
1244         if (!tegra_powergate_is_powered(id)) {
1245                 ret = is_partition_clk_disabled(id);
1246                 if (ret) {
1247                         /* clock disabled */
1248                         ret = tegra_unpowergate_partition_with_clk_on(id);
1249                         if (ret < 0)
1250                                 return ret;
1251                 } else {
1252                         ret = tegra_unpowergate_partition(id);
1253                         if (ret < 0)
1254                                 return ret;
1255                 }
1256         }
1257         return 0;
1258 }
1259
1260 static int tegra11x_check_partition_pg_seq(int id)
1261 {
1262         int ret;
1263
1264         switch (id) {
1265         case TEGRA_POWERGATE_DISA:
1266                 ret = tegra11x_powergate_partition(TEGRA_POWERGATE_VENC);
1267                 if (ret < 0)
1268                         return ret;
1269                 ret = tegra11x_powergate_partition(TEGRA_POWERGATE_DISB);
1270                 if (ret < 0)
1271                         return ret;
1272
1273                 break;
1274         }
1275         return 0;
1276 }
1277
1278 static int tegra11x_check_partition_pug_seq(int id)
1279 {
1280         int ret;
1281
1282         switch (id) {
1283         case TEGRA_POWERGATE_DISB:
1284         case TEGRA_POWERGATE_VENC:
1285                 ret = tegra11x_unpowergate_partition(TEGRA_POWERGATE_DISA);
1286                 if (ret < 0)
1287                         return ret;
1288
1289                 break;
1290         }
1291         return 0;
1292 }
1293 #endif
1294
1295 /*
1296  * Must be called with clk disabled. Powergates the partition only
1297  */
1298 int tegra_powergate_partition(int id)
1299 {
1300         int ret;
1301
1302 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1303         ret = tegra11x_check_partition_pg_seq(id);
1304         if (ret)
1305                 return ret;
1306 #endif
1307         /* If first clk_ptr is null, fill clk info for the partition */
1308         if (powergate_partition_info[id].clk_info[0].clk_ptr)
1309                 get_clk_info(id);
1310         powergate_partition_assert_reset(id);
1311
1312         /* Powergating is done only if refcnt of all clks is 0 */
1313         ret = is_partition_clk_disabled(id);
1314         if (ret)
1315                 goto err_clk_off;
1316
1317         ret = powergate_module(id);
1318         if (ret)
1319                 goto err_power_off;
1320
1321         return 0;
1322
1323 err_power_off:
1324         WARN(1, "Could not Powergate Partition %d", id);
1325 err_clk_off:
1326         WARN(1, "Could not Powergate Partition %d, all clks not disabled", id);
1327         return ret;
1328 }
1329
1330 int tegra_powergate_partition_with_clk_off(int id)
1331 {
1332         int ret = 0;
1333
1334 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
1335         /* Restrict functions use to selected partitions */
1336         BUG_ON(id != TEGRA_POWERGATE_PCIE && id != TEGRA_POWERGATE_SATA);
1337 #elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
1338         /* Restrict functions use to selected partitions */
1339         BUG_ON(id != TEGRA_POWERGATE_PCIE);
1340 #endif
1341         /* Disable clks for the partition */
1342         partition_clk_disable(id);
1343
1344         ret = is_partition_clk_disabled(id);
1345         if (ret)
1346                 goto err_powergate_clk;
1347
1348         ret = tegra_powergate_partition(id);
1349         if (ret)
1350                 goto err_powergating;
1351
1352         return ret;
1353
1354 err_powergate_clk:
1355         WARN(1, "Could not Powergate Partition %d, all clks not disabled", id);
1356 err_powergating:
1357         partition_clk_enable(id);
1358         WARN(1, "Could not Powergate Partition %d", id);
1359         return ret;
1360 }
1361
1362 #if defined(DEBUG_T11x_POWERGATE)
1363 static void test_powergate_parts(void)
1364 {
1365         int i;
1366
1367         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1368                 tegra_powergate_partition(i);
1369 }
1370 #endif
1371
1372 #if defined(DEBUG_T11x_POWERUNGATE)
1373 static void test_powerungate_parts(void)
1374 {
1375         int i;
1376
1377         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1378                 tegra_unpowergate_partition(i);
1379 }
1380 #endif
1381
1382 #if defined(DEBUG_T11x_POWERGATE_CLK_OFF)
1383 static void test_powergate_clk_off_parts(void)
1384 {
1385         int i;
1386
1387         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1388                 tegra_powergate_partition_with_clk_off(i);
1389 }
1390 #endif
1391
1392 #if defined(DEBUG_T11x_POWERUNGATE_CLK_OFF)
1393 static void test_unpowergate_clk_on_parts(void)
1394 {
1395         int i;
1396
1397         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1398                 tegra_unpowergate_partition_with_clk_on(i);
1399 }
1400 #endif
1401
1402 const char *tegra_powergate_get_name(int id)
1403 {
1404         if (id < 0 || id >= TEGRA_NUM_POWERGATE)
1405                 return "invalid";
1406
1407         return powergate_partition_info[id].name;
1408 }
1409
1410 #ifdef CONFIG_DEBUG_FS
1411
1412 static int powergate_show(struct seq_file *s, void *data)
1413 {
1414         int i;
1415         const char *name;
1416
1417         seq_printf(s, " powergate powered\n");
1418         seq_printf(s, "------------------\n");
1419
1420         for (i = 0; i < tegra_num_powerdomains; i++) {
1421                 name = tegra_powergate_get_name(i);
1422                 if (name)
1423                         seq_printf(s, " %9s %7s\n", name,
1424                                 tegra_powergate_is_powered(i) ? "yes" : "no");
1425         }
1426
1427         return 0;
1428 }
1429
1430 static int powergate_open(struct inode *inode, struct file *file)
1431 {
1432         return single_open(file, powergate_show, inode->i_private);
1433 }
1434
1435 static const struct file_operations powergate_fops = {
1436         .open           = powergate_open,
1437         .read           = seq_read,
1438         .llseek         = seq_lseek,
1439         .release        = single_release,
1440 };
1441
1442 int __init tegra_powergate_debugfs_init(void)
1443 {
1444         struct dentry *d;
1445
1446         if (powergate_name) {
1447                 d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
1448                         &powergate_fops);
1449                 if (!d)
1450                         return -ENOMEM;
1451         }
1452
1453         return 0;
1454 }
1455
1456 #endif