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