2 * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
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.
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.
15 #include <linux/spinlock.h>
16 #include <linux/delay.h>
17 #include <linux/regulator/consumer.h>
18 #include <linux/tegra-powergate.h>
20 #include <asm/atomic.h>
22 #include "powergate-priv.h"
23 #include "powergate-ops-txx.h"
24 #include "powergate-ops-t1xx.h"
37 MC_CLIENT_XUSB_HOST = 19,
38 MC_CLIENT_XUSB_DEV = 20,
44 struct tegra12x_powergate_mc_client_info {
45 enum mc_client hot_reset_clients[MAX_HOTRESET_CLIENT_NUM];
48 static struct tegra12x_powergate_mc_client_info tegra12x_pg_mc_info[] = {
49 [TEGRA_POWERGATE_CRAIL] = {
50 .hot_reset_clients = {
54 [TEGRA_POWERGATE_GPU] = {
55 .hot_reset_clients = {
60 [TEGRA_POWERGATE_VDEC] = {
61 .hot_reset_clients = {
66 [TEGRA_POWERGATE_MPE] = {
67 .hot_reset_clients = {
68 [0] = MC_CLIENT_MSENC,
72 [TEGRA_POWERGATE_VENC] = {
73 .hot_reset_clients = {
80 [TEGRA_POWERGATE_CPU1] = {
81 .hot_reset_clients = {
85 [TEGRA_POWERGATE_CPU2] = {
86 .hot_reset_clients = {
90 [TEGRA_POWERGATE_CPU3] = {
91 .hot_reset_clients = {
95 [TEGRA_POWERGATE_CELP] = {
96 .hot_reset_clients = {
100 [TEGRA_POWERGATE_CPU0] = {
101 .hot_reset_clients = {
102 [0] = MC_CLIENT_LAST,
105 [TEGRA_POWERGATE_C0NC] = {
106 .hot_reset_clients = {
107 [0] = MC_CLIENT_LAST,
110 [TEGRA_POWERGATE_C1NC] = {
111 .hot_reset_clients = {
112 [0] = MC_CLIENT_LAST,
115 [TEGRA_POWERGATE_DISA] = {
116 .hot_reset_clients = {
118 [1] = MC_CLIENT_LAST,
121 [TEGRA_POWERGATE_DISB] = {
122 .hot_reset_clients = {
124 [1] = MC_CLIENT_LAST,
127 [TEGRA_POWERGATE_XUSBA] = {
128 .hot_reset_clients = {
129 [0] = MC_CLIENT_LAST,
132 [TEGRA_POWERGATE_XUSBB] = {
133 .hot_reset_clients = {
134 [0] = MC_CLIENT_XUSB_DEV,
138 [TEGRA_POWERGATE_XUSBC] = {
139 .hot_reset_clients = {
140 [0] = MC_CLIENT_XUSB_HOST,
141 [1] = MC_CLIENT_LAST,
144 #ifdef CONFIG_ARCH_TEGRA_HAS_PCIE
145 [TEGRA_POWERGATE_PCIE] = {
146 .hot_reset_clients = {
148 [1] = MC_CLIENT_LAST,
152 #ifdef CONFIG_ARCH_TEGRA_HAS_SATA
153 [TEGRA_POWERGATE_SATA] = {
154 .hot_reset_clients = {
155 [0] = MC_CLIENT_SATA,
156 [1] = MC_CLIENT_LAST,
160 [TEGRA_POWERGATE_SOR] = {
161 .hot_reset_clients = {
162 [0] = MC_CLIENT_LAST,
165 #ifdef CONFIG_ARCH_TEGRA_VIC
166 [TEGRA_POWERGATE_VIC] = {
167 .hot_reset_clients = {
169 [1] = MC_CLIENT_LAST,
175 static struct powergate_partition_info tegra12x_powergate_partition_info[] = {
176 [TEGRA_POWERGATE_CRAIL] = { .name = "crail" },
177 [TEGRA_POWERGATE_GPU] = {
180 [0] = { .clk_name = "gpu_ref", .clk_type = CLK_AND_RST },
181 [1] = { .clk_name = "pll_p_out5", .clk_type = CLK_ONLY },
184 [TEGRA_POWERGATE_VDEC] = {
187 [0] = { .clk_name = "vde", .clk_type = CLK_AND_RST },
190 [TEGRA_POWERGATE_MPE] = {
193 [0] = { .clk_name = "msenc.cbus", .clk_type = CLK_AND_RST },
196 [TEGRA_POWERGATE_VENC] = {
199 [0] = { .clk_name = "ispa", .clk_type = CLK_AND_RST },
200 [1] = { .clk_name = "ispb", .clk_type = CLK_AND_RST },
201 [2] = { .clk_name = "vi", .clk_type = CLK_AND_RST },
202 [3] = { .clk_name = "csi", .clk_type = CLK_AND_RST },
205 [TEGRA_POWERGATE_CPU1] = { .name = "cpu1" },
206 [TEGRA_POWERGATE_CPU2] = { .name = "cpu2" },
207 [TEGRA_POWERGATE_CPU3] = { .name = "cpu3" },
208 [TEGRA_POWERGATE_CELP] = { .name = "celp" },
209 [TEGRA_POWERGATE_CPU0] = { .name = "cpu0" },
210 [TEGRA_POWERGATE_C0NC] = { .name = "c0nc" },
211 [TEGRA_POWERGATE_C1NC] = { .name = "c1nc" },
212 [TEGRA_POWERGATE_DISA] = {
215 [0] = { .clk_name = "disp1", .clk_type = CLK_AND_RST },
218 [TEGRA_POWERGATE_DISB] = {
221 [0] = { .clk_name = "disp2", .clk_type = CLK_AND_RST },
224 [TEGRA_POWERGATE_XUSBA] = {
227 [0] = { .clk_name = "xusb_ss", .clk_type = CLK_AND_RST },
230 [TEGRA_POWERGATE_XUSBB] = {
233 [0] = { .clk_name = "xusb_dev", .clk_type = CLK_AND_RST },
236 [TEGRA_POWERGATE_XUSBC] = {
239 [0] = { .clk_name = "xusb_host", .clk_type = CLK_AND_RST },
242 #ifdef CONFIG_ARCH_TEGRA_HAS_PCIE
243 [TEGRA_POWERGATE_PCIE] = {
246 [0] = { .clk_name = "afi", .clk_type = CLK_AND_RST },
247 [1] = { .clk_name = "pcie", .clk_type = CLK_AND_RST },
248 [2] = { .clk_name = "cml0", .clk_type = CLK_ONLY },
249 [3] = { .clk_name = "pciex", .clk_type = RST_ONLY },
253 #ifdef CONFIG_ARCH_TEGRA_HAS_SATA
254 [TEGRA_POWERGATE_SATA] = {
257 [0] = { .clk_name = "sata", .clk_type = CLK_AND_RST },
258 [1] = { .clk_name = "sata_oob", .clk_type = CLK_AND_RST },
259 [2] = { .clk_name = "cml1", .clk_type = CLK_ONLY },
260 [3] = { .clk_name = "sata_cold", .clk_type = RST_ONLY },
264 [TEGRA_POWERGATE_SOR] = {
267 [0] = { .clk_name = "sor0", .clk_type = CLK_AND_RST },
268 [1] = { .clk_name = "dsia", .clk_type = CLK_AND_RST },
269 [2] = { .clk_name = "dsib", .clk_type = CLK_AND_RST },
270 [3] = { .clk_name = "hdmi", .clk_type = CLK_AND_RST },
271 [4] = { .clk_name = "mipi-cal", .clk_type = CLK_AND_RST },
272 [5] = { .clk_name = "dpaux", .clk_type = CLK_ONLY },
275 #ifdef CONFIG_ARCH_TEGRA_VIC
276 [TEGRA_POWERGATE_VIC] = {
279 [0] = { .clk_name = "vic03.cbus", .clk_type = CLK_AND_RST },
285 #define MC_CLIENT_HOTRESET_CTRL 0x200
286 #define MC_CLIENT_HOTRESET_STAT 0x204
287 #define MC_CLIENT_HOTRESET_CTRL_1 0x970
288 #define MC_CLIENT_HOTRESET_STAT_1 0x974
289 #define MC_VIDEO_PROTECT_REG_CTRL 0x650
291 #define PMC_GPU_RG_CNTRL_0 0x2d4
293 static DEFINE_SPINLOCK(tegra12x_powergate_lock);
294 static DEFINE_MUTEX(tegra12x_powergate_disp_lock);
296 static struct dvfs_rail *gpu_rail;
298 #define HOTRESET_READ_COUNT 5
299 static bool tegra12x_stable_hotreset_check(u32 stat_reg, u32 *stat)
306 spin_lock_irqsave(&tegra12x_powergate_lock, flags);
307 prv_stat = mc_read(stat_reg);
308 for (i = 0; i < HOTRESET_READ_COUNT; i++) {
309 cur_stat = mc_read(stat_reg);
310 if (cur_stat != prv_stat) {
311 spin_unlock_irqrestore(&tegra12x_powergate_lock, flags);
316 spin_unlock_irqrestore(&tegra12x_powergate_lock, flags);
320 int tegra12x_powergate_mc_enable(int id)
325 int tegra12x_powergate_mc_disable(int id)
330 int tegra12x_powergate_mc_flush(int id)
332 u32 idx, rst_ctrl, rst_stat;
333 u32 rst_ctrl_reg, rst_stat_reg;
334 enum mc_client mcClientBit;
338 for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
340 tegra12x_pg_mc_info[id].hot_reset_clients[idx];
341 if (mcClientBit == MC_CLIENT_LAST)
344 if (mcClientBit < 32) {
345 rst_ctrl_reg = MC_CLIENT_HOTRESET_CTRL;
346 rst_stat_reg = MC_CLIENT_HOTRESET_STAT;
349 rst_ctrl_reg = MC_CLIENT_HOTRESET_CTRL_1;
350 rst_stat_reg = MC_CLIENT_HOTRESET_STAT_1;
353 spin_lock_irqsave(&tegra12x_powergate_lock, flags);
355 rst_ctrl = mc_read(rst_ctrl_reg);
356 rst_ctrl |= (1 << mcClientBit);
357 mc_write(rst_ctrl, rst_ctrl_reg);
359 spin_unlock_irqrestore(&tegra12x_powergate_lock, flags);
364 ret = tegra12x_stable_hotreset_check(rst_stat_reg, &rst_stat);
367 } while (!(rst_stat & (1 << mcClientBit)));
373 int tegra12x_powergate_mc_flush_done(int id)
375 u32 idx, rst_ctrl, rst_ctrl_reg;
376 enum mc_client mcClientBit;
379 for (idx = 0; idx < MAX_HOTRESET_CLIENT_NUM; idx++) {
381 tegra12x_pg_mc_info[id].hot_reset_clients[idx];
382 if (mcClientBit == MC_CLIENT_LAST)
385 if (mcClientBit < 32)
386 rst_ctrl_reg = MC_CLIENT_HOTRESET_CTRL;
389 rst_ctrl_reg = MC_CLIENT_HOTRESET_CTRL_1;
392 spin_lock_irqsave(&tegra12x_powergate_lock, flags);
394 rst_ctrl = mc_read(rst_ctrl_reg);
395 rst_ctrl &= ~(1 << mcClientBit);
396 mc_write(rst_ctrl, rst_ctrl_reg);
397 mc_read(rst_ctrl_reg);
399 spin_unlock_irqrestore(&tegra12x_powergate_lock, flags);
407 static int tegra12x_gpu_powergate(int id, struct powergate_partition_info *pg_info)
411 /* If first clk_ptr is null, fill clk info for the partition */
412 if (!pg_info->clk_info[0].clk_ptr)
413 get_clk_info(pg_info);
415 tegra_powergate_mc_flush(id);
420 pmc_write(0x1, PMC_GPU_RG_CNTRL_0);
421 pmc_read(PMC_GPU_RG_CNTRL_0);
425 powergate_partition_assert_reset(pg_info);
430 * GPCPLL is already disabled before entering this function; reference
431 * clocks are enabled until now - disable them just before rail gating
433 partition_clk_disable(pg_info);
437 if (gpu_rail && tegra_powergate_is_powered(id)) {
438 ret = tegra_dvfs_rail_power_down(gpu_rail);
442 pr_info("No GPU regulator?\n");
447 WARN(1, "Could not Railgate Partition %d", id);
451 static int mc_check_vpr(void)
454 u32 val = mc_read(MC_VIDEO_PROTECT_REG_CTRL);
455 if ((val & 1) == 0) {
456 pr_err("VPR configuration not locked down\n");
462 static int tegra12x_gpu_unpowergate(int id,
463 struct powergate_partition_info *pg_info)
468 ret = mc_check_vpr();
473 gpu_rail = tegra_dvfs_get_rail_by_name("vdd_gpu");
474 if (IS_ERR_OR_NULL(gpu_rail)) {
475 WARN(1, "No GPU regulator?\n");
480 ret = tegra_dvfs_rail_power_up(gpu_rail);
485 /* If first clk_ptr is null, fill clk info for the partition */
486 if (!pg_info->clk_info[0].clk_ptr)
487 get_clk_info(pg_info);
490 * GPU reference clocks are initially enabled - skip clock enable if
491 * 1st unpowergate, and in any case leave reference clock enabled on
492 * exit. GPCPLL is still disabled, and will be enabled by driver.
495 /* Un-Powergating fails if all clks are not enabled */
496 ret = partition_clk_enable(pg_info);
503 powergate_partition_assert_reset(pg_info);
508 pmc_write(0, PMC_GPU_RG_CNTRL_0);
509 pmc_read(PMC_GPU_RG_CNTRL_0);
513 powergate_partition_deassert_reset(pg_info);
517 tegra_powergate_mc_flush_done(id);
524 powergate_module(id);
526 WARN(1, "Could not Un-Railgate %d", id);
530 static atomic_t ref_count_dispa = ATOMIC_INIT(0);
531 static atomic_t ref_count_dispb = ATOMIC_INIT(0);
532 static atomic_t ref_count_venc = ATOMIC_INIT(0);
533 static atomic_t ref_count_pcie = ATOMIC_INIT(0);
535 #define CHECK_RET(x) \
543 static inline int tegra12x_powergate(int id)
545 if (tegra_powergate_is_powered(id))
546 return tegra1xx_powergate(id,
547 &tegra12x_powergate_partition_info[id]);
551 static inline int tegra12x_unpowergate(int id)
553 if (!tegra_powergate_is_powered(id))
554 return tegra1xx_unpowergate(id,
555 &tegra12x_powergate_partition_info[id]);
559 static int tegra12x_disp_powergate(int id)
565 mutex_lock(&tegra12x_powergate_disp_lock);
567 ref_counta = atomic_read(&ref_count_dispa);
568 ref_countb = atomic_read(&ref_count_dispb);
570 if (id == TEGRA_POWERGATE_DISA) {
572 ref_counta = atomic_dec_return(&ref_count_dispa);
573 if ((ref_counta <= 0) &&
574 tegra12x_powergate(TEGRA_POWERGATE_DISA)) {
578 } else if (id == TEGRA_POWERGATE_DISB) {
580 ref_countb = atomic_dec_return(&ref_count_dispb);
581 if ((ref_countb <= 0) &&
582 tegra12x_powergate(TEGRA_POWERGATE_DISB)) {
588 if ((ref_counta <= 0) && (ref_countb <= 0)) {
589 if (tegra12x_powergate(TEGRA_POWERGATE_SOR)) {
596 mutex_unlock(&tegra12x_powergate_disp_lock);
600 static int tegra12x_disp_unpowergate(int id)
604 mutex_lock(&tegra12x_powergate_disp_lock);
605 /* always unpowergate SOR partition */
606 if (tegra12x_unpowergate(TEGRA_POWERGATE_SOR)) {
611 if (id == TEGRA_POWERGATE_DISA)
612 atomic_inc(&ref_count_dispa);
613 else if (id == TEGRA_POWERGATE_DISB)
614 atomic_inc(&ref_count_dispb);
615 ret = tegra12x_unpowergate(id);
618 mutex_unlock(&tegra12x_powergate_disp_lock);
622 static int tegra12x_venc_powergate(int id)
627 if (!TEGRA_IS_VENC_POWERGATE_ID(id))
630 ref_count = atomic_dec_return(&ref_count_venc);
631 WARN_ON(ref_count < 0);
633 /* only powergate when decrementing ref_count from 1 to 0 */
634 if (ref_count == 0) {
635 CHECK_RET(tegra12x_powergate(id));
636 CHECK_RET(tegra12x_disp_powergate(TEGRA_POWERGATE_DISA));
642 static int tegra12x_venc_unpowergate(int id)
647 if (!TEGRA_IS_VENC_POWERGATE_ID(id))
650 ref_count = atomic_inc_return(&ref_count_venc);
651 WARN_ON(ref_count < 1);
653 /* only unpowergate when incrementing ref_count from 0 to 1 */
654 if (ref_count == 1) {
655 CHECK_RET(tegra12x_disp_unpowergate(TEGRA_POWERGATE_DISA));
656 CHECK_RET(tegra12x_unpowergate(id));
662 static int tegra12x_pcie_powergate(int id)
667 if (!TEGRA_IS_PCIE_POWERGATE_ID(id))
670 ref_count = atomic_dec_return(&ref_count_pcie);
671 WARN_ON(ref_count < 0);
673 /* only powergate when decrementing ref_count from 1 to 0 */
675 CHECK_RET(tegra12x_powergate(id));
680 static int tegra12x_pcie_unpowergate(int id)
685 if (!TEGRA_IS_PCIE_POWERGATE_ID(id))
688 ref_count = atomic_inc_return(&ref_count_pcie);
689 WARN_ON(ref_count < 1);
691 /* only unpowergate when incrementing ref_count from 0 to 1 */
693 CHECK_RET(tegra12x_unpowergate(id));
698 int tegra12x_powergate_partition(int id)
702 if (TEGRA_IS_GPU_POWERGATE_ID(id)) {
703 ret = tegra12x_gpu_powergate(id,
704 &tegra12x_powergate_partition_info[id]);
705 } else if (TEGRA_IS_DISP_POWERGATE_ID(id))
706 ret = tegra12x_disp_powergate(id);
707 else if (id == TEGRA_POWERGATE_CRAIL)
708 ret = tegra_powergate_set(id, false);
709 else if (id == TEGRA_POWERGATE_VENC)
710 ret = tegra12x_venc_powergate(id);
711 else if (id == TEGRA_POWERGATE_PCIE)
712 ret = tegra12x_pcie_powergate(id);
714 /* call common power-gate API for t1xx */
715 ret = tegra1xx_powergate(id,
716 &tegra12x_powergate_partition_info[id]);
722 int tegra12x_unpowergate_partition(int id)
726 if (TEGRA_IS_GPU_POWERGATE_ID(id)) {
727 ret = tegra12x_gpu_unpowergate(id,
728 &tegra12x_powergate_partition_info[id]);
729 } else if (TEGRA_IS_DISP_POWERGATE_ID(id))
730 ret = tegra12x_disp_unpowergate(id);
731 else if (id == TEGRA_POWERGATE_CRAIL)
732 ret = tegra_powergate_set(id, true);
733 else if (id == TEGRA_POWERGATE_VENC)
734 ret = tegra12x_venc_unpowergate(id);
735 else if (id == TEGRA_POWERGATE_PCIE)
736 ret = tegra12x_pcie_unpowergate(id);
738 ret = tegra1xx_unpowergate(id,
739 &tegra12x_powergate_partition_info[id]);
745 int tegra12x_powergate_partition_with_clk_off(int id)
747 BUG_ON(TEGRA_IS_GPU_POWERGATE_ID(id));
749 return tegraxx_powergate_partition_with_clk_off(id,
750 &tegra12x_powergate_partition_info[id]);
753 int tegra12x_unpowergate_partition_with_clk_on(int id)
755 BUG_ON(TEGRA_IS_GPU_POWERGATE_ID(id));
757 return tegraxx_unpowergate_partition_with_clk_on(id,
758 &tegra12x_powergate_partition_info[id]);
761 const char *tegra12x_get_powergate_domain_name(int id)
763 return tegra12x_powergate_partition_info[id].name;
766 spinlock_t *tegra12x_get_powergate_lock(void)
768 return &tegra12x_powergate_lock;
771 bool tegra12x_powergate_skip(int id)
774 #ifdef CONFIG_ARCH_TEGRA_HAS_SATA
775 case TEGRA_POWERGATE_SATA:
784 bool tegra12x_powergate_is_powered(int id)
788 if (TEGRA_IS_GPU_POWERGATE_ID(id)) {
790 return tegra_dvfs_is_rail_up(gpu_rail);
792 status = pmc_read(PWRGATE_STATUS) & (1 << id);
798 static int tegra12x_powergate_init_refcount(void)
800 bool disa_powered = tegra_powergate_is_powered(TEGRA_POWERGATE_DISA);
801 bool venc_powered = tegra_powergate_is_powered(TEGRA_POWERGATE_VENC);
802 bool pcie_powered = tegra_powergate_is_powered(TEGRA_POWERGATE_PCIE);
804 WARN_ON(venc_powered && !disa_powered);
806 /* if it wasn't powered on, power it on */
808 tegra12x_disp_unpowergate(TEGRA_POWERGATE_DISA);
809 } else { /* if it was, set the refcount to 1 */
810 atomic_set(&ref_count_dispa, 1);
812 /* either way you end up with disa powered on and the
817 /* venc_unpowergate() take a ref_count on dispa to account for
818 * the hardware dependency between the two. This needs to
819 * happen here as well to match that behaviour.
821 atomic_inc(&ref_count_dispa);
822 atomic_set(&ref_count_venc, 1);
824 atomic_set(&ref_count_venc, 0);
827 /* PCIE needs refcount menchanism due to HW Bug#1320346. PCIE should be
828 * powergated only when both XUSB and PCIE are not active.
832 atomic_set(&ref_count_pcie, 1);
834 atomic_set(&ref_count_pcie, 0);
839 static struct powergate_ops tegra12x_powergate_ops = {
840 .soc_name = "tegra12x",
842 .num_powerdomains = TEGRA_NUM_POWERGATE,
844 .get_powergate_lock = tegra12x_get_powergate_lock,
845 .get_powergate_domain_name = tegra12x_get_powergate_domain_name,
847 .powergate_partition = tegra12x_powergate_partition,
848 .unpowergate_partition = tegra12x_unpowergate_partition,
850 .powergate_partition_with_clk_off = tegra12x_powergate_partition_with_clk_off,
851 .unpowergate_partition_with_clk_on = tegra12x_unpowergate_partition_with_clk_on,
853 .powergate_mc_enable = tegra12x_powergate_mc_enable,
854 .powergate_mc_disable = tegra12x_powergate_mc_disable,
856 .powergate_mc_flush = tegra12x_powergate_mc_flush,
857 .powergate_mc_flush_done = tegra12x_powergate_mc_flush_done,
859 .powergate_skip = tegra12x_powergate_skip,
861 .powergate_init_refcount = tegra12x_powergate_init_refcount,
862 .powergate_is_powered = tegra12x_powergate_is_powered,
865 struct powergate_ops *tegra12x_powergate_init_chip_support(void)
867 return &tegra12x_powergate_ops;