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