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