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