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