tlk: 6/19 update
[3rdparty/ote_partner/tlk.git] / platform / tegra / monitor / psci.c
1 /*
2  * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23
24 #include <stdlib.h>
25 #include <err.h>
26 #include <debug.h>
27 #include <platform.h>
28 #include <platform/memmap.h>
29 #include <reg.h>
30 #include <string.h>
31 #include <psci.h>
32 #include <target/debugconfig.h>
33 #include <platform/platform_p.h>
34 #include <lib/monitor/monitor_vector.h>
35
36 /* referenced APBDEV_PMC_SECURE registers */
37 #define MC_SECURITY_CFG1_0              0x74
38
39 #define PMC_SECURE_DISABLE2             0x2c4
40 #define PMC_SECURE_DISABLE2_WRITE22_ON  (1 << 28)
41 #define PMC_SECURE_SCRATCH22            0x338
42
43 #define PMC_SECURE_DISABLE3             0x2d4
44 #define PMC_SECURE_DISABLE3_WRITE34_ON  (1 << 20)
45 #define PMC_SECURE_DISABLE3_WRITE35_ON  (1 << 22)
46 #define PMC_SECURE_SCRATCH34            0x368
47 #define PMC_SECURE_SCRATCH35            0x36c
48
49 #define EVP_CPU_RESET_VECTOR            0x100
50
51 #define SB_CSR                          0x0
52 #define SB_CSR_NS_RST_VEC_WR_DIS        (1 << 1)
53
54 /* CPU reset vector */
55 #define SB_AA64_RESET_LOW               0x30    // width = 31:0
56 #define SB_AA64_RESET_HI                0x34    // width = 11:0
57
58 static volatile uint32_t cpus_started;
59 static const uint32_t cpus_expected = ((1 << MONCPUS) - 1);
60
61 /* sets of MMIO ranges setup */
62 #define MMIO_RANGE_0_ADDR       0x50000000
63 #define MMIO_RANGE_1_ADDR       0x60000000
64 #define MMIO_RANGE_2_ADDR       0x70000000
65 #define MMIO_RANGE_SIZE         0x200000
66
67 static void psci_program_reset_vectors()
68 {
69         uint64_t phys_cpu_reset;
70         uint32_t reg;
71
72         phys_cpu_reset = mon_virt_to_phys(&__mon_cpu_reset_vector);
73
74 #if WITH_AA64_CPU_RESET_VECTORS
75         /* write lower 32 bits first, then the upper 11 bits */
76         phys_cpu_reset = mon_virt_to_phys(&__mon_cpu_reset_vector);
77         writel((phys_cpu_reset & 0xFFFFFFFF) | 1, TEGRA_SB_BASE + SB_AA64_RESET_LOW);
78         phys_cpu_reset >>= 32;
79         writel(phys_cpu_reset & 0x7FF, TEGRA_SB_BASE + SB_AA64_RESET_HI);
80
81         /* ensure SECURE_SCRATCH34/35 are write locked */
82         reg  = readl(TEGRA_PMC_BASE + PMC_SECURE_DISABLE3);
83         reg |= (PMC_SECURE_DISABLE3_WRITE34_ON |
84                 PMC_SECURE_DISABLE3_WRITE35_ON);
85         writel(reg, TEGRA_PMC_BASE + PMC_SECURE_DISABLE3);      /* lock */
86 #else
87         /* set exception vector (read to flush) */
88         writel(phys_cpu_reset, TEGRA_EXCEPTION_VECTORS_BASE + EVP_CPU_RESET_VECTOR);
89         (void)readl(TEGRA_EXCEPTION_VECTORS_BASE + EVP_CPU_RESET_VECTOR);
90
91         /* ensure SECURE_SCRATCH22 is write locked */
92         reg  = readl(TEGRA_PMC_BASE + PMC_SECURE_DISABLE2);
93         reg |= PMC_SECURE_DISABLE2_WRITE22_ON;
94         writel(reg, TEGRA_PMC_BASE + PMC_SECURE_DISABLE2);      /* lock */
95 #endif
96
97         /* set secure boot control (read to flush) */
98         reg  = readl(TEGRA_SB_BASE + SB_CSR);
99         reg |= SB_CSR_NS_RST_VEC_WR_DIS;
100         writel(reg, TEGRA_SB_BASE + SB_CSR);
101         (void)readl(TEGRA_SB_BASE + SB_CSR);
102 }
103
104 /*
105  * One-time init called during cold boot from primary CPU
106  */
107 void platform_psci_init(uint32_t cpu)
108 {
109         uint64_t phys_cpu_reset;
110         uint32_t reg;
111
112         /* identity map MMIO ranges for register access */
113         mon_mmu_map_mmio(MMIO_RANGE_0_ADDR, MMIO_RANGE_0_ADDR, MMIO_RANGE_SIZE);
114         mon_mmu_map_mmio(MMIO_RANGE_1_ADDR, MMIO_RANGE_1_ADDR, MMIO_RANGE_SIZE);
115         mon_mmu_map_mmio(MMIO_RANGE_2_ADDR, MMIO_RANGE_2_ADDR, MMIO_RANGE_SIZE);
116
117         platform_init_debug_port(DEFAULT_DEBUG_PORT);
118
119 #if WITH_AA64_CPU_RESET_VECTORS
120         reg  = readl(TEGRA_PMC_BASE + PMC_SECURE_DISABLE3);
121         reg &= ~PMC_SECURE_DISABLE3_WRITE34_ON;
122         reg &= ~PMC_SECURE_DISABLE3_WRITE35_ON;
123         writel(reg, TEGRA_PMC_BASE + PMC_SECURE_DISABLE3);      /* unlock */
124
125         /* write lower 32 bits first, then the upper 11 bits */
126         phys_cpu_reset = mon_virt_to_phys(&__mon_cpu_reset_vector);
127         writel((phys_cpu_reset & 0xFFFFFFFF) | 1, TEGRA_SB_BASE + SB_AA64_RESET_LOW);
128         phys_cpu_reset >>= 32;
129         writel(phys_cpu_reset & 0x7FF, TEGRA_SB_BASE + SB_AA64_RESET_HI);
130
131         /* set exception vector to be used to resume from suspend */
132         phys_cpu_reset = mon_virt_to_phys(&__mon_cpu_reset_vector);
133         writel(phys_cpu_reset & 0xFFFFFFFF, TEGRA_PMC_BASE + PMC_SECURE_SCRATCH34);
134         phys_cpu_reset >>= 32;
135         writel(phys_cpu_reset & 0x7FF, TEGRA_PMC_BASE + PMC_SECURE_SCRATCH35);
136
137         reg  = readl(TEGRA_PMC_BASE + PMC_SECURE_DISABLE3);
138         reg |= (PMC_SECURE_DISABLE3_WRITE34_ON |
139                 PMC_SECURE_DISABLE3_WRITE35_ON);
140         writel(reg, TEGRA_PMC_BASE + PMC_SECURE_DISABLE3);      /* lock */
141 #else
142         reg  = readl(TEGRA_PMC_BASE + PMC_SECURE_DISABLE2);
143         reg &= ~PMC_SECURE_DISABLE2_WRITE22_ON;
144         writel(reg, TEGRA_PMC_BASE + PMC_SECURE_DISABLE2);      /* unlock */
145
146         phys_cpu_reset = mon_virt_to_phys(&__mon_cpu_reset_vector);
147         writel(phys_cpu_reset, TEGRA_PMC_BASE + PMC_SECURE_SCRATCH22);
148
149         reg  = readl(TEGRA_PMC_BASE + PMC_SECURE_DISABLE2);
150         reg |= PMC_SECURE_DISABLE2_WRITE22_ON;
151         writel(reg, TEGRA_PMC_BASE + PMC_SECURE_DISABLE2);      /* lock */
152 #endif
153
154         mon_atomic_or(&cpus_started, 1 << cpu);
155
156         platform_monitor_init_cpu();
157         platform_init_memory(__mon_phys_base, __mon_phys_size);
158         platform_config_interrupts();
159 }
160
161 /*
162  * One time init call during end of cold boot from primary CPU
163  */
164 void platform_psci_coldboot_epilog()
165 {
166         /* mark entire TLK carveout as secure in the MC */
167         platform_secure_dram_aperture();
168
169 #if !defined(WITH_ARM_PSCI_SUPPORT)
170         /* make sure all CPUs have reset before reprogramming vector */
171         while (cpus_started != cpus_expected)
172                 ;
173 #endif
174
175         psci_program_reset_vectors();
176 }
177
178 /*
179  * Routine is called when a CPU goes through reset, either a secondary
180  * CPU during cold boot, or all CPUs during system suspend.
181  */
182 void platform_psci_cpu_has_reset(uint32_t cpu)
183 {
184         uint32_t reg;
185
186         mon_atomic_or(&cpus_started, 1 << cpu);
187
188         /*
189          * Opportunity to do an per-CPU setup after reset. For now, only
190          * restores global state, so just run on the primary (CPU0).
191          */
192         if (cpu != 0)
193                 return;
194
195         /*
196          * Avoid relying on having seen an LP0 enter SMC.
197          *
198          * If MC_SECURITY_CFG1 has gone back zero (its POR value) then LP0
199          * has occurred (as it's not part of BL's warmboot restore) and system
200          * registers need to be reloaded.
201          */
202         reg = readl(TEGRA_MC_BASE + MC_SECURITY_CFG1_0);
203         if (reg == (__mon_phys_size >> 20))
204                 return;
205
206 #if !defined(WITH_ARM_PSCI_SUPPORT)
207         /* make sure all CPUs have reset before reprogramming vector */
208         while (cpus_started != cpus_expected)
209                 ;
210 #endif
211
212         psci_program_reset_vectors();
213         platform_monitor_init_cpu();
214         platform_restore_memory();
215         platform_config_interrupts();
216 }
217
218 void platform_psci_handler(struct fastcall_frame *frame, uint32_t cpu)
219 {
220         /* currently, only handling CPU_SUSPEND */
221         if (frame->r[0] != PSCI_FUNC_ID_CPU_SUSPEND_LEGACY &&
222             frame->r[0] != PSCI_FUNC_ID_CPU_SUSPEND) {
223                 frame->r[0] = PSCI_RETURN_NOT_SUPPORTED;
224                 return;
225         }
226
227         /* save NS entry point */
228         ((uint64_t *)&__mon_cpu_return_addr)[cpu] = frame->r[2];
229
230         cpus_started = 0;
231
232         frame->r[0] = PSCI_RETURN_SUCCESS;
233 }