ARM: tegra: mc: Add config for MC flushing delay
[linux-3.10.git] / arch / arm / mach-tegra / powergate-t14x.c
1 /*
2  * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  */
14
15 #include <linux/spinlock.h>
16 #include <linux/delay.h>
17
18 #include <asm/atomic.h>
19
20 #include <mach/powergate.h>
21
22 #include "powergate-priv.h"
23 #include "powergate-ops-txx.h"
24 #include "powergate-ops-t1xx.h"
25
26 enum mc_client {
27         MC_CLIENT_AVPC          = 1,
28         MC_CLIENT_DC            = 2,
29         MC_CLIENT_DCB           = 3,
30         MC_CLIENT_EPP           = 4,
31         MC_CLIENT_G2            = 5,
32         MC_CLIENT_HC            = 6,
33         MC_CLIENT_HDA           = 7,
34         MC_CLIENT_ISP           = 8,
35         MC_CLIENT_MPCORE        = 9,
36         MC_CLIENT_MPCORELP      = 10,
37         MC_CLIENT_MSENC         = 11,
38         MC_CLIENT_NV            = 12,
39         MC_CLIENT_PPCS          = 14,
40         MC_CLIENT_VDE           = 16,
41         MC_CLIENT_VI            = 17,
42         MC_CLIENT_EMUCIF        = 21,
43         MC_CLIENT_TSEC          = 22,
44         MC_CLIENT_LAST          = -1,
45         MC_CLIENT_AFI           = MC_CLIENT_LAST,
46         MC_CLIENT_MPE           = MC_CLIENT_LAST,
47         MC_CLIENT_NV2           = MC_CLIENT_LAST,
48         MC_CLIENT_SATA          = MC_CLIENT_LAST,
49 };
50
51 struct tegra14x_powergate_mc_client_info {
52         enum mc_client hot_reset_clients[MAX_HOTRESET_CLIENT_NUM];
53 };
54
55 static struct tegra14x_powergate_mc_client_info
56         tegra14x_pg_mc_info[TEGRA_NUM_POWERGATE] = {
57         [TEGRA_POWERGATE_CRAIL] = {
58                 .hot_reset_clients = {
59                         [0] = MC_CLIENT_LAST,
60                 },
61         },
62         [TEGRA_POWERGATE_3D] = {
63                 .hot_reset_clients = {
64                         [0] = MC_CLIENT_NV,
65                         [1] = MC_CLIENT_LAST,
66                 },
67         },
68         [TEGRA_POWERGATE_VDEC] = {
69                 .hot_reset_clients = {
70                         [0] = MC_CLIENT_VDE,
71                         [1] = MC_CLIENT_LAST,
72                 },
73         },
74         [TEGRA_POWERGATE_MPE] = {
75                 .hot_reset_clients = {
76                         [0] = MC_CLIENT_MSENC,
77                         [1] = MC_CLIENT_LAST,
78                 },
79         },
80         [TEGRA_POWERGATE_VENC] = {
81                 .hot_reset_clients = {
82                         [0] = MC_CLIENT_ISP,
83                         [1] = MC_CLIENT_VI,
84                         [2] = MC_CLIENT_LAST,
85                 },
86         },
87         [TEGRA_POWERGATE_HEG] = {
88                 .hot_reset_clients = {
89                         [0] = MC_CLIENT_G2,
90                         [1] = MC_CLIENT_EPP,
91                         [2] = MC_CLIENT_LAST,
92                 },
93         },
94         [TEGRA_POWERGATE_CPU1] = {
95                 .hot_reset_clients = {
96                         [0] = MC_CLIENT_LAST,
97                 },
98         },
99         [TEGRA_POWERGATE_CPU2] = {
100                 .hot_reset_clients = {
101                         [0] = MC_CLIENT_LAST,
102                 },
103         },
104         [TEGRA_POWERGATE_CPU3] = {
105                 .hot_reset_clients = {
106                         [0] = MC_CLIENT_LAST,
107                 },
108         },
109         [TEGRA_POWERGATE_CELP] = {
110                 .hot_reset_clients = {
111                         [0] = MC_CLIENT_LAST,
112                 },
113         },
114         [TEGRA_POWERGATE_CPU0] = {
115                 .hot_reset_clients = {
116                         [0] = MC_CLIENT_LAST,
117                 },
118         },
119         [TEGRA_POWERGATE_C0NC] = {
120                 .hot_reset_clients = {
121                         [0] = MC_CLIENT_LAST,
122                 },
123         },
124         [TEGRA_POWERGATE_C1NC] = {
125                 .hot_reset_clients = {
126                         [0] = MC_CLIENT_LAST,
127                 },
128         },
129         [TEGRA_POWERGATE_DISA] = {
130                 .hot_reset_clients = {
131                         [0] = MC_CLIENT_DC,
132                         [1] = MC_CLIENT_LAST,
133                 },
134         },
135         [TEGRA_POWERGATE_DISB] = {
136                 .hot_reset_clients = {
137                         [0] = MC_CLIENT_DCB,
138                         [1] = MC_CLIENT_LAST,
139                 },
140         },
141 };
142
143 static struct powergate_partition_info
144         tegra14x_powergate_partition_info[TEGRA_NUM_POWERGATE] = {
145         [TEGRA_POWERGATE_CRAIL] = { .name = "crail" },
146         [TEGRA_POWERGATE_3D] = {
147                 .name = "3d",
148                 .clk_info = {
149                         [0] = { .clk_name = "3d", .clk_type = CLK_AND_RST },
150                 },
151         },
152         [TEGRA_POWERGATE_VDEC] = {
153                 .name = "vde",
154                 .clk_info = {
155                         [0] = { .clk_name = "vde", .clk_type = CLK_AND_RST },
156                 },
157         },
158         [TEGRA_POWERGATE_MPE] = {
159                 .name = "mpe",
160                 .clk_info = {
161                         [0] = { .clk_name = "msenc.cbus",
162                                 .clk_type = CLK_AND_RST },
163                 },
164         },
165         [TEGRA_POWERGATE_VENC] = {
166                 .name = "ve",
167                 .clk_info = {
168                         [0] = { .clk_name = "isp", .clk_type = CLK_AND_RST },
169                         [1] = { .clk_name = "vi", .clk_type = CLK_AND_RST },
170                         [2] = { .clk_name = "csi", .clk_type = CLK_AND_RST },
171                 },
172         },
173         [TEGRA_POWERGATE_HEG] = {
174                 .name = "heg",
175                 .clk_info = {
176                         [0] = { .clk_name = "2d.cbus",
177                                 .clk_type = CLK_AND_RST },
178                         [1] = { .clk_name = "epp.cbus",
179                                 .clk_type = CLK_AND_RST },
180                 },
181         },
182         [TEGRA_POWERGATE_CPU1] = { .name = "cpu1" },
183         [TEGRA_POWERGATE_CPU2] = { .name = "cpu2" },
184         [TEGRA_POWERGATE_CPU3] = { .name = "cpu3" },
185         [TEGRA_POWERGATE_CELP] = { .name = "celp" },
186         [TEGRA_POWERGATE_CPU0] = { .name = "cpu0" },
187         [TEGRA_POWERGATE_C0NC] = { .name = "c0nc" },
188         [TEGRA_POWERGATE_C1NC] = { .name = "c1nc" },
189         [TEGRA_POWERGATE_DISA] = {
190                 .name = "disa",
191                 .clk_info = {
192                         [0] = { .clk_name = "disp1", .clk_type = CLK_AND_RST },
193                         [1] = { .clk_name = "dsia", .clk_type = CLK_AND_RST },
194                         [2] = { .clk_name = "dsib", .clk_type = CLK_AND_RST },
195                         [3] = { .clk_name = "csi", .clk_type = CLK_AND_RST },
196                         [4] = { .clk_name = "mipi-cal",
197                                 .clk_type = CLK_AND_RST },
198                 },
199         },
200         [TEGRA_POWERGATE_DISB] = {
201                 .name = "disb",
202                 .clk_info = {
203                         [0] = { .clk_name = "disp2", .clk_type = CLK_AND_RST },
204                         [1] = { .clk_name = "hdmi", .clk_type = CLK_AND_RST },
205                 },
206         },
207 };
208
209 static atomic_t ref_count_a = ATOMIC_INIT(1); /* for TEGRA_POWERGATE_DISA */
210 static atomic_t ref_count_b = ATOMIC_INIT(1); /* for TEGRA_POWERGATE_DISB */
211
212 static void __iomem *mipi_cal = IO_ADDRESS(TEGRA_MIPI_CAL_BASE);
213 static u32 mipi_cal_read(unsigned long reg)
214 {
215         return readl(mipi_cal + reg);
216 }
217
218 static void mipi_cal_write(u32 val, unsigned long reg)
219 {
220         writel_relaxed(val, mipi_cal + reg);
221 }
222
223 #define MC_CLIENT_HOTRESET_CTRL         0x200
224 #define MC_CLIENT_HOTRESET_STAT         0x204
225
226 static DEFINE_SPINLOCK(tegra14x_powergate_lock);
227
228 /* Forward Declarations */
229 static int tegra14x_powergate_mc_flush(int id);
230 static int tegra14x_powergate_mc_flush_done(int id);
231 static int tegra14x_unpowergate_partition_with_clk_on(int id);
232 static int tegra14x_powergate_partition_with_clk_off(int id);
233
234 #define HOTRESET_READ_COUNT     5
235 static bool tegra14x_stable_hotreset_check(u32 *stat)
236 {
237         int i;
238         u32 cur_stat;
239         u32 prv_stat;
240         unsigned long flags;
241
242         spin_lock_irqsave(&tegra14x_powergate_lock, flags);
243         prv_stat = mc_read(MC_CLIENT_HOTRESET_STAT);
244         for (i = 0; i < HOTRESET_READ_COUNT; i++) {
245                 cur_stat = mc_read(MC_CLIENT_HOTRESET_STAT);
246                 if (cur_stat != prv_stat) {
247                         spin_unlock_irqrestore(&tegra14x_powergate_lock, flags);
248                         return false;
249                 }
250         }
251         *stat = cur_stat;
252         spin_unlock_irqrestore(&tegra14x_powergate_lock, flags);
253         return true;
254 }
255
256 /*
257  * FIXME: sw war for mipi-cal calibration when unpowergating DISA partition
258  */
259 static void tegra14x_mipical_calibrate(int id)
260 {
261         struct reg_offset_val {
262                 u32 offset;
263                 u32 por_value;
264         };
265         u32 status;
266         unsigned long flags;
267
268 #define MIPI_CAL_MIPI_CAL_CTRL_0                0x0
269 #define MIPI_CAL_CIL_MIPI_CAL_STATUS_0          0x8
270 #define MIPI_CAL_CILA_MIPI_CAL_CONFIG_0         0x14
271 #define MIPI_CAL_CILB_MIPI_CAL_CONFIG_0         0x18
272 #define MIPI_CAL_CILC_MIPI_CAL_CONFIG_0         0x1c
273 #define MIPI_CAL_CILD_MIPI_CAL_CONFIG_0         0x20
274 #define MIPI_CAL_CILE_MIPI_CAL_CONFIG_0         0x24
275 #define MIPI_CAL_DSIA_MIPI_CAL_CONFIG_0         0x38
276 #define MIPI_CAL_DSIB_MIPI_CAL_CONFIG_0         0x3c
277 #define MIPI_CAL_DSIC_MIPI_CAL_CONFIG_0         0x40
278 #define MIPI_CAL_DSID_MIPI_CAL_CONFIG_0         0x44
279
280         static struct reg_offset_val mipi_cal_por_values[] = {
281                 { MIPI_CAL_MIPI_CAL_CTRL_0, 0x2a000000 },
282                 { MIPI_CAL_CILA_MIPI_CAL_CONFIG_0, 0x00200000 },
283                 { MIPI_CAL_CILB_MIPI_CAL_CONFIG_0, 0x00200000 },
284                 { MIPI_CAL_CILC_MIPI_CAL_CONFIG_0, 0x00200000 },
285                 { MIPI_CAL_CILD_MIPI_CAL_CONFIG_0, 0x00200000 },
286                 { MIPI_CAL_CILE_MIPI_CAL_CONFIG_0, 0x00000000 },
287                 { MIPI_CAL_DSIA_MIPI_CAL_CONFIG_0, 0x00200000 },
288                 { MIPI_CAL_DSIB_MIPI_CAL_CONFIG_0, 0x00200000 },
289                 { MIPI_CAL_DSIC_MIPI_CAL_CONFIG_0, 0x00200000 },
290                 { MIPI_CAL_DSID_MIPI_CAL_CONFIG_0, 0x00200000 },
291         };
292         int i;
293
294         if (id != TEGRA_POWERGATE_DISA)
295                 return;
296
297         spin_lock_irqsave(&tegra14x_powergate_lock, flags);
298
299         /* mipi cal por restore */
300         for (i = 0; i < ARRAY_SIZE(mipi_cal_por_values); i++) {
301                 mipi_cal_write(mipi_cal_por_values[i].por_value,
302                         mipi_cal_por_values[i].offset);
303         }
304
305         /* mipi cal status clear */
306         status = mipi_cal_read(MIPI_CAL_CIL_MIPI_CAL_STATUS_0);
307         mipi_cal_write(status, MIPI_CAL_CIL_MIPI_CAL_STATUS_0);
308
309         /* mipi cal status read - to flush writes */
310         status = mipi_cal_read(MIPI_CAL_CIL_MIPI_CAL_STATUS_0);
311
312         spin_unlock_irqrestore(&tegra14x_powergate_lock, flags);
313 }
314
315 static int tegra14x_powergate_partition_internal(int id,
316         struct powergate_partition_info *pg_info)
317 {
318         int ret;
319
320         if (tegra_powergate_is_powered(id)) {
321                 ret = is_partition_clk_disabled(pg_info);
322                 if (ret < 0) {
323                         /* clock enabled */
324                         ret = tegra14x_powergate_partition_with_clk_off(id);
325                         if (ret < 0)
326                                 return ret;
327                 } else {
328                         ret = tegra_powergate_partition(id);
329                         if (ret < 0)
330                                 return ret;
331                 }
332         }
333         return 0;
334 }
335
336 static int tegra14x_unpowergate_partition_internal(int id,
337         struct powergate_partition_info *pg_info)
338 {
339         int ret;
340
341         if (!tegra_powergate_is_powered(id)) {
342                 ret = is_partition_clk_disabled(pg_info);
343                 if (ret) {
344                         /* clock disabled */
345                         ret = tegra14x_unpowergate_partition_with_clk_on(id);
346                         if (ret < 0)
347                                 return ret;
348                 } else {
349                         ret = tegra_unpowergate_partition(id);
350                         if (ret < 0)
351                                 return ret;
352                 }
353         }
354         return 0;
355 }
356
357 /*
358  * Tegra14x has powergate dependencies between partitions.
359  * This function captures the dependencies.
360  */
361 static int tegra14x_check_partition_pg_seq(int id,
362         struct powergate_partition_info *pg_info)
363 {
364         int ret;
365
366         if (id == TEGRA_POWERGATE_DISA) {
367                 ret = tegra14x_powergate_partition_internal(
368                                 TEGRA_POWERGATE_VENC, pg_info);
369                 if (ret < 0)
370                         return ret;
371
372                 ret = tegra14x_powergate_partition_internal(
373                                 TEGRA_POWERGATE_DISB, pg_info);
374                 if (ret < 0)
375                         return ret;
376         }
377
378         return 0;
379 }
380
381 /*
382  * This function captures power-ungate dependencies between tegra14x partitions
383  */
384 static int tegra14x_check_partition_pug_seq(int id,
385         struct powergate_partition_info *pg_info)
386 {
387         int ret;
388
389         switch (id) {
390         case TEGRA_POWERGATE_DISB:
391         case TEGRA_POWERGATE_VENC:
392                 ret = tegra14x_unpowergate_partition_internal(
393                                 TEGRA_POWERGATE_DISA, pg_info);
394                 if (ret < 0)
395                         return ret;
396
397                 break;
398         }
399         return 0;
400 }
401
402 int tegra14x_powergate_mc_enable(int id)
403 {
404         return 0;
405 }
406
407 int tegra14x_powergate_mc_disable(int id)
408 {
409         return 0;
410 }
411
412 int tegra14x_powergate_mc_flush(int id)
413 {
414         u32 idx, rst_ctrl, rst_stat;
415         enum mc_client mcClientBit;
416         unsigned long flags;
417         bool ret;
418
419         for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
420                 mcClientBit =
421                         tegra14x_pg_mc_info[id].hot_reset_clients[idx];
422                 if (mcClientBit == MC_CLIENT_LAST)
423                         break;
424
425                 spin_lock_irqsave(&tegra14x_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(&tegra14x_powergate_lock, flags);
431
432                 do {
433 #ifdef CONFIG_TEGRA_ERRATA_1213083
434                         udelay(10);
435 #endif
436                         rst_stat = 0;
437                         ret = tegra14x_stable_hotreset_check(&rst_stat);
438                         if (!ret)
439                                 continue;
440                 } while (!(rst_stat & (1 << mcClientBit)));
441         }
442
443         return 0;
444 }
445
446 int tegra14x_powergate_mc_flush_done(int id)
447 {
448         u32 idx, rst_ctrl;
449         enum mc_client mcClientBit;
450         unsigned long flags;
451
452         for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
453                 mcClientBit =
454                         tegra14x_pg_mc_info[id].hot_reset_clients[idx];
455                 if (mcClientBit == MC_CLIENT_LAST)
456                         break;
457
458                 spin_lock_irqsave(&tegra14x_powergate_lock, flags);
459
460                 rst_ctrl = mc_read(MC_CLIENT_HOTRESET_CTRL);
461                 rst_ctrl &= ~(1 << mcClientBit);
462                 mc_write(rst_ctrl, MC_CLIENT_HOTRESET_CTRL);
463
464                 spin_unlock_irqrestore(&tegra14x_powergate_lock, flags);
465         }
466
467         wmb();
468
469         return 0;
470 }
471
472 static int tegra14x_unpowergate(int id,
473         struct powergate_partition_info *pg_info)
474 {
475         int ret;
476
477         /* If first clk_ptr is null, fill clk info for the partition */
478         if (!pg_info->clk_info[0].clk_ptr)
479                 get_clk_info(pg_info);
480
481         if (tegra_powergate_is_powered(id))
482                 return tegra_powergate_reset_module(pg_info);
483
484         ret = tegra_powergate_set(id, true);
485         if (ret)
486                 goto err_power;
487
488         udelay(10);
489
490         /* Un-Powergating fails if all clks are not enabled */
491         ret = partition_clk_enable(pg_info);
492         if (ret)
493                 goto err_clk_on;
494
495         udelay(10);
496
497         ret = tegra_powergate_remove_clamping(id);
498         if (ret)
499                 goto err_clamp;
500
501         udelay(10);
502
503         tegra14x_mipical_calibrate(id);
504
505         powergate_partition_deassert_reset(pg_info);
506
507         udelay(10);
508
509         tegra_powergate_mc_flush_done(id);
510
511         udelay(10);
512
513         /* Disable all clks enabled earlier. Drivers should enable clks */
514         partition_clk_disable(pg_info);
515
516         return 0;
517
518 err_clamp:
519         partition_clk_disable(pg_info);
520 err_clk_on:
521         powergate_module(id);
522 err_power:
523         WARN(1, "Could not Un-Powergate %d", id);
524         return ret;
525 }
526
527 void tegra14x_powergate_dis_partition(void)
528 {
529         tegra1xx_powergate(TEGRA_POWERGATE_DISB,
530                 &tegra14x_powergate_partition_info[TEGRA_POWERGATE_DISB]);
531
532         tegra14x_powergate_partition_internal(TEGRA_POWERGATE_VENC,
533                 &tegra14x_powergate_partition_info[TEGRA_POWERGATE_DISA]);
534
535         tegra1xx_powergate(TEGRA_POWERGATE_DISA,
536                 &tegra14x_powergate_partition_info[TEGRA_POWERGATE_DISA]);
537 }
538
539 /* The logic manages the ref-count for dis partitions. The dependency between
540  * disa and disb is hided from client. */
541 bool tegra14x_powergate_check_dis_refcount(int id, int op)
542 {
543         WARN_ONCE(atomic_read(&ref_count_a), "dis ref a count underflow");
544         WARN_ONCE(atomic_read(&ref_count_b), "dis ref b count underflow");
545
546         if (op && id == TEGRA_POWERGATE_DISA) {
547                 if (atomic_inc_return(&ref_count_a) != 1)
548                         return 0;
549         } else if (op && id == TEGRA_POWERGATE_DISB) {
550                 if (tegra_powergate_is_powered(TEGRA_POWERGATE_DISA))
551                         atomic_inc(&ref_count_a);
552                 if (atomic_inc_return(&ref_count_b) != 1)
553                         return 0;
554         } else if (!op && id == TEGRA_POWERGATE_DISA) {
555                 if (atomic_dec_return(&ref_count_a) != 0)
556                         return 0;
557         } else if (!op && id == TEGRA_POWERGATE_DISB) {
558                 atomic_dec(&ref_count_a);
559                 if (atomic_dec_return(&ref_count_b) != 0) {
560                         return 0;
561                 } else if (atomic_read(&ref_count_a) == 0) {
562                         tegra14x_powergate_dis_partition();
563                         return 0;
564                 }
565         }
566
567         return 1;
568 }
569
570 int tegra14x_powergate_partition(int id)
571 {
572         int ret;
573
574         if ((id == TEGRA_POWERGATE_DISA || id == TEGRA_POWERGATE_DISB) &&
575                         !tegra14x_powergate_check_dis_refcount(id, 0))
576                 return 0;
577
578         ret = tegra14x_check_partition_pg_seq(id,
579                 &tegra14x_powergate_partition_info[id]);
580         if (ret)
581                 return ret;
582
583         /* call common power-gate API for t1xx */
584         ret = tegra1xx_powergate(id,
585                 &tegra14x_powergate_partition_info[id]);
586
587         return ret;
588 }
589
590 int tegra14x_unpowergate_partition(int id)
591 {
592         int ret;
593
594         if ((id == TEGRA_POWERGATE_DISA || id == TEGRA_POWERGATE_DISB) &&
595                         !tegra14x_powergate_check_dis_refcount(id, 1))
596                 return 0;
597
598         ret = tegra14x_check_partition_pug_seq(id,
599                 &tegra14x_powergate_partition_info[id]);
600         if (ret)
601                 return ret;
602
603         /* t14x needs to calibrate mipi in un-power-gate sequence
604          * hence it cannot use common un-power-gate api tegra1xx_unpowergate */
605         ret = tegra14x_unpowergate(id,
606                 &tegra14x_powergate_partition_info[id]);
607
608         return ret;
609 }
610
611 int tegra14x_powergate_partition_with_clk_off(int id)
612 {
613         return tegraxx_powergate_partition_with_clk_off(id,
614                 &tegra14x_powergate_partition_info[id]);
615 }
616
617 int tegra14x_unpowergate_partition_with_clk_on(int id)
618 {
619         return tegraxx_unpowergate_partition_with_clk_on(id,
620                 &tegra14x_powergate_partition_info[id]);
621 }
622
623 const char *tegra14x_get_powergate_domain_name(int id)
624 {
625         return tegra14x_powergate_partition_info[id].name;
626 }
627
628 spinlock_t *tegra14x_get_powergate_lock(void)
629 {
630         return &tegra14x_powergate_lock;
631 }
632
633 int tegra14x_powergate_init_refcount(void)
634 {
635         if (tegra_powergate_is_powered(TEGRA_POWERGATE_DISA))
636                         atomic_set(&ref_count_a, 1);
637         else
638                         atomic_set(&ref_count_a, 0);
639
640         if (tegra_powergate_is_powered(TEGRA_POWERGATE_DISB))
641                         atomic_set(&ref_count_b, 1);
642         else
643                         atomic_set(&ref_count_b, 0);
644         return 0;
645 }
646
647 static struct powergate_ops tegra14x_powergate_ops = {
648         .soc_name = "tegra14x",
649
650         .num_powerdomains = TEGRA_NUM_POWERGATE,
651
652         .get_powergate_lock = tegra14x_get_powergate_lock,
653         .get_powergate_domain_name = tegra14x_get_powergate_domain_name,
654
655         .powergate_partition = tegra14x_powergate_partition,
656         .unpowergate_partition = tegra14x_unpowergate_partition,
657
658         .powergate_partition_with_clk_off =
659                 tegra14x_powergate_partition_with_clk_off,
660         .unpowergate_partition_with_clk_on =
661                 tegra14x_unpowergate_partition_with_clk_on,
662
663         .powergate_mc_enable = tegra14x_powergate_mc_enable,
664         .powergate_mc_disable = tegra14x_powergate_mc_disable,
665
666         .powergate_mc_flush = tegra14x_powergate_mc_flush,
667         .powergate_mc_flush_done = tegra14x_powergate_mc_flush_done,
668
669         .powergate_init_refcount = tegra14x_powergate_init_refcount,
670 };
671
672 struct powergate_ops *tegra14x_powergate_init_chip_support(void)
673 {
674         return &tegra14x_powergate_ops;
675 }