ARM: tegra: power gate skip update
[linux-3.10.git] / arch / arm / mach-tegra / powergate.c
1 /*
2  * drivers/powergate/tegra-powergate.c
3  *
4  * Copyright (c) 2010 Google, Inc
5  * Copyright (C) 2011-2012 NVIDIA Corporation.
6  *
7  * Author:
8  *      Colin Cross <ccross@google.com>
9  *
10  * This software is licensed under the terms of the GNU General Public
11  * License version 2, as published by the Free Software Foundation, and
12  * may be copied, distributed, and modified under those terms.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/clk.h>
24 #include <linux/string.h>
25 #include <linux/debugfs.h>
26 #include <linux/delay.h>
27 #include <linux/err.h>
28 #include <linux/init.h>
29 #include <linux/io.h>
30 #include <linux/seq_file.h>
31 #include <linux/spinlock.h>
32 #include <linux/clk/tegra.h>
33 #include <trace/events/power.h>
34
35 #include <mach/powergate.h>
36
37 #include "clock.h"
38 #include "fuse.h"
39 #include "iomap.h"
40
41 #if defined(DEBUG_T11x_POWERGATE)
42 static void test_powergate_parts(void);
43 #endif
44 #if defined(DEBUG_T11x_POWERUNGATE)
45 static void test_powerungate_parts(void);
46 #endif
47 #if defined(DEBUG_T11x_POWERGATE_CLK_OFF)
48 static void test_powergate_clk_off_parts(void);
49 #endif
50 #if defined(DEBUG_T11x_POWERUNGATE_CLK_OFF)
51 static void test_unpowergate_clk_on_parts(void);
52 #endif
53
54 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
55 static int tegra11x_check_partition_pug_seq(int id);
56 #endif
57
58 #define PWRGATE_TOGGLE          0x30
59 #define PWRGATE_TOGGLE_START    (1 << 8)
60
61 #define REMOVE_CLAMPING         0x34
62
63 #define PWRGATE_STATUS          0x38
64
65 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
66 enum mc_client {
67         MC_CLIENT_AFI           = 0,
68         MC_CLIENT_AVPC          = 1,
69         MC_CLIENT_DC            = 2,
70         MC_CLIENT_DCB           = 3,
71         MC_CLIENT_EPP           = 4,
72         MC_CLIENT_G2            = 5,
73         MC_CLIENT_HC            = 6,
74         MC_CLIENT_HDA           = 7,
75         MC_CLIENT_ISP           = 8,
76         MC_CLIENT_MPCORE        = 9,
77         MC_CLIENT_MPCORELP      = 10,
78         MC_CLIENT_MPE           = 11,
79         MC_CLIENT_NV            = 12,
80         MC_CLIENT_NV2           = 13,
81         MC_CLIENT_PPCS          = 14,
82         MC_CLIENT_SATA          = 15,
83         MC_CLIENT_VDE           = 16,
84         MC_CLIENT_VI            = 17,
85         MC_CLIENT_LAST          = -1,
86 };
87 #elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
88 enum mc_client {
89         MC_CLIENT_AVPC          = 0,
90         MC_CLIENT_DC            = 1,
91         MC_CLIENT_DCB           = 2,
92         MC_CLIENT_EPP           = 3,
93         MC_CLIENT_G2            = 4,
94         MC_CLIENT_HC            = 5,
95         MC_CLIENT_ISP           = 6,
96         MC_CLIENT_MPCORE        = 7,
97         MC_CLIENT_MPEA          = 8,
98         MC_CLIENT_MPEB          = 9,
99         MC_CLIENT_MPEC          = 10,
100         MC_CLIENT_NV            = 11,
101         MC_CLIENT_PPCS          = 12,
102         MC_CLIENT_VDE           = 13,
103         MC_CLIENT_VI            = 14,
104         MC_CLIENT_LAST          = -1,
105         MC_CLIENT_AFI           = MC_CLIENT_LAST,
106 };
107 #else
108 /* bit positions are specific to chip */
109 enum mc_client {
110         MC_CLIENT_AVPC          = 1,
111         MC_CLIENT_DC            = 2,
112         MC_CLIENT_DCB           = 3,
113         MC_CLIENT_EPP           = 4,
114         MC_CLIENT_G2            = 5,
115         MC_CLIENT_HC            = 6,
116         MC_CLIENT_HDA           = 7,
117         MC_CLIENT_ISP           = 8,
118         MC_CLIENT_MPCORE        = 9,
119         MC_CLIENT_MPCORELP      = 10,
120         MC_CLIENT_MSENC         = 11,
121         MC_CLIENT_NV            = 12,
122         MC_CLIENT_PPCS          = 14,
123         MC_CLIENT_VDE           = 16,
124         MC_CLIENT_VI            = 17,
125         MC_CLIENT_XUSB_HOST     = 19,
126         MC_CLIENT_XUSB_DEV      = 20,
127         MC_CLIENT_EMUCIF        = 21,
128         MC_CLIENT_TSEC          = 22,
129         MC_CLIENT_LAST          = -1,
130         MC_CLIENT_AFI           = MC_CLIENT_LAST,
131         MC_CLIENT_MPE           = MC_CLIENT_LAST,
132         MC_CLIENT_NV2           = MC_CLIENT_LAST,
133         MC_CLIENT_SATA          = MC_CLIENT_LAST,
134 };
135 #endif
136
137 #define MAX_CLK_EN_NUM                  9
138
139 static int tegra_num_powerdomains;
140 static int tegra_num_cpu_domains;
141 static u8 *tegra_cpu_domains;
142 static u8 tegra_quad_cpu_domains[] = {
143         TEGRA_POWERGATE_CPU0,
144         TEGRA_POWERGATE_CPU1,
145         TEGRA_POWERGATE_CPU2,
146         TEGRA_POWERGATE_CPU3,
147 };
148
149 static DEFINE_SPINLOCK(tegra_powergate_lock);
150
151 #define MAX_HOTRESET_CLIENT_NUM         4
152
153 enum clk_type {
154         CLK_AND_RST,
155         RST_ONLY,
156         CLK_ONLY,
157 };
158
159 struct partition_clk_info {
160         const char *clk_name;
161         enum clk_type clk_type;
162         /* true if clk is only used in assert/deassert reset and not while enable-den*/
163         struct clk *clk_ptr;
164 };
165
166 struct powergate_partition {
167         const char *name;
168         enum mc_client hot_reset_clients[MAX_HOTRESET_CLIENT_NUM];
169         struct partition_clk_info clk_info[MAX_CLK_EN_NUM];
170 };
171
172 static struct powergate_partition powergate_partition_info[TEGRA_NUM_POWERGATE] = {
173         [TEGRA_POWERGATE_CPU]   = { "cpu0",     {MC_CLIENT_LAST}, },
174 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
175         [TEGRA_POWERGATE_L2]    = { "l2",       {MC_CLIENT_LAST}, },
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 and 3D partitions enable/disable
1098                  * is managed by respective modules
1099                  */
1100                 TEGRA_POWERGATE_VENC,
1101                 TEGRA_POWERGATE_VDEC,
1102                 TEGRA_POWERGATE_MPE,
1103                 TEGRA_POWERGATE_DISA,
1104                 TEGRA_POWERGATE_DISB,
1105                 TEGRA_POWERGATE_XUSBA,
1106                 TEGRA_POWERGATE_XUSBB,
1107                 TEGRA_POWERGATE_XUSBC,
1108         };
1109         int i;
1110
1111         /*
1112          * skip unnecessary multiple calls e.g. powergate call when
1113          * partition is already powered-off or vice-versa
1114          */
1115         if ((tegra_powergate_is_powered(id) &&
1116                 is_unpowergate) ||
1117                 (!(tegra_powergate_is_powered(id)) &&
1118                 (!is_unpowergate))) {
1119                 pr_err("Partition %s already powered-%s and %spowergate skipped\n",
1120                         tegra_powergate_get_name(id),
1121                         (tegra_powergate_is_powered(id)) ?
1122                         "on" : "off",
1123                         (is_unpowergate) ? "un" : "");
1124                 return true;
1125         }
1126         /* unpowergate is allowed for all partitions */
1127         if (!tegra_powergate_is_powered(id) &&
1128                 is_unpowergate)
1129                 return false;
1130         for (i = 0; i < tegra_num_powerdomains; i++) {
1131                 if (id == skip_pg_t11x_list[i]) {
1132                         pr_err("Partition %s %spowergate skipped\n",
1133                                 tegra_powergate_get_name(id),
1134                                 (is_unpowergate) ? "un" : "");
1135                         return true;
1136                 }
1137         }
1138
1139         return false;
1140 }
1141 #endif
1142
1143 /*
1144  * Must be called with clk disabled, and returns with clk disabled
1145  * Drivers should enable clks for partition. Unpowergates only the
1146  * partition.
1147  */
1148 int tegra_unpowergate_partition(int id)
1149 {
1150         int ret;
1151 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1152         bool is_pg_skip;
1153
1154         is_pg_skip = skip_pg_check(id, true);
1155         if (is_pg_skip)
1156                 return 0;
1157         ret = tegra11x_check_partition_pug_seq(id);
1158         if (ret)
1159                 return ret;
1160 #endif
1161         /* If first clk_ptr is null, fill clk info for the partition */
1162         if (!powergate_partition_info[id].clk_info[0].clk_ptr)
1163                 get_clk_info(id);
1164
1165         if (tegra_powergate_is_powered(id))
1166                 return tegra_powergate_reset_module(id);
1167
1168         ret = unpowergate_module(id);
1169         if (ret)
1170                 goto err_power;
1171
1172         powergate_partition_assert_reset(id);
1173
1174         /* Un-Powergating fails if all clks are not enabled */
1175         ret = partition_clk_enable(id);
1176         if (ret)
1177                 goto err_clk_on;
1178
1179         udelay(10);
1180
1181         ret = tegra_powergate_remove_clamping(id);
1182         if (ret)
1183                 goto err_clamp;
1184
1185         udelay(10);
1186
1187 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1188         tegra11x_mipical_calibrate(id);
1189 #endif
1190         powergate_partition_deassert_reset(id);
1191
1192         mc_flush_done(id);
1193
1194         /* Disable all clks enabled earlier. Drivers should enable clks */
1195         partition_clk_disable(id);
1196
1197         return 0;
1198
1199 err_clamp:
1200         partition_clk_disable(id);
1201 err_clk_on:
1202         powergate_module(id);
1203 err_power:
1204         WARN(1, "Could not Un-Powergate %d", id);
1205         return ret;
1206 }
1207
1208 int tegra_cpu_powergate_id(int cpuid)
1209 {
1210         if (cpuid > 0 && cpuid < tegra_num_cpu_domains)
1211                 return tegra_cpu_domains[cpuid];
1212
1213         return -EINVAL;
1214 }
1215
1216 int __init tegra_powergate_init(void)
1217 {
1218         switch (tegra_chip_id) {
1219         case TEGRA20:
1220                 tegra_num_powerdomains = 7;
1221                 break;
1222         case TEGRA30:
1223                 tegra_num_powerdomains = 14;
1224                 tegra_num_cpu_domains = 4;
1225                 tegra_cpu_domains = tegra_quad_cpu_domains;
1226                 break;
1227         case TEGRA11X:
1228                 tegra_num_powerdomains = 23;
1229                 tegra_num_cpu_domains = 4;
1230                 tegra_cpu_domains = tegra_quad_cpu_domains;
1231                 break;
1232         default:
1233                 /* Unknown Tegra variant. Disable powergating */
1234                 tegra_num_powerdomains = 0;
1235                 break;
1236         }
1237
1238 #if defined(DEBUG_T11x_POWERGATE)
1239         test_powergate_parts();
1240 #endif
1241 #if defined(DEBUG_T11x_POWERUNGATE)
1242         test_unpowergate_parts();
1243 #endif
1244 #if defined(DEBUG_T11x_POWERGATE_CLK_OFF)
1245         test_powergate_clk_off_parts();
1246 #endif
1247 #if defined(DEBUG_T11x_POWERUNGATE_CLK_ON)
1248         test_unpowergate_clk_on_parts();
1249 #endif
1250         return 0;
1251 }
1252
1253 /*
1254  * Must be called with clk disabled, and returns with clk enabled
1255  * Unpowergates the partition and enables all required clks.
1256  */
1257 int tegra_unpowergate_partition_with_clk_on(int id)
1258 {
1259         int ret = 0;
1260 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1261         bool is_pg_skip;
1262
1263         is_pg_skip = skip_pg_check(id, true);
1264         if (is_pg_skip)
1265                 return 0;
1266 #endif
1267 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
1268         /* Restrict this functions use to few partitions */
1269         BUG_ON(id != TEGRA_POWERGATE_SATA && id != TEGRA_POWERGATE_PCIE);
1270 #elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
1271         /* Restrict this functions use to few partitions */
1272         BUG_ON(id != TEGRA_POWERGATE_PCIE);
1273 #endif
1274
1275         ret = tegra_unpowergate_partition(id);
1276         if (ret)
1277                 goto err_unpowergating;
1278
1279         /* Enable clks for the partition */
1280         ret = partition_clk_enable(id);
1281         if (ret)
1282                 goto err_unpowergate_clk;
1283
1284         return ret;
1285
1286 err_unpowergate_clk:
1287         tegra_powergate_partition(id);
1288         WARN(1, "Could not Un-Powergate %d, err in enabling clk", id);
1289 err_unpowergating:
1290         WARN(1, "Could not Un-Powergate %d", id);
1291         return ret;
1292 }
1293
1294 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1295 static int tegra11x_3d_powergate_set(int id, bool new_state)
1296 {
1297 #ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
1298         bool status;
1299         unsigned long flags;
1300         /* 10us timeout for toggle operation if it takes affect*/
1301         int toggle_timeout = 10;
1302         /* 100 * 10 = 1000us timeout for toggle command to take affect in case
1303            of contention with h/w initiated CPU power gating */
1304         int contention_timeout = 100;
1305
1306         spin_lock_irqsave(&tegra_powergate_lock, flags);
1307
1308         status = !!(pmc_read(PWRGATE_STATUS) & (1 << id));
1309
1310         if (status == new_state) {
1311                 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
1312                 return 0;
1313         }
1314
1315         pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
1316         do {
1317                 do {
1318                         udelay(1);
1319                         status = !!(pmc_read(PWRGATE_STATUS) & (1 << id));
1320
1321                         toggle_timeout--;
1322                 } while ((status != new_state) && (toggle_timeout > 0));
1323
1324                 contention_timeout--;
1325         } while ((status != new_state) && (contention_timeout > 0));
1326
1327         spin_unlock_irqrestore(&tegra_powergate_lock, flags);
1328
1329         if (status != new_state) {
1330                 WARN(1, "Could not set powergate %d to %d", id, new_state);
1331                 return -EBUSY;
1332         }
1333
1334         trace_power_domain_target(powergate_partition_info[id].name, new_state,
1335                         smp_processor_id());
1336 #endif
1337
1338         return 0;
1339 }
1340
1341 static int tegra11x_powergate_3d(int id)
1342 {
1343         int ret;
1344
1345         /* If first clk_ptr is null, fill clk info for the partition */
1346         if (powergate_partition_info[id].clk_info[0].clk_ptr)
1347                 get_clk_info(id);
1348
1349         ret = partition_clk_enable(id);
1350         if (ret)
1351                 WARN(1, "Couldn't enable clock");
1352
1353         udelay(10);
1354
1355         mc_flush(id);
1356
1357         udelay(10);
1358
1359         powergate_partition_assert_reset(id);
1360
1361         udelay(10);
1362
1363         /* Powergating is done only if refcnt of all clks is 0 */
1364         partition_clk_disable(id);
1365
1366         udelay(10);
1367
1368         ret = tegra11x_3d_powergate_set(id, false);
1369         if (ret)
1370                 goto err_power_off;
1371
1372         return 0;
1373
1374 err_power_off:
1375         WARN(1, "Could not Powergate Partition %d", id);
1376         return ret;
1377 }
1378
1379 static int tegra11x_unpowergate_3d(int id)
1380 {
1381         int ret;
1382         /* If first clk_ptr is null, fill clk info for the partition */
1383         if (!powergate_partition_info[id].clk_info[0].clk_ptr)
1384                 get_clk_info(id);
1385
1386         if (tegra_powergate_is_powered(id))
1387                 return tegra_powergate_reset_module(id);
1388
1389         ret = tegra11x_3d_powergate_set(id, true);
1390         if (ret)
1391                 goto err_power;
1392
1393         udelay(10);
1394
1395         /* Un-Powergating fails if all clks are not enabled */
1396         ret = partition_clk_enable(id);
1397         if (ret)
1398                 goto err_clk_on;
1399
1400         udelay(10);
1401
1402         ret = tegra_powergate_remove_clamping(id);
1403         if (ret)
1404                 goto err_clamp;
1405
1406         udelay(10);
1407
1408         powergate_partition_deassert_reset(id);
1409
1410         udelay(10);
1411
1412         mc_flush_done(id);
1413
1414         udelay(10);
1415
1416         /* Disable all clks enabled earlier. Drivers should enable clks */
1417         partition_clk_disable(id);
1418
1419         return 0;
1420
1421 err_clamp:
1422         partition_clk_disable(id);
1423 err_clk_on:
1424         powergate_module(id);
1425 err_power:
1426         WARN(1, "Could not Un-Powergate %d", id);
1427         return ret;
1428 }
1429
1430 static int tegra11x_powergate_partition(int id)
1431 {
1432         int ret;
1433
1434         if (tegra_powergate_is_powered(id)) {
1435                 ret = is_partition_clk_disabled(id);
1436                 if (ret < 0) {
1437                         /* clock enabled */
1438                         ret = tegra_powergate_partition_with_clk_off(id);
1439                         if (ret < 0)
1440                                 return ret;
1441                 } else {
1442                         ret = tegra_powergate_partition(id);
1443                         if (ret < 0)
1444                                 return ret;
1445                 }
1446         }
1447         return 0;
1448 }
1449
1450 static int tegra11x_unpowergate_partition(int id)
1451 {
1452         int ret;
1453
1454         if (!tegra_powergate_is_powered(id)) {
1455                 ret = is_partition_clk_disabled(id);
1456                 if (ret) {
1457                         /* clock disabled */
1458                         ret = tegra_unpowergate_partition_with_clk_on(id);
1459                         if (ret < 0)
1460                                 return ret;
1461                 } else {
1462                         ret = tegra_unpowergate_partition(id);
1463                         if (ret < 0)
1464                                 return ret;
1465                 }
1466         }
1467         return 0;
1468 }
1469
1470 static int tegra11x_check_partition_pg_seq(int id)
1471 {
1472         int ret;
1473
1474         switch (id) {
1475         case TEGRA_POWERGATE_DISA:
1476                 ret = tegra11x_powergate_partition(TEGRA_POWERGATE_VENC);
1477                 if (ret < 0)
1478                         return ret;
1479                 ret = tegra11x_powergate_partition(TEGRA_POWERGATE_DISB);
1480                 if (ret < 0)
1481                         return ret;
1482
1483                 break;
1484         case TEGRA_POWERGATE_3D:
1485         case TEGRA_POWERGATE_HEG:
1486         case TEGRA_POWERGATE_MPE:
1487                 ret = tegra11x_powergate_3d(id);
1488                 if (ret < 0)
1489                         return ret;
1490         }
1491         return 0;
1492 }
1493
1494 static int tegra11x_check_partition_pug_seq(int id)
1495 {
1496         int ret;
1497
1498         switch (id) {
1499         case TEGRA_POWERGATE_DISB:
1500         case TEGRA_POWERGATE_VENC:
1501                 ret = tegra11x_unpowergate_partition(TEGRA_POWERGATE_DISA);
1502                 if (ret < 0)
1503                         return ret;
1504
1505                 break;
1506         case TEGRA_POWERGATE_3D:
1507         case TEGRA_POWERGATE_HEG:
1508         case TEGRA_POWERGATE_MPE:
1509                 ret = tegra11x_unpowergate_3d(id);
1510                 if (ret < 0)
1511                         return ret;
1512         }
1513         return 0;
1514 }
1515 #endif
1516
1517 /*
1518  * Must be called with clk disabled. Powergates the partition only
1519  */
1520 int tegra_powergate_partition(int id)
1521 {
1522         int ret;
1523 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1524         bool is_pg_skip;
1525
1526         is_pg_skip = skip_pg_check(id, false);
1527         if (is_pg_skip)
1528                 return 0;
1529
1530         ret = tegra11x_check_partition_pg_seq(id);
1531         if (ret)
1532                 return ret;
1533 #endif
1534         /* If first clk_ptr is null, fill clk info for the partition */
1535         if (powergate_partition_info[id].clk_info[0].clk_ptr)
1536                 get_clk_info(id);
1537
1538         powergate_partition_assert_reset(id);
1539
1540         /* Powergating is done only if refcnt of all clks is 0 */
1541         ret = is_partition_clk_disabled(id);
1542         if (ret)
1543                 goto err_clk_off;
1544
1545         ret = powergate_module(id);
1546         if (ret)
1547                 goto err_power_off;
1548
1549         return 0;
1550
1551 err_power_off:
1552         WARN(1, "Could not Powergate Partition %d", id);
1553 err_clk_off:
1554         WARN(1, "Could not Powergate Partition %d, all clks not disabled", id);
1555         return ret;
1556 }
1557
1558 int tegra_powergate_partition_with_clk_off(int id)
1559 {
1560         int ret = 0;
1561 #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) && !defined(CONFIG_ARCH_TEGRA_3x_SOC)
1562         bool is_pg_skip;
1563
1564         is_pg_skip = skip_pg_check(id, false);
1565         if (is_pg_skip)
1566                 return 0;
1567 #endif
1568 #if defined(CONFIG_ARCH_TEGRA_3x_SOC)
1569         /* Restrict functions use to selected partitions */
1570         BUG_ON(id != TEGRA_POWERGATE_PCIE && id != TEGRA_POWERGATE_SATA);
1571 #elif defined(CONFIG_ARCH_TEGRA_2x_SOC)
1572         /* Restrict functions use to selected partitions */
1573         BUG_ON(id != TEGRA_POWERGATE_PCIE);
1574 #endif
1575         /* Disable clks for the partition */
1576         partition_clk_disable(id);
1577
1578         ret = is_partition_clk_disabled(id);
1579         if (ret)
1580                 goto err_powergate_clk;
1581
1582         ret = tegra_powergate_partition(id);
1583         if (ret)
1584                 goto err_powergating;
1585
1586         return ret;
1587
1588 err_powergate_clk:
1589         WARN(1, "Could not Powergate Partition %d, all clks not disabled", id);
1590 err_powergating:
1591         partition_clk_enable(id);
1592         WARN(1, "Could not Powergate Partition %d", id);
1593         return ret;
1594 }
1595
1596 #if defined(DEBUG_T11x_POWERGATE)
1597 static void test_powergate_parts(void)
1598 {
1599         int i;
1600
1601         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1602                 tegra_powergate_partition(i);
1603 }
1604 #endif
1605
1606 #if defined(DEBUG_T11x_POWERUNGATE)
1607 static void test_powerungate_parts(void)
1608 {
1609         int i;
1610
1611         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1612                 tegra_unpowergate_partition(i);
1613 }
1614 #endif
1615
1616 #if defined(DEBUG_T11x_POWERGATE_CLK_OFF)
1617 static void test_powergate_clk_off_parts(void)
1618 {
1619         int i;
1620
1621         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1622                 tegra_powergate_partition_with_clk_off(i);
1623 }
1624 #endif
1625
1626 #if defined(DEBUG_T11x_POWERUNGATE_CLK_OFF)
1627 static void test_unpowergate_clk_on_parts(void)
1628 {
1629         int i;
1630
1631         for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
1632                 tegra_unpowergate_partition_with_clk_on(i);
1633 }
1634 #endif
1635
1636 const char *tegra_powergate_get_name(int id)
1637 {
1638         if (id < 0 || id >= TEGRA_NUM_POWERGATE)
1639                 return "invalid";
1640
1641         return powergate_partition_info[id].name;
1642 }
1643
1644 #ifdef CONFIG_DEBUG_FS
1645
1646 static int powergate_show(struct seq_file *s, void *data)
1647 {
1648         int i;
1649         const char *name;
1650
1651         seq_printf(s, " powergate powered\n");
1652         seq_printf(s, "------------------\n");
1653
1654         for (i = 0; i < tegra_num_powerdomains; i++) {
1655                 name = tegra_powergate_get_name(i);
1656                 if (name)
1657                         seq_printf(s, " %9s %7s\n", name,
1658                                 tegra_powergate_is_powered(i) ? "yes" : "no");
1659         }
1660
1661         return 0;
1662 }
1663
1664 static int powergate_open(struct inode *inode, struct file *file)
1665 {
1666         return single_open(file, powergate_show, inode->i_private);
1667 }
1668
1669 static const struct file_operations powergate_fops = {
1670         .open           = powergate_open,
1671         .read           = seq_read,
1672         .llseek         = seq_lseek,
1673         .release        = single_release,
1674 };
1675
1676 int __init tegra_powergate_debugfs_init(void)
1677 {
1678         struct dentry *d;
1679
1680         if (powergate_name) {
1681                 d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
1682                         &powergate_fops);
1683                 if (!d)
1684                         return -ENOMEM;
1685         }
1686
1687         return 0;
1688 }
1689
1690 #endif