blob: 329ab0cf8eb47506251e6056d39b6331d11e5c57 [file] [log] [blame]
Rajeshwari Shindebed24422013-07-04 12:29:17 +05301/*
2 * Lowlevel setup for EXYNOS5 based board
3 *
4 * Copyright (C) 2013 Samsung Electronics
5 * Rajeshwari Shinde <rajeshwari.s@samsung.com>
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26#include <common.h>
27#include <config.h>
28#include <asm/arch/cpu.h>
29#include <asm/arch/dmc.h>
30#include <asm/arch/power.h>
31#include <asm/arch/tzpc.h>
32#include <asm/arch/periph.h>
33#include <asm/arch/pinmux.h>
Akshay Saraswat1d575af2015-02-20 13:27:12 +053034#include <asm/arch/system.h>
Akshay Saraswat4bb039f2015-02-20 13:27:15 +053035#include <asm/armv7.h>
Rajeshwari Shindebed24422013-07-04 12:29:17 +053036#include "common_setup.h"
Akshay Saraswat1d575af2015-02-20 13:27:12 +053037#include "exynos5_setup.h"
Rajeshwari Shindebed24422013-07-04 12:29:17 +053038
39/* These are the things we can do during low-level init */
40enum {
41 DO_WAKEUP = 1 << 0,
42 DO_CLOCKS = 1 << 1,
43 DO_MEM_RESET = 1 << 2,
44 DO_UART = 1 << 3,
Doug Anderson6a39e7f2014-05-29 21:40:54 +053045 DO_POWER = 1 << 4,
Rajeshwari Shindebed24422013-07-04 12:29:17 +053046};
47
Akshay Saraswat1d575af2015-02-20 13:27:12 +053048#ifdef CONFIG_EXYNOS5420
49/*
Akshay Saraswat58771912015-02-20 13:27:17 +053050 * Enable ECC by setting L2CTLR[21].
51 * Set L2CTLR[7] to make tag ram latency 3 cycles and
52 * set L2CTLR[1] to make data ram latency 3 cycles.
53 * We need to make RAM latency of 3 cycles here because cores
54 * power ON and OFF while switching. And everytime a core powers
55 * ON, iROM provides it a default L2CTLR value 0x400 which stands
56 * for TAG RAM setup of 1 cycle. Hence, we face a need of
57 * restoring data and tag latency values.
58 */
59static void configure_l2_ctlr(void)
60{
61 uint32_t val;
62
63 mrc_l2_ctlr(val);
64 val |= (1 << 21);
65 val |= (1 << 7);
66 val |= (1 << 1);
67 mcr_l2_ctlr(val);
68}
69
70/*
71 * Set L2ACTLR[27] to prevent the clock generator from stopping
72 * the L2 logic clock.
73 * Set L2ACTLR[3] to disable clean/evict push to external.
74 */
75static void configure_l2_actlr(void)
76{
77 uint32_t val;
78
79 mrc_l2_aux_ctlr(val);
80 val |= (1 << 27);
81 val |= (1 << 3);
82 mcr_l2_aux_ctlr(val);
83}
84
85/*
Akshay Saraswat4bb039f2015-02-20 13:27:15 +053086 * Power up secondary CPUs.
87 */
88static void secondary_cpu_start(void)
89{
90 v7_enable_smp(EXYNOS5420_INFORM_BASE);
91 svc32_mode_en();
Akshay Saraswatc1f5d212015-02-20 13:27:18 +053092 branch_bx(CONFIG_EXYNOS_RELOCATE_CODE_BASE);
Akshay Saraswat4bb039f2015-02-20 13:27:15 +053093}
94
95/*
96 * This is the entry point of hotplug-in and
97 * cluster switching.
98 */
99static void low_power_start(void)
100{
101 uint32_t val, reg_val;
102
103 reg_val = readl(EXYNOS5420_SPARE_BASE);
104 if (reg_val != CPU_RST_FLAG_VAL) {
105 writel(0x0, CONFIG_LOWPOWER_FLAG);
Akshay Saraswat0db0b7a2015-02-20 13:27:19 +0530106 branch_bx(0x0);
Akshay Saraswat4bb039f2015-02-20 13:27:15 +0530107 }
108
109 reg_val = readl(CONFIG_PHY_IRAM_BASE + 0x4);
110 if (reg_val != (uint32_t)&low_power_start) {
111 /* Store jump address as low_power_start if not present */
112 writel((uint32_t)&low_power_start, CONFIG_PHY_IRAM_BASE + 0x4);
113 dsb();
114 sev();
115 }
116
117 /* Set the CPU to SVC32 mode */
118 svc32_mode_en();
Akshay Saraswat58771912015-02-20 13:27:17 +0530119
120#ifndef CONFIG_SYS_L2CACHE_OFF
121 /* Read MIDR for Primary Part Number */
122 mrc_midr(val);
123 val = (val >> 4);
124 val &= 0xf;
125
126 if (val == 0xf) {
127 configure_l2_ctlr();
128 configure_l2_actlr();
129 v7_enable_l2_hazard_detect();
130 }
131#endif
Akshay Saraswat4bb039f2015-02-20 13:27:15 +0530132
133 /* Invalidate L1 & TLB */
134 val = 0x0;
135 mcr_tlb(val);
136 mcr_icache(val);
137
138 /* Disable MMU stuff and caches */
139 mrc_sctlr(val);
140
141 val &= ~((0x2 << 12) | 0x7);
142 val |= ((0x1 << 12) | (0x8 << 8) | 0x2);
143 mcr_sctlr(val);
144
145 /* CPU state is hotplug or reset */
146 secondary_cpu_start();
147
148 /* Core should not enter into WFI here */
149 wfi();
150}
151
152/*
Akshay Saraswat1d575af2015-02-20 13:27:12 +0530153 * Pointer to this function is stored in iRam which is used
154 * for jump and power down of a specific core.
155 */
156static void power_down_core(void)
157{
158 uint32_t tmp, core_id, core_config;
159
160 /* Get the unique core id */
161 /*
162 * Multiprocessor Affinity Register
163 * [11:8] Cluster ID
164 * [1:0] CPU ID
165 */
166 mrc_mpafr(core_id);
167 tmp = core_id & 0x3;
168 core_id = (core_id >> 6) & ~3;
169 core_id |= tmp;
170 core_id &= 0x3f;
171
172 /* Set the status of the core to low */
173 core_config = (core_id * CPU_CONFIG_STATUS_OFFSET);
174 core_config += EXYNOS5420_CPU_CONFIG_BASE;
175 writel(0x0, core_config);
176
177 /* Core enter WFI */
178 wfi();
179}
180
181/*
182 * Configurations for secondary cores are inapt at this stage.
183 * Reconfigure secondary cores. Shutdown and change the status
184 * of all cores except the primary core.
185 */
186static void secondary_cores_configure(void)
187{
Akshay Saraswat4bb039f2015-02-20 13:27:15 +0530188 /* Setup L2 cache */
Akshay Saraswat58771912015-02-20 13:27:17 +0530189 configure_l2_ctlr();
Akshay Saraswat4bb039f2015-02-20 13:27:15 +0530190 v7_enable_l2_hazard_detect();
Akshay Saraswat1d575af2015-02-20 13:27:12 +0530191
Akshay Saraswat4bb039f2015-02-20 13:27:15 +0530192 /* Clear secondary boot iRAM base */
193 writel(0x0, (CONFIG_EXYNOS_RELOCATE_CODE_BASE + 0x1C));
194
195 /* set lowpower flag and address */
196 writel(CPU_RST_FLAG_VAL, CONFIG_LOWPOWER_FLAG);
197 writel((uint32_t)&low_power_start, CONFIG_LOWPOWER_ADDR);
198 writel(CPU_RST_FLAG_VAL, EXYNOS5420_SPARE_BASE);
199 /* Store jump address for power down */
Akshay Saraswat1d575af2015-02-20 13:27:12 +0530200 writel((uint32_t)&power_down_core, CONFIG_PHY_IRAM_BASE + 0x4);
201
202 /* Need all core power down check */
203 dsb();
204 sev();
Akshay Saraswat1d575af2015-02-20 13:27:12 +0530205}
Akshay Saraswat4bb039f2015-02-20 13:27:15 +0530206
207extern void relocate_wait_code(void);
Akshay Saraswat1d575af2015-02-20 13:27:12 +0530208#endif
209
Rajeshwari Shindebed24422013-07-04 12:29:17 +0530210int do_lowlevel_init(void)
211{
212 uint32_t reset_status;
213 int actions = 0;
214
215 arch_cpu_init();
216
Akshay Saraswat1d575af2015-02-20 13:27:12 +0530217#ifdef CONFIG_EXYNOS5420
Akshay Saraswat4bb039f2015-02-20 13:27:15 +0530218 relocate_wait_code();
219
Akshay Saraswat1d575af2015-02-20 13:27:12 +0530220 /* Reconfigure secondary cores */
221 secondary_cores_configure();
222#endif
223
Rajeshwari Shindebed24422013-07-04 12:29:17 +0530224 reset_status = get_reset_status();
225
226 switch (reset_status) {
227 case S5P_CHECK_SLEEP:
228 actions = DO_CLOCKS | DO_WAKEUP;
229 break;
230 case S5P_CHECK_DIDLE:
231 case S5P_CHECK_LPA:
232 actions = DO_WAKEUP;
233 break;
234 default:
235 /* This is a normal boot (not a wake from sleep) */
Doug Anderson6a39e7f2014-05-29 21:40:54 +0530236 actions = DO_CLOCKS | DO_MEM_RESET | DO_POWER;
Rajeshwari Shindebed24422013-07-04 12:29:17 +0530237 }
238
Doug Anderson6a39e7f2014-05-29 21:40:54 +0530239 if (actions & DO_POWER)
240 set_ps_hold_ctrl();
241
Rajeshwari Shindebed24422013-07-04 12:29:17 +0530242 if (actions & DO_CLOCKS) {
243 system_clock_init();
244 mem_ctrl_init(actions & DO_MEM_RESET);
245 tzpc_init();
246 }
247
248 return actions & DO_WAKEUP;
249}