ARM: tegra: Use 3D power gating sequence for MSENC
[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.cbus", 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         int contention_timeout = 100;
783
784         if (id < 0 || id >= tegra_num_powerdomains)
785                 return -EINVAL;
786
787         /*
788          * PCIE and VDE clamping masks are swapped with respect to their
789          * partition ids
790          */
791         if (id ==  TEGRA_POWERGATE_VDEC)
792                 mask = (1 << TEGRA_POWERGATE_PCIE);
793         else if (id == TEGRA_POWERGATE_PCIE)
794                 mask = (1 << TEGRA_POWERGATE_VDEC);
795         else
796                 mask = (1 << id);
797
798         pmc_write(mask, REMOVE_CLAMPING);
799         /* Wait until clamp is removed */
800         do {
801                 udelay(1);
802                 contention_timeout--;
803         } while ((contention_timeout > 0)
804                         && (pmc_read(REMOVE_CLAMPING) & mask));
805
806         WARN(contention_timeout <= 0, "Couldn't remove clamping");
807
808         return 0;
809 }
810
811 static void get_clk_info(int id)
812 {
813         int idx;
814
815         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
816                 if (!powergate_partition_info[id].clk_info[idx].clk_name)
817                         break;
818                 powergate_partition_info[id].
819                                 clk_info[idx].clk_ptr =
820                                         tegra_get_clock_by_name(
821                         powergate_partition_info[id].clk_info[idx].clk_name);
822         }
823 }
824
825 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
826 static bool tegra11x_pug_clk_n_rst_skip(int id, u32 idx)
827 {
828         switch (id) {
829         case TEGRA_POWERGATE_VENC:
830                 if ((powergate_partition_info[id].clk_info[idx].clk_name) &&
831                         (!(strncmp("csi",
832                         powergate_partition_info[id].clk_info[idx].clk_name,
833                         3)))) {
834                                 /* DIS powered ON then do clk enable CSI */
835                                 if (!tegra_powergate_is_powered(
836                                                 TEGRA_POWERGATE_DISA))
837                                         return true;
838                 }
839                 break;
840         case TEGRA_POWERGATE_DISA:
841                 if ((powergate_partition_info[id].clk_info[idx].clk_name) &&
842                         (!(strncmp("csi",
843                         powergate_partition_info[id].clk_info[idx].clk_name,
844                         3)))) {
845                                 /* DIS powered ON then do clk enable CSI */
846                                 if (!tegra_powergate_is_powered(
847                                                 TEGRA_POWERGATE_VENC))
848                                         return true;
849                 }
850                 break;
851         }
852         return false;
853 }
854 #endif
855
856 static int partition_clk_enable(int id)
857 {
858         int ret;
859         u32 idx;
860         struct clk *clk;
861         struct partition_clk_info *clk_info;
862 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
863         bool skip_enable;
864 #endif
865
866         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
867
868         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
869 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
870                 skip_enable = tegra11x_pug_clk_n_rst_skip(id, idx);
871                 if (skip_enable)
872                         continue;
873 #endif
874                 clk_info = &powergate_partition_info[id].clk_info[idx];
875                 clk = clk_info->clk_ptr;
876                 if (!clk)
877                         break;
878
879                 if (clk_info->clk_type != RST_ONLY) {
880                         ret = clk_prepare_enable(clk);
881                         if (ret)
882                                 goto err_clk_en;
883                 }
884         }
885
886         return 0;
887
888 err_clk_en:
889         WARN(1, "Could not enable clk %s", clk->name);
890         while (idx--) {
891                 clk_info = &powergate_partition_info[id].clk_info[idx];
892                 if (clk_info->clk_type != RST_ONLY)
893                         clk_disable_unprepare(clk_info->clk_ptr);
894         }
895
896         return ret;
897 }
898
899 static int is_partition_clk_disabled(int id)
900 {
901         u32 idx;
902         struct clk *clk;
903         struct partition_clk_info *clk_info;
904         int ret = 0;
905
906         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
907
908         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
909                 clk_info = &powergate_partition_info[id].clk_info[idx];
910                 clk = clk_info->clk_ptr;
911                 if (!clk)
912                         break;
913
914                 if (clk_info->clk_type != RST_ONLY) {
915                         if (tegra_is_clk_enabled(clk)) {
916                                 ret = -1;
917                                 break;
918                         }
919                 }
920         }
921
922         return ret;
923 }
924
925 static void partition_clk_disable(int id)
926 {
927         u32 idx;
928         struct clk *clk;
929         struct partition_clk_info *clk_info;
930 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
931         bool skip_disable;
932 #endif
933
934         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
935
936         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
937 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
938                 if (id == TEGRA_POWERGATE_DISA) {
939                         skip_disable = tegra11x_pug_clk_n_rst_skip(id, idx);
940                         if (skip_disable)
941                                 continue;
942                 }
943 #endif
944                 clk_info = &powergate_partition_info[id].clk_info[idx];
945                 clk = clk_info->clk_ptr;
946                 if (!clk)
947                         break;
948
949                 if (clk_info->clk_type != RST_ONLY)
950                         clk_disable_unprepare(clk);
951         }
952 }
953
954 static void powergate_partition_assert_reset(int id)
955 {
956         u32 idx;
957         struct clk *clk_ptr;
958         struct partition_clk_info *clk_info;
959 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
960         bool skip_reset;
961 #endif
962
963         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
964
965         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
966 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
967                 if (id == TEGRA_POWERGATE_DISA) {
968                         skip_reset = tegra11x_pug_clk_n_rst_skip(id, idx);
969                         if (skip_reset)
970                                 continue;
971                 }
972 #endif
973                 clk_info = &powergate_partition_info[id].clk_info[idx];
974                 clk_ptr = clk_info->clk_ptr;
975                 if (!clk_ptr)
976                         break;
977                 if (clk_info->clk_type != CLK_ONLY)
978                         tegra_periph_reset_assert(clk_ptr);
979         }
980 }
981
982 static void powergate_partition_deassert_reset(int id)
983 {
984         u32 idx;
985         struct clk *clk_ptr;
986         struct partition_clk_info *clk_info;
987 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
988         bool skip_reset;
989 #endif
990
991         BUG_ON(id < 0 || id >= TEGRA_NUM_POWERGATE);
992
993         for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
994 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
995                 skip_reset = tegra11x_pug_clk_n_rst_skip(id, idx);
996                 if (skip_reset)
997                         continue;
998 #endif
999                 clk_info = &powergate_partition_info[id].clk_info[idx];
1000                 clk_ptr = clk_info->clk_ptr;
1001                 if (!clk_ptr)
1002                         break;
1003                 if (clk_info->clk_type != CLK_ONLY)
1004                         tegra_periph_reset_deassert(clk_ptr);
1005         }
1006 }
1007
1008 /* Must be called with clk disabled, and returns with clk disabled */
1009 static int tegra_powergate_reset_module(int id)
1010 {
1011         int ret;
1012
1013         powergate_partition_assert_reset(id);
1014
1015         udelay(10);
1016
1017         ret = partition_clk_enable(id);
1018         if (ret)
1019                 return ret;
1020
1021         udelay(10);
1022
1023         powergate_partition_deassert_reset(id);
1024
1025         partition_clk_disable(id);
1026
1027         return 0;
1028 }
1029
1030 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1031 /*
1032  * FIXME: sw war for mipi-cal calibration when unpowergating DISA partition
1033  */
1034 static void tegra11x_mipical_calibrate(int id)
1035 {
1036         struct reg_offset_val {
1037                 u32 offset;
1038                 u32 por_value;
1039         };
1040         u32 status;
1041         unsigned long flags;
1042 #define MIPI_CAL_MIPI_CAL_CTRL_0 0x0
1043 #define MIPI_CAL_CIL_MIPI_CAL_STATUS_0 0x8
1044 #define MIPI_CAL_CILA_MIPI_CAL_CONFIG_0 0x14
1045 #define MIPI_CAL_CILB_MIPI_CAL_CONFIG_0 0x18
1046 #define MIPI_CAL_CILC_MIPI_CAL_CONFIG_0 0x1c
1047 #define MIPI_CAL_CILD_MIPI_CAL_CONFIG_0 0x20
1048 #define MIPI_CAL_CILE_MIPI_CAL_CONFIG_0 0x24
1049 #define MIPI_CAL_DSIA_MIPI_CAL_CONFIG_0 0x38
1050 #define MIPI_CAL_DSIB_MIPI_CAL_CONFIG_0 0x3c
1051 #define MIPI_CAL_DSIC_MIPI_CAL_CONFIG_0 0x40
1052 #define MIPI_CAL_DSID_MIPI_CAL_CONFIG_0 0x44
1053         static struct reg_offset_val mipi_cal_por_values[] = {
1054                 { MIPI_CAL_MIPI_CAL_CTRL_0, 0x2a000000 },
1055                 { MIPI_CAL_CILA_MIPI_CAL_CONFIG_0, 0x00200000 },
1056                 { MIPI_CAL_CILB_MIPI_CAL_CONFIG_0, 0x00200000 },
1057                 { MIPI_CAL_CILC_MIPI_CAL_CONFIG_0, 0x00200000 },
1058                 { MIPI_CAL_CILD_MIPI_CAL_CONFIG_0, 0x00200000 },
1059                 { MIPI_CAL_CILE_MIPI_CAL_CONFIG_0, 0x00000000 },
1060                 { MIPI_CAL_DSIA_MIPI_CAL_CONFIG_0, 0x00200000 },
1061                 { MIPI_CAL_DSIB_MIPI_CAL_CONFIG_0, 0x00200000 },
1062                 { MIPI_CAL_DSIC_MIPI_CAL_CONFIG_0, 0x00200000 },
1063                 { MIPI_CAL_DSID_MIPI_CAL_CONFIG_0, 0x00200000 },
1064         };
1065         int i;
1066
1067         if (id != TEGRA_POWERGATE_DISA)
1068                 return;
1069         spin_lock_irqsave(&tegra_powergate_lock, flags);
1070         /* mipi cal por restore */
1071         for (i = 0; i < ARRAY_SIZE(mipi_cal_por_values); i++) {
1072                 mipi_cal_write(mipi_cal_por_values[i].por_value,
1073                         mipi_cal_por_values[i].offset);
1074         }
1075         /* mipi cal status clear */
1076         status = mipi_cal_read(MIPI_CAL_CIL_MIPI_CAL_STATUS_0);
1077         mipi_cal_write(status, MIPI_CAL_CIL_MIPI_CAL_STATUS_0);
1078         /* mipi cal status read - to flush writes */
1079         status = mipi_cal_read(MIPI_CAL_CIL_MIPI_CAL_STATUS_0);
1080         spin_unlock_irqrestore(&tegra_powergate_lock, flags);
1081         if (status)
1082                 pr_err("Error: mipi_cal calibration failed at file: %s, func: %s, line=%d\n",
1083                 __FILE__, __func__, __LINE__);
1084 }
1085 #endif
1086
1087 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1088 static bool skip_pg_check(int id, bool is_unpowergate)
1089 {
1090         /*
1091          * FIXME: need to stress test partition power gating before
1092          * enabling power gating for T11x
1093          * List of T11x partition id which skip power gating
1094          */
1095         static int skip_pg_t11x_list[] = {
1096                 /*
1097                  * CPU power gate enable/disable done
1098                  * from cpu power management code
1099                  */
1100                 TEGRA_POWERGATE_CRAIL,
1101                 TEGRA_POWERGATE_VENC,
1102                 TEGRA_POWERGATE_PCIE,
1103                 TEGRA_POWERGATE_VDEC,
1104                 TEGRA_POWERGATE_L2,
1105                 TEGRA_POWERGATE_MPE,
1106                 TEGRA_POWERGATE_HEG,
1107                 TEGRA_POWERGATE_SATA,
1108                 TEGRA_POWERGATE_CELP,
1109                 TEGRA_POWERGATE_3D1,
1110                 TEGRA_POWERGATE_C0NC,
1111                 TEGRA_POWERGATE_C1NC,
1112                 TEGRA_POWERGATE_DISA,
1113                 TEGRA_POWERGATE_DISB,
1114                 TEGRA_POWERGATE_XUSBA,
1115                 TEGRA_POWERGATE_XUSBB,
1116                 TEGRA_POWERGATE_XUSBC,
1117         };
1118         int i;
1119
1120         /*
1121          * skip unnecessary multiple calls e.g. powergate call when
1122          * partition is already powered-off or vice-versa
1123          */
1124         if ((tegra_powergate_is_powered(id) &&
1125                 is_unpowergate) ||
1126                 (!(tegra_powergate_is_powered(id)) &&
1127                 (!is_unpowergate))) {
1128                 pr_err("Partition %s already powered-%s and %spowergate skipped\n",
1129                         tegra_powergate_get_name(id),
1130                         (tegra_powergate_is_powered(id)) ?
1131                         "on" : "off",
1132                         (is_unpowergate) ? "un" : "");
1133                 return true;
1134         }
1135         /* unpowergate is allowed for all partitions */
1136         if (!tegra_powergate_is_powered(id) &&
1137                 is_unpowergate) {
1138                 pr_err("Partition %s already powered-%s unpowergating\n",
1139                         tegra_powergate_get_name(id),
1140                         (tegra_powergate_is_powered(id)) ?
1141                         "on" : "off");
1142                 return false;
1143         }
1144         for (i = 0; i < tegra_num_powerdomains; i++) {
1145                 if (id == skip_pg_t11x_list[i]) {
1146                         pr_err("Partition %s %spowergate skipped\n",
1147                                 tegra_powergate_get_name(id),
1148                                 (is_unpowergate) ? "un" : "");
1149                         return true;
1150                 }
1151         }
1152
1153         return false;
1154 }
1155 #endif
1156
1157 /*
1158  * Must be called with clk disabled, and returns with clk disabled
1159  * Drivers should enable clks for partition. Unpowergates only the
1160  * partition.
1161  */
1162 int tegra_unpowergate_partition(int id)
1163 {
1164         int ret;
1165 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1166         bool is_pg_skip;
1167
1168         is_pg_skip = skip_pg_check(id, true);
1169         if (is_pg_skip)
1170                 return 0;
1171         ret = tegra11x_check_partition_pug_seq(id);
1172         if (ret)
1173                 return ret;
1174 #endif
1175         /* If first clk_ptr is null, fill clk info for the partition */
1176         if (!powergate_partition_info[id].clk_info[0].clk_ptr)
1177                 get_clk_info(id);
1178
1179         if (tegra_powergate_is_powered(id))
1180                 return tegra_powergate_reset_module(id);
1181
1182         ret = unpowergate_module(id);
1183         if (ret)
1184                 goto err_power;
1185
1186         powergate_partition_assert_reset(id);
1187
1188         /* Un-Powergating fails if all clks are not enabled */
1189         ret = partition_clk_enable(id);
1190         if (ret)
1191                 goto err_clk_on;
1192
1193         udelay(10);
1194
1195         ret = tegra_powergate_remove_clamping(id);
1196         if (ret)
1197                 goto err_clamp;
1198
1199         udelay(10);
1200
1201 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1202         tegra11x_mipical_calibrate(id);
1203 #endif
1204         powergate_partition_deassert_reset(id);
1205
1206         mc_flush_done(id);
1207
1208         /* Disable all clks enabled earlier. Drivers should enable clks */
1209         partition_clk_disable(id);
1210
1211         return 0;
1212
1213 err_clamp:
1214         partition_clk_disable(id);
1215 err_clk_on:
1216         powergate_module(id);
1217 err_power:
1218         WARN(1, "Could not Un-Powergate %d", id);
1219         return ret;
1220 }
1221
1222 int tegra_cpu_powergate_id(int cpuid)
1223 {
1224         if (cpuid > 0 && cpuid < tegra_num_cpu_domains)
1225                 return tegra_cpu_domains[cpuid];
1226
1227         return -EINVAL;
1228 }
1229
1230 int __init tegra_powergate_init(void)
1231 {
1232         switch (tegra_chip_id) {
1233         case TEGRA20:
1234                 tegra_num_powerdomains = 7;
1235                 break;
1236         case TEGRA30:
1237                 tegra_num_powerdomains = 14;
1238                 tegra_num_cpu_domains = 4;
1239                 tegra_cpu_domains = tegra_quad_cpu_domains;
1240                 break;
1241         case TEGRA11X:
1242                 tegra_num_powerdomains = 23;
1243                 tegra_num_cpu_domains = 4;
1244                 tegra_cpu_domains = tegra_quad_cpu_domains;
1245                 break;
1246         default:
1247                 /* Unknown Tegra variant. Disable powergating */
1248                 tegra_num_powerdomains = 0;
1249                 break;
1250         }
1251
1252 #if defined(DEBUG_T11x_POWERGATE)
1253         test_powergate_parts();
1254 #endif
1255 #if defined(DEBUG_T11x_POWERUNGATE)
1256         test_unpowergate_parts();
1257 #endif
1258 #if defined(DEBUG_T11x_POWERGATE_CLK_OFF)
1259         test_powergate_clk_off_parts();
1260 #endif
1261 #if defined(DEBUG_T11x_POWERUNGATE_CLK_ON)
1262         test_unpowergate_clk_on_parts();
1263 #endif
1264         return 0;
1265 }
1266
1267 /*
1268  * Must be called with clk disabled, and returns with clk enabled
1269  * Unpowergates the partition and enables all required clks.
1270  */
1271 int tegra_unpowergate_partition_with_clk_on(int id)
1272 {
1273         int ret = 0;
1274 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1275         bool is_pg_skip;
1276
1277         is_pg_skip = skip_pg_check(id, true);
1278         if (is_pg_skip)
1279                 return 0;
1280 #endif
1281 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
1282         /* Restrict this functions use to few partitions */
1283         BUG_ON(id != TEGRA_POWERGATE_SATA && id != TEGRA_POWERGATE_PCIE);
1284 #elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
1285         /* Restrict this functions use to few partitions */
1286         BUG_ON(id != TEGRA_POWERGATE_PCIE);
1287 #endif
1288
1289         ret = tegra_unpowergate_partition(id);
1290         if (ret)
1291                 goto err_unpowergating;
1292
1293         /* Enable clks for the partition */
1294         ret = partition_clk_enable(id);
1295         if (ret)
1296                 goto err_unpowergate_clk;
1297
1298         return ret;
1299
1300 err_unpowergate_clk:
1301         tegra_powergate_partition(id);
1302         WARN(1, "Could not Un-Powergate %d, err in enabling clk", id);
1303 err_unpowergating:
1304         WARN(1, "Could not Un-Powergate %d", id);
1305         return ret;
1306 }
1307
1308 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1309 static int tegra11x_3d_powergate_set(int id, bool new_state)
1310 {
1311 #ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
1312         bool status;
1313         unsigned long flags;
1314         /* 10us timeout for toggle operation if it takes affect*/
1315         int toggle_timeout = 10;
1316         /* 100 * 10 = 1000us timeout for toggle command to take affect in case
1317            of contention with h/w initiated CPU power gating */
1318         int contention_timeout = 100;
1319
1320         spin_lock_irqsave(&tegra_powergate_lock, flags);
1321
1322         status = !!(pmc_read(PWRGATE_STATUS) & (1 << id));
1323
1324         if (status == new_state) {
1325                 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
1326                 return 0;
1327         }
1328
1329         pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
1330         do {
1331                 do {
1332                         udelay(1);
1333                         status = !!(pmc_read(PWRGATE_STATUS) & (1 << id));
1334
1335                         toggle_timeout--;
1336                 } while ((status != new_state) && (toggle_timeout > 0));
1337
1338                 contention_timeout--;
1339         } while ((status != new_state) && (contention_timeout > 0));
1340
1341         spin_unlock_irqrestore(&tegra_powergate_lock, flags);
1342
1343         if (status != new_state) {
1344                 WARN(1, "Could not set powergate %d to %d", id, new_state);
1345                 return -EBUSY;
1346         }
1347
1348         trace_power_domain_target(powergate_partition_info[id].name, new_state,
1349                         smp_processor_id());
1350 #endif
1351
1352         return 0;
1353 }
1354
1355 static int tegra11x_powergate_3d(int id)
1356 {
1357         int ret;
1358
1359         /* If first clk_ptr is null, fill clk info for the partition */
1360         if (powergate_partition_info[id].clk_info[0].clk_ptr)
1361                 get_clk_info(id);
1362
1363         ret = partition_clk_enable(id);
1364         if (ret)
1365                 WARN(1, "Couldn't enable clock");
1366
1367         udelay(10);
1368
1369         mc_flush(id);
1370
1371         udelay(10);
1372
1373         powergate_partition_assert_reset(id);
1374
1375         udelay(10);
1376
1377         /* Powergating is done only if refcnt of all clks is 0 */
1378         partition_clk_disable(id);
1379
1380         udelay(10);
1381
1382         ret = tegra11x_3d_powergate_set(id, false);
1383         if (ret)
1384                 goto err_power_off;
1385
1386         return 0;
1387
1388 err_power_off:
1389         WARN(1, "Could not Powergate Partition %d", id);
1390         return ret;
1391 }
1392
1393 static int tegra11x_unpowergate_3d(int id)
1394 {
1395         int ret;
1396         /* If first clk_ptr is null, fill clk info for the partition */
1397         if (!powergate_partition_info[id].clk_info[0].clk_ptr)
1398                 get_clk_info(id);
1399
1400         if (tegra_powergate_is_powered(id))
1401                 return tegra_powergate_reset_module(id);
1402
1403         ret = tegra11x_3d_powergate_set(id, true);
1404         if (ret)
1405                 goto err_power;
1406
1407         udelay(10);
1408
1409         /* Un-Powergating fails if all clks are not enabled */
1410         ret = partition_clk_enable(id);
1411         if (ret)
1412                 goto err_clk_on;
1413
1414         udelay(10);
1415
1416         ret = tegra_powergate_remove_clamping(id);
1417         if (ret)
1418                 goto err_clamp;
1419
1420         udelay(10);
1421
1422         powergate_partition_deassert_reset(id);
1423
1424         udelay(10);
1425
1426         mc_flush_done(id);
1427
1428         udelay(10);
1429
1430         /* Disable all clks enabled earlier. Drivers should enable clks */
1431         partition_clk_disable(id);
1432
1433         return 0;
1434
1435 err_clamp:
1436         partition_clk_disable(id);
1437 err_clk_on:
1438         powergate_module(id);
1439 err_power:
1440         WARN(1, "Could not Un-Powergate %d", id);
1441         return ret;
1442 }
1443
1444 static int tegra11x_powergate_partition(int id)
1445 {
1446         int ret;
1447
1448         if (tegra_powergate_is_powered(id)) {
1449                 ret = is_partition_clk_disabled(id);
1450                 if (ret < 0) {
1451                         /* clock enabled */
1452                         ret = tegra_powergate_partition_with_clk_off(id);
1453                         if (ret < 0)
1454                                 return ret;
1455                 } else {
1456                         ret = tegra_powergate_partition(id);
1457                         if (ret < 0)
1458                                 return ret;
1459                 }
1460         }
1461         return 0;
1462 }
1463
1464 static int tegra11x_unpowergate_partition(int id)
1465 {
1466         int ret;
1467
1468         if (!tegra_powergate_is_powered(id)) {
1469                 ret = is_partition_clk_disabled(id);
1470                 if (ret) {
1471                         /* clock disabled */
1472                         ret = tegra_unpowergate_partition_with_clk_on(id);
1473                         if (ret < 0)
1474                                 return ret;
1475                 } else {
1476                         ret = tegra_unpowergate_partition(id);
1477                         if (ret < 0)
1478                                 return ret;
1479                 }
1480         }
1481         return 0;
1482 }
1483
1484 static int tegra11x_check_partition_pg_seq(int id)
1485 {
1486         int ret;
1487
1488         switch (id) {
1489         case TEGRA_POWERGATE_DISA:
1490                 ret = tegra11x_powergate_partition(TEGRA_POWERGATE_VENC);
1491                 if (ret < 0)
1492                         return ret;
1493                 ret = tegra11x_powergate_partition(TEGRA_POWERGATE_DISB);
1494                 if (ret < 0)
1495                         return ret;
1496
1497                 break;
1498         case TEGRA_POWERGATE_3D:
1499         case TEGRA_POWERGATE_MPE:
1500                 ret = tegra11x_powergate_3d(id);
1501                 if (ret < 0)
1502                         return ret;
1503         }
1504         return 0;
1505 }
1506
1507 static int tegra11x_check_partition_pug_seq(int id)
1508 {
1509         int ret;
1510
1511         switch (id) {
1512         case TEGRA_POWERGATE_DISB:
1513         case TEGRA_POWERGATE_VENC:
1514                 ret = tegra11x_unpowergate_partition(TEGRA_POWERGATE_DISA);
1515                 if (ret < 0)
1516                         return ret;
1517
1518                 break;
1519         case TEGRA_POWERGATE_3D:
1520         case TEGRA_POWERGATE_MPE:
1521                 ret = tegra11x_unpowergate_3d(id);
1522                 if (ret < 0)
1523                         return ret;
1524         }
1525         return 0;
1526 }
1527 #endif
1528
1529 /*
1530  * Must be called with clk disabled. Powergates the partition only
1531  */
1532 int tegra_powergate_partition(int id)
1533 {
1534         int ret;
1535 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1536         bool is_pg_skip;
1537
1538         is_pg_skip = skip_pg_check(id, false);
1539         if (is_pg_skip)
1540                 return 0;
1541
1542         ret = tegra11x_check_partition_pg_seq(id);
1543         if (ret)
1544                 return ret;
1545 #endif
1546         /* If first clk_ptr is null, fill clk info for the partition */
1547         if (powergate_partition_info[id].clk_info[0].clk_ptr)
1548                 get_clk_info(id);
1549
1550         powergate_partition_assert_reset(id);
1551
1552         /* Powergating is done only if refcnt of all clks is 0 */
1553         ret = is_partition_clk_disabled(id);
1554         if (ret)
1555                 goto err_clk_off;
1556
1557         ret = powergate_module(id);
1558         if (ret)
1559                 goto err_power_off;
1560
1561         return 0;
1562
1563 err_power_off:
1564         WARN(1, "Could not Powergate Partition %d", id);
1565 err_clk_off:
1566         WARN(1, "Could not Powergate Partition %d, all clks not disabled", id);
1567         return ret;
1568 }
1569
1570 int tegra_powergate_partition_with_clk_off(int id)
1571 {
1572         int ret = 0;
1573 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1574         bool is_pg_skip;
1575
1576         is_pg_skip = skip_pg_check(id, false);
1577         if (is_pg_skip)
1578                 return 0;
1579 #endif
1580 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
1581         /* Restrict functions use to selected partitions */
1582         BUG_ON(id != TEGRA_POWERGATE_PCIE && id != TEGRA_POWERGATE_SATA);
1583 #elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
1584         /* Restrict functions use to selected partitions */
1585         BUG_ON(id != TEGRA_POWERGATE_PCIE);
1586 #endif
1587         /* Disable clks for the partition */
1588         partition_clk_disable(id);
1589
1590         ret = is_partition_clk_disabled(id);
1591         if (ret)
1592                 goto err_powergate_clk;
1593
1594         ret = tegra_powergate_partition(id);
1595         if (ret)
1596                 goto err_powergating;
1597
1598         return ret;
1599
1600 err_powergate_clk:
1601         WARN(1, "Could not Powergate Partition %d, all clks not disabled", id);
1602 err_powergating:
1603         partition_clk_enable(id);
1604         WARN(1, "Could not Powergate Partition %d", id);
1605         return ret;
1606 }
1607
1608 #if defined(DEBUG_T11x_POWERGATE)
1609 static void test_powergate_parts(void)
1610 {
1611         int i;
1612
1613         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1614                 tegra_powergate_partition(i);
1615 }
1616 #endif
1617
1618 #if defined(DEBUG_T11x_POWERUNGATE)
1619 static void test_powerungate_parts(void)
1620 {
1621         int i;
1622
1623         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1624                 tegra_unpowergate_partition(i);
1625 }
1626 #endif
1627
1628 #if defined(DEBUG_T11x_POWERGATE_CLK_OFF)
1629 static void test_powergate_clk_off_parts(void)
1630 {
1631         int i;
1632
1633         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1634                 tegra_powergate_partition_with_clk_off(i);
1635 }
1636 #endif
1637
1638 #if defined(DEBUG_T11x_POWERUNGATE_CLK_OFF)
1639 static void test_unpowergate_clk_on_parts(void)
1640 {
1641         int i;
1642
1643         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1644                 tegra_unpowergate_partition_with_clk_on(i);
1645 }
1646 #endif
1647
1648 const char *tegra_powergate_get_name(int id)
1649 {
1650         if (id < 0 || id >= TEGRA_NUM_POWERGATE)
1651                 return "invalid";
1652
1653         return powergate_partition_info[id].name;
1654 }
1655
1656 #ifdef CONFIG_DEBUG_FS
1657
1658 static int powergate_show(struct seq_file *s, void *data)
1659 {
1660         int i;
1661         const char *name;
1662
1663         seq_printf(s, " powergate powered\n");
1664         seq_printf(s, "------------------\n");
1665
1666         for (i = 0; i < tegra_num_powerdomains; i++) {
1667                 name = tegra_powergate_get_name(i);
1668                 if (name)
1669                         seq_printf(s, " %9s %7s\n", name,
1670                                 tegra_powergate_is_powered(i) ? "yes" : "no");
1671         }
1672
1673         return 0;
1674 }
1675
1676 static int powergate_open(struct inode *inode, struct file *file)
1677 {
1678         return single_open(file, powergate_show, inode->i_private);
1679 }
1680
1681 static const struct file_operations powergate_fops = {
1682         .open           = powergate_open,
1683         .read           = seq_read,
1684         .llseek         = seq_lseek,
1685         .release        = single_release,
1686 };
1687
1688 int __init tegra_powergate_debugfs_init(void)
1689 {
1690         struct dentry *d;
1691
1692         if (powergate_name) {
1693                 d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
1694                         &powergate_fops);
1695                 if (!d)
1696                         return -ENOMEM;
1697         }
1698
1699         return 0;
1700 }
1701
1702 #endif