blob: 09e4c4aaa4f3f7f97da035e9cea22a5d8d2bcf8e [file] [log] [blame]
Varun Wadekarb316e242015-05-19 16:48:04 +05301/*
2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Varun Wadekarb316e242015-05-19 16:48:04 +05305 */
6
7#include <arch_helpers.h>
8#include <assert.h>
9#include <debug.h>
10#include <mmio.h>
11#include <pmc.h>
12#include <tegra_def.h>
13
14/* Module IDs used during power ungate procedure */
15static const int pmc_cpu_powergate_id[4] = {
16 0, /* CPU 0 */
17 9, /* CPU 1 */
18 10, /* CPU 2 */
19 11 /* CPU 3 */
20};
21
22/*******************************************************************************
23 * Power ungate CPU to start the boot process. CPU reset vectors must be
24 * populated before calling this function.
25 ******************************************************************************/
26void tegra_pmc_cpu_on(int cpu)
27{
28 uint32_t val;
29
30 /*
Varun Wadekarfccf8e02015-07-16 10:35:12 +053031 * Check if CPU is already power ungated
32 */
33 val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);
34 if (val & (1 << pmc_cpu_powergate_id[cpu]))
35 return;
36
37 /*
Varun Wadekarb316e242015-05-19 16:48:04 +053038 * The PMC deasserts the START bit when it starts the power
39 * ungate process. Loop till no power toggle is in progress.
40 */
41 do {
42 val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE);
43 } while (val & PMC_TOGGLE_START);
44
45 /*
46 * Start the power ungate procedure
47 */
48 val = pmc_cpu_powergate_id[cpu] | PMC_TOGGLE_START;
49 tegra_pmc_write_32(PMC_PWRGATE_TOGGLE, val);
50
51 /*
52 * The PMC deasserts the START bit when it starts the power
53 * ungate process. Loop till powergate START bit is asserted.
54 */
55 do {
56 val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE);
57 } while (val & (1 << 8));
58
59 /* loop till the CPU is power ungated */
60 do {
61 val = tegra_pmc_read_32(PMC_PWRGATE_STATUS);
62 } while ((val & (1 << pmc_cpu_powergate_id[cpu])) == 0);
63}
64
65/*******************************************************************************
66 * Setup CPU vectors for resume from deep sleep
67 ******************************************************************************/
68void tegra_pmc_cpu_setup(uint64_t reset_addr)
69{
70 uint32_t val;
71
72 tegra_pmc_write_32(PMC_SECURE_SCRATCH34, (reset_addr & 0xFFFFFFFF) | 1);
73 val = reset_addr >> 32;
74 tegra_pmc_write_32(PMC_SECURE_SCRATCH35, val & 0x7FF);
75}
76
77/*******************************************************************************
78 * Lock CPU vectors to restrict further writes
79 ******************************************************************************/
80void tegra_pmc_lock_cpu_vectors(void)
81{
82 uint32_t val;
83
Varun Wadekar30d89772015-07-16 10:38:11 +053084 /* lock PMC_SECURE_SCRATCH22 */
85 val = tegra_pmc_read_32(PMC_SECURE_DISABLE2);
86 val |= PMC_SECURE_DISABLE2_WRITE22_ON;
87 tegra_pmc_write_32(PMC_SECURE_DISABLE2, val);
88
Varun Wadekarb316e242015-05-19 16:48:04 +053089 /* lock PMC_SECURE_SCRATCH34/35 */
90 val = tegra_pmc_read_32(PMC_SECURE_DISABLE3);
91 val |= (PMC_SECURE_DISABLE3_WRITE34_ON |
92 PMC_SECURE_DISABLE3_WRITE35_ON);
93 tegra_pmc_write_32(PMC_SECURE_DISABLE3, val);
94}
95
96/*******************************************************************************
97 * Restart the system
98 ******************************************************************************/
99__dead2 void tegra_pmc_system_reset(void)
100{
101 uint32_t reg;
102
103 reg = tegra_pmc_read_32(PMC_CONFIG);
104 reg |= 0x10; /* restart */
105 tegra_pmc_write_32(PMC_CONFIG, reg);
106 wfi();
107
108 ERROR("Tegra System Reset: operation not handled.\n");
109 panic();
110}