xref: /rk3399_ARM-atf/plat/nvidia/tegra/drivers/pmc/pmc.c (revision e2469d823bfc633a32782a8c018d3b55eb2b23a1)
1*e2469d82SVarun Wadekar /*
2*e2469d82SVarun Wadekar  * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3*e2469d82SVarun Wadekar  *
4*e2469d82SVarun Wadekar  * SPDX-License-Identifier: BSD-3-Clause
5*e2469d82SVarun Wadekar  */
6*e2469d82SVarun Wadekar 
7*e2469d82SVarun Wadekar #include <assert.h>
8*e2469d82SVarun Wadekar 
9*e2469d82SVarun Wadekar #include <arch_helpers.h>
10*e2469d82SVarun Wadekar #include <common/debug.h>
11*e2469d82SVarun Wadekar #include <lib/mmio.h>
12*e2469d82SVarun Wadekar 
13*e2469d82SVarun Wadekar #include <pmc.h>
14*e2469d82SVarun Wadekar #include <tegra_def.h>
15*e2469d82SVarun Wadekar 
16*e2469d82SVarun Wadekar #define RESET_ENABLE	0x10U
17*e2469d82SVarun Wadekar 
18*e2469d82SVarun Wadekar /* Module IDs used during power ungate procedure */
19*e2469d82SVarun Wadekar static const uint32_t pmc_cpu_powergate_id[4] = {
20*e2469d82SVarun Wadekar 	14, /* CPU 0 */
21*e2469d82SVarun Wadekar 	9, /* CPU 1 */
22*e2469d82SVarun Wadekar 	10, /* CPU 2 */
23*e2469d82SVarun Wadekar 	11 /* CPU 3 */
24*e2469d82SVarun Wadekar };
25*e2469d82SVarun Wadekar 
26*e2469d82SVarun Wadekar /*******************************************************************************
27*e2469d82SVarun Wadekar  * Power ungate CPU to start the boot process. CPU reset vectors must be
28*e2469d82SVarun Wadekar  * populated before calling this function.
29*e2469d82SVarun Wadekar  ******************************************************************************/
30*e2469d82SVarun Wadekar void tegra_pmc_cpu_on(int32_t cpu)
31*e2469d82SVarun Wadekar {
32*e2469d82SVarun Wadekar 	uint32_t val;
33*e2469d82SVarun Wadekar 
34*e2469d82SVarun Wadekar 	/*
35*e2469d82SVarun Wadekar 	 * Check if CPU is already power ungated
36*e2469d82SVarun Wadekar 	 */
37*e2469d82SVarun Wadekar 	val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);
38*e2469d82SVarun Wadekar 	if ((val & (1U << pmc_cpu_powergate_id[cpu])) == 0U) {
39*e2469d82SVarun Wadekar 		/*
40*e2469d82SVarun Wadekar 		 * The PMC deasserts the START bit when it starts the power
41*e2469d82SVarun Wadekar 		 * ungate process. Loop till no power toggle is in progress.
42*e2469d82SVarun Wadekar 		 */
43*e2469d82SVarun Wadekar 		do {
44*e2469d82SVarun Wadekar 			val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE);
45*e2469d82SVarun Wadekar 		} while ((val & PMC_TOGGLE_START) != 0U);
46*e2469d82SVarun Wadekar 
47*e2469d82SVarun Wadekar 		/*
48*e2469d82SVarun Wadekar 		 * Start the power ungate procedure
49*e2469d82SVarun Wadekar 		 */
50*e2469d82SVarun Wadekar 		val = pmc_cpu_powergate_id[cpu] | PMC_TOGGLE_START;
51*e2469d82SVarun Wadekar 		tegra_pmc_write_32(PMC_PWRGATE_TOGGLE, val);
52*e2469d82SVarun Wadekar 
53*e2469d82SVarun Wadekar 		/*
54*e2469d82SVarun Wadekar 		 * The PMC deasserts the START bit when it starts the power
55*e2469d82SVarun Wadekar 		 * ungate process. Loop till powergate START bit is asserted.
56*e2469d82SVarun Wadekar 		 */
57*e2469d82SVarun Wadekar 		do {
58*e2469d82SVarun Wadekar 			val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE);
59*e2469d82SVarun Wadekar 		} while ((val & (1U << 8)) != 0U);
60*e2469d82SVarun Wadekar 
61*e2469d82SVarun Wadekar 		/* loop till the CPU is power ungated */
62*e2469d82SVarun Wadekar 		do {
63*e2469d82SVarun Wadekar 			val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);
64*e2469d82SVarun Wadekar 		} while ((val & (1U << pmc_cpu_powergate_id[cpu])) == 0U);
65*e2469d82SVarun Wadekar 	}
66*e2469d82SVarun Wadekar }
67*e2469d82SVarun Wadekar 
68*e2469d82SVarun Wadekar /*******************************************************************************
69*e2469d82SVarun Wadekar  * Setup CPU vectors for resume from deep sleep
70*e2469d82SVarun Wadekar  ******************************************************************************/
71*e2469d82SVarun Wadekar void tegra_pmc_cpu_setup(uint64_t reset_addr)
72*e2469d82SVarun Wadekar {
73*e2469d82SVarun Wadekar 	uint32_t val;
74*e2469d82SVarun Wadekar 
75*e2469d82SVarun Wadekar 	tegra_pmc_write_32(PMC_SECURE_SCRATCH34,
76*e2469d82SVarun Wadekar 			   ((uint32_t)reset_addr & 0xFFFFFFFFU) | 1U);
77*e2469d82SVarun Wadekar 	val = (uint32_t)(reset_addr >> 32U);
78*e2469d82SVarun Wadekar 	tegra_pmc_write_32(PMC_SECURE_SCRATCH35, val & 0x7FFU);
79*e2469d82SVarun Wadekar }
80*e2469d82SVarun Wadekar 
81*e2469d82SVarun Wadekar /*******************************************************************************
82*e2469d82SVarun Wadekar  * Lock CPU vectors to restrict further writes
83*e2469d82SVarun Wadekar  ******************************************************************************/
84*e2469d82SVarun Wadekar void tegra_pmc_lock_cpu_vectors(void)
85*e2469d82SVarun Wadekar {
86*e2469d82SVarun Wadekar 	uint32_t val;
87*e2469d82SVarun Wadekar 
88*e2469d82SVarun Wadekar 	/* lock PMC_SECURE_SCRATCH22 */
89*e2469d82SVarun Wadekar 	val = tegra_pmc_read_32(PMC_SECURE_DISABLE2);
90*e2469d82SVarun Wadekar 	val |= PMC_SECURE_DISABLE2_WRITE22_ON;
91*e2469d82SVarun Wadekar 	tegra_pmc_write_32(PMC_SECURE_DISABLE2, val);
92*e2469d82SVarun Wadekar 
93*e2469d82SVarun Wadekar 	/* lock PMC_SECURE_SCRATCH34/35 */
94*e2469d82SVarun Wadekar 	val = tegra_pmc_read_32(PMC_SECURE_DISABLE3);
95*e2469d82SVarun Wadekar 	val |= (PMC_SECURE_DISABLE3_WRITE34_ON |
96*e2469d82SVarun Wadekar 		PMC_SECURE_DISABLE3_WRITE35_ON);
97*e2469d82SVarun Wadekar 	tegra_pmc_write_32(PMC_SECURE_DISABLE3, val);
98*e2469d82SVarun Wadekar }
99*e2469d82SVarun Wadekar 
100*e2469d82SVarun Wadekar /*******************************************************************************
101*e2469d82SVarun Wadekar  * Find out if this is the last standing CPU
102*e2469d82SVarun Wadekar  ******************************************************************************/
103*e2469d82SVarun Wadekar bool tegra_pmc_is_last_on_cpu(void)
104*e2469d82SVarun Wadekar {
105*e2469d82SVarun Wadekar 	int i, cpu = read_mpidr() & MPIDR_CPU_MASK;
106*e2469d82SVarun Wadekar 	uint32_t val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);;
107*e2469d82SVarun Wadekar 	bool status = true;
108*e2469d82SVarun Wadekar 
109*e2469d82SVarun Wadekar 	/* check if this is the last standing CPU */
110*e2469d82SVarun Wadekar 	for (i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER; i++) {
111*e2469d82SVarun Wadekar 
112*e2469d82SVarun Wadekar 		/* skip the current CPU */
113*e2469d82SVarun Wadekar 		if (i == cpu)
114*e2469d82SVarun Wadekar 			continue;
115*e2469d82SVarun Wadekar 
116*e2469d82SVarun Wadekar 		/* are other CPUs already power gated? */
117*e2469d82SVarun Wadekar 		if ((val & ((uint32_t)1 << pmc_cpu_powergate_id[i])) != 0U) {
118*e2469d82SVarun Wadekar 			status = false;
119*e2469d82SVarun Wadekar 		}
120*e2469d82SVarun Wadekar 	}
121*e2469d82SVarun Wadekar 
122*e2469d82SVarun Wadekar 	return status;
123*e2469d82SVarun Wadekar }
124*e2469d82SVarun Wadekar 
125*e2469d82SVarun Wadekar /*******************************************************************************
126*e2469d82SVarun Wadekar  * Handler to be called on exiting System suspend. Right now only DPD registers
127*e2469d82SVarun Wadekar  * are cleared.
128*e2469d82SVarun Wadekar  ******************************************************************************/
129*e2469d82SVarun Wadekar void tegra_pmc_resume(void)
130*e2469d82SVarun Wadekar {
131*e2469d82SVarun Wadekar 
132*e2469d82SVarun Wadekar 	/* Clear DPD sample */
133*e2469d82SVarun Wadekar 	mmio_write_32((TEGRA_PMC_BASE + PMC_IO_DPD_SAMPLE), 0x0);
134*e2469d82SVarun Wadekar 
135*e2469d82SVarun Wadekar 	/* Clear DPD Enable */
136*e2469d82SVarun Wadekar 	mmio_write_32((TEGRA_PMC_BASE + PMC_DPD_ENABLE_0), 0x0);
137*e2469d82SVarun Wadekar }
138*e2469d82SVarun Wadekar 
139*e2469d82SVarun Wadekar /*******************************************************************************
140*e2469d82SVarun Wadekar  * Restart the system
141*e2469d82SVarun Wadekar  ******************************************************************************/
142*e2469d82SVarun Wadekar __dead2 void tegra_pmc_system_reset(void)
143*e2469d82SVarun Wadekar {
144*e2469d82SVarun Wadekar 	uint32_t reg;
145*e2469d82SVarun Wadekar 
146*e2469d82SVarun Wadekar 	reg = tegra_pmc_read_32(PMC_CONFIG);
147*e2469d82SVarun Wadekar 	reg |= RESET_ENABLE;		/* restart */
148*e2469d82SVarun Wadekar 	tegra_pmc_write_32(PMC_CONFIG, reg);
149*e2469d82SVarun Wadekar 	wfi();
150*e2469d82SVarun Wadekar 
151*e2469d82SVarun Wadekar 	ERROR("Tegra System Reset: operation not handled.\n");
152*e2469d82SVarun Wadekar 	panic();
153*e2469d82SVarun Wadekar }
154