xref: /aosp_15_r20/external/coreboot/src/soc/nvidia/tegra124/lp0/tegra_lp0_resume.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 /* Function unit addresses. */
4 enum {
5 	UP_TAG_BASE = 0x60000000,
6 	TIMER_BASE = 0x60005000,
7 	CLK_RST_BASE = 0x60006000,
8 	FLOW_CTLR_BASE = 0x60007000,
9 	TEGRA_EVP_BASE = 0x6000f000,
10 	PMC_CTLR_BASE = 0x7000e400,
11 	MC_CTLR_BASE = 0x70019000,
12 	SYSCTR_CTLR_BASE = 0x700f0000
13 };
14 
15 /* UP tag registers. */
16 static uint32_t *up_tag_ptr = (void *)(UP_TAG_BASE + 0x0);
17 enum {
18 	UP_TAG_AVP = 0xaaaaaaaa
19 };
20 
21 /* Timer registers. */
22 static uint32_t *timer_us_ptr = (void *)(TIMER_BASE + 0x10);
23 
24 /* Clock and reset controller registers. */
25 static uint32_t *clk_rst_rst_devices_l_ptr = (void *)(CLK_RST_BASE + 0x4);
26 enum {
27 	SWR_TRIG_SYS_RST = 0x1 << 2
28 };
29 
30 static uint32_t *clk_rst_cclk_burst_policy_ptr = (void *)(CLK_RST_BASE + 0x20);
31 enum {
32 	CCLK_PLLP_BURST_POLICY = 0x20004444
33 };
34 
35 static uint32_t *clk_rst_super_cclk_div_ptr = (void *)(CLK_RST_BASE + 0x24);
36 enum {
37 	SUPER_CDIV_ENB = 0x1 << 31
38 };
39 
40 static uint32_t *clk_rst_osc_ctrl_ptr = (void *)(CLK_RST_BASE + 0x50);
41 enum {
42 	OSC_XOE = 0x1 << 0,
43 	OSC_XOFS_SHIFT = 4,
44 	OSC_XOFS_MASK = 0x3f << OSC_XOFS_SHIFT,
45 	OSC_FREQ_SHIFT = 28,
46 	OSC_FREQ_MASK = 0xf << OSC_FREQ_SHIFT
47 };
48 enum {
49 	OSC_FREQ_13 = 0,
50 	OSC_FREQ_16P8 = 1,
51 	OSC_FREQ_19P2 = 4,
52 	OSC_FREQ_38P4 = 5,
53 	OSC_FREQ_12 = 8,
54 	OSC_FREQ_48 = 9,
55 	OSC_FREQ_26 = 12
56 };
57 
58 static uint32_t *clk_rst_pllu_base_ptr = (void *)(CLK_RST_BASE + 0xc0);
59 enum {
60 	PLLU_DIVM_SHIFT = 0,
61 	PLLU_DIVN_SHIFT = 8,
62 	PLLU_OVERRIDE = 0x1 << 24,
63 	PLLU_ENABLE = 0x1 << 30,
64 	PLLU_BYPASS = 0x1 << 31
65 };
66 
67 static uint32_t *clk_rst_pllu_misc_ptr = (void *)(CLK_RST_BASE + 0xcc);
68 enum {
69 	PLLU_LFCON_SHIFT = 4,
70 	PLLU_CPCON_SHIFT = 8,
71 	PLLU_LOCK_ENABLE = 22
72 };
73 
74 static uint32_t *clk_rst_pllx_base_ptr = (void *)(CLK_RST_BASE + 0xe0);
75 enum {
76 	PLLX_ENABLE = 0x1 << 30
77 };
78 
79 static uint32_t *clk_rst_rst_dev_u_clr_ptr = (void *)(CLK_RST_BASE + 0x314);
80 enum {
81 	SWR_CSITE_RST = 0x1 << 9
82 };
83 
84 static uint32_t *clk_rst_clk_enb_l_set_ptr = (void *)(CLK_RST_BASE + 0x320);
85 enum {
86 	CLK_ENB_CPU = 0x1 << 0
87 };
88 
89 static uint32_t *clk_rst_clk_out_enb_u_set_ptr =
90 	(void *)(CLK_RST_BASE + 0x330);
91 enum {
92 	CLK_ENB_CSITE = 0x1 << 9
93 };
94 
95 static uint32_t *clk_rst_cpu_softrst_ctrl2_ptr =
96 	(void *)(CLK_RST_BASE + 0x388);
97 enum {
98 	CAR2PMC_CPU_ACK_WIDTH_SHIFT = 0,
99 	CAR2PMC_CPU_ACK_WIDTH_MASK = 0xfff << CAR2PMC_CPU_ACK_WIDTH_SHIFT
100 };
101 
102 static uint32_t *clk_rst_clk_src_mselect_ptr =
103 	(void *)(CLK_RST_BASE + 0x3b4);
104 enum {
105 	MSELECT_CLK_DIV_SHIFT = 0,
106 	MSELECT_CLK_SRC_SHIFT = 29,
107 	MSELECT_CLK_SRC_PLLP_OUT0 = 0x0 << MSELECT_CLK_SRC_SHIFT,
108 	MSELECT_CLK_SRC_PLLC2_OUT0 = 0x1 << MSELECT_CLK_SRC_SHIFT,
109 	MSELECT_CLK_SRC_PLLC_OUT0 = 0x2 << MSELECT_CLK_SRC_SHIFT,
110 	MSELECT_CLK_SRC_PLLC3_OUT0 = 0x3 << MSELECT_CLK_SRC_SHIFT
111 };
112 
113 static uint32_t *clk_rst_rst_dev_v_clr_ptr = (void *)(CLK_RST_BASE + 0x434);
114 enum {
115 	SWR_MSELECT_RST = 0x1 << 3
116 };
117 
118 static uint32_t *clk_rst_clk_enb_v_set_ptr = (void *)(CLK_RST_BASE + 0x440);
119 enum {
120 	CLK_ENB_CPUG = 0x1 << 0,
121 	CLK_ENB_CPULP = 0x1 << 1,
122 	CLK_ENB_MSELECT = 0x1 << 3
123 };
124 
125 static uint32_t *clk_rst_rst_cpulp_cmplx_clr_ptr =
126 	(void *)(CLK_RST_BASE + 0x45c);
127 static uint32_t *clk_rst_rst_cpug_cmplx_clr_ptr =
128 	(void *)(CLK_RST_BASE + 0x454);
129 enum {
130 	CLR_CPURESET0 = 0x1 << 0,
131 	CLR_CPURESET1 = 0x1 << 1,
132 	CLR_CPURESET2 = 0x1 << 2,
133 	CLR_CPURESET3 = 0x1 << 3,
134 	CLR_DBGRESET0 = 0x1 << 12,
135 	CLR_DBGRESET1 = 0x1 << 13,
136 	CLR_DBGRESET2 = 0x1 << 14,
137 	CLR_DBGRESET3 = 0x1 << 15,
138 	CLR_CORERESET0 = 0x1 << 16,
139 	CLR_CORERESET1 = 0x1 << 17,
140 	CLR_CORERESET2 = 0x1 << 18,
141 	CLR_CORERESET3 = 0x1 << 19,
142 	CLR_CXRESET0 = 0x1 << 20,
143 	CLR_CXRESET1 = 0x1 << 21,
144 	CLR_CXRESET2 = 0x1 << 22,
145 	CLR_CXRESET3 = 0x1 << 23,
146 	CLR_NONCPURESET = 0x1 << 29
147 };
148 
149 /* Reset vector. */
150 static uint32_t *evp_cpu_reset_ptr = (void *)(TEGRA_EVP_BASE + 0x100);
151 
152 /* Flow controller registers. */
153 static uint32_t *flow_ctlr_halt_cop_events_ptr =
154 	(void *)(FLOW_CTLR_BASE + 0x4);
155 enum {
156 	EVENT_MSEC = 0x1 << 24,
157 	EVENT_JTAG = 0x1 << 28,
158 	FLOW_MODE_SHIFT = 29,
159 	FLOW_MODE_STOP = 2 << FLOW_MODE_SHIFT,
160 };
161 
162 static uint32_t *flow_ctlr_cluster_control_ptr =
163 	(void *)(FLOW_CTLR_BASE + 0x2c);
164 enum {
165 	FLOW_CLUSTER_ACTIVE_LP = 0x1 << 0
166 };
167 
168 static uint32_t *flow_ctlr_ram_repair_ptr =
169 	(void *)(FLOW_CTLR_BASE + 0x40);
170 static uint32_t *flow_ctlr_ram_repair_cluster1_ptr =
171 	(void *)(FLOW_CTLR_BASE + 0x58);
172 enum {
173 	RAM_REPAIR_REQ = 0x1 << 0,
174 	RAM_REPAIR_STS = 0x1 << 1,
175 };
176 
177 /* Power management controller registers. */
178 enum {
179 	PARTID_CRAIL = 0,
180 	PARTID_CELP = 12,
181 	PARTID_CE0 = 14,
182 	PARTID_C0NC = 15,
183 	PARTID_C1NC = 16
184 };
185 
186 static uint32_t *pmc_ctlr_clamp_status_ptr = (void *)(PMC_CTLR_BASE + 0x2c);
187 
188 static uint32_t *pmc_ctlr_pwrgate_toggle_ptr = (void *)(PMC_CTLR_BASE + 0x30);
189 enum {
190 	PWRGATE_TOGGLE_START = 0x1 << 8
191 };
192 
193 static uint32_t *pmc_ctlr_pwrgate_status_ptr = (void *)(PMC_CTLR_BASE + 0x38);
194 
195 static uint32_t *pmc_ctlr_scratch4_ptr = (void *)(PMC_CTLR_BASE + 0x60);
196 enum {
197 	PMC_SCRATCH4_LP = 0x1 << 31
198 };
199 
200 static uint32_t *pmc_ctlr_cpupwrgood_timer_ptr =
201 	(void *)(PMC_CTLR_BASE + 0xc8);
202 
203 static uint32_t *pmc_ctlr_scratch41_ptr = (void *)(PMC_CTLR_BASE + 0x140);
204 
205 static uint32_t *pmc_ctlr_osc_edpd_over_ptr = (void *)(PMC_CTLR_BASE + 0x1a4);
206 enum {
207 	PMC_XOFS_SHIFT = 1,
208 	PMC_XOFS_MASK = 0x3f << PMC_XOFS_SHIFT
209 };
210 
211 /* Memory controller registers. */
212 static uint32_t *mc_video_protect_size_mb_ptr = (void *)(MC_CTLR_BASE + 0x64c);
213 
214 static uint32_t *mc_video_protect_reg_ctrl_ptr =
215 	(void *)(MC_CTLR_BASE + 0x650);
216 enum {
217 	VIDEO_PROTECT_WRITE_ACCESS_DISABLE = 0x1 << 0,
218 	VIDEO_PROTECT_ALLOW_TZ_WRITE_ACCESS = 0x1 << 1
219 };
220 
221 /* System counter registers. */
222 static uint32_t *sysctr_cntcr_ptr = (void *)(SYSCTR_CTLR_BASE + 0x0);
223 enum {
224 	TSC_CNTCR_ENABLE = 0x1 << 0,
225 	TSC_CNTCR_HDBG = 0x1 << 1
226 };
227 
228 static uint32_t *sysctr_cntfid0_ptr = (void *)(SYSCTR_CTLR_BASE + 0x20);
229 
230 /* Utility functions. */
halt(void)231 static __always_inline void __noreturn halt(void)
232 {
233 	for (;;);
234 }
235 
read32(const void * addr)236 static inline uint32_t read32(const void *addr)
237 {
238 	return *(volatile uint32_t *)addr;
239 }
240 
write32(void * addr,uint32_t val)241 static inline void write32(void *addr, uint32_t val)
242 {
243 	*(volatile uint32_t *)addr = val;
244 }
245 
setbits32(uint32_t bits,void * addr)246 static inline void setbits32(uint32_t bits, void *addr)
247 {
248 	write32(addr, read32(addr) | bits);
249 }
250 
clrbits32(uint32_t bits,void * addr)251 static inline void clrbits32(uint32_t bits, void *addr)
252 {
253 	write32(addr, read32(addr) & ~bits);
254 }
255 
reset(void)256 static void __noreturn reset(void)
257 {
258 	write32(clk_rst_rst_devices_l_ptr, SWR_TRIG_SYS_RST);
259 	halt();
260 }
261 
udelay(unsigned int usecs)262 static void udelay(unsigned int usecs)
263 {
264 	uint32_t start = read32(timer_us_ptr);
265 	while (read32(timer_us_ptr) - start < usecs)
266 		;
267 }
268 
269 /* Accessors. */
wakeup_on_lp(void)270 static int wakeup_on_lp(void)
271 {
272 	return !!(read32(pmc_ctlr_scratch4_ptr) & PMC_SCRATCH4_LP);
273 }
274 
get_wakeup_vector(void)275 static uint32_t get_wakeup_vector(void)
276 {
277 	return read32(pmc_ctlr_scratch41_ptr);
278 }
279 
get_osc_freq(void)280 static unsigned int get_osc_freq(void)
281 {
282 	return (read32(clk_rst_osc_ctrl_ptr) & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
283 }
284 
285 /* Clock configuration. */
config_oscillator(void)286 static void config_oscillator(void)
287 {
288 	// Read oscillator drive strength from OSC_EDPD_OVER.XOFS and copy
289 	// to OSC_CTRL.XOFS and set XOE.
290 	uint32_t xofs = (read32(pmc_ctlr_osc_edpd_over_ptr) &
291 		    PMC_XOFS_MASK) >> PMC_XOFS_SHIFT;
292 
293 	uint32_t osc_ctrl = read32(clk_rst_osc_ctrl_ptr);
294 	osc_ctrl &= ~OSC_XOFS_MASK;
295 	osc_ctrl |= (xofs << OSC_XOFS_SHIFT);
296 	osc_ctrl |= OSC_XOE;
297 	write32(clk_rst_osc_ctrl_ptr, osc_ctrl);
298 }
299 
config_pllu(void)300 static void config_pllu(void)
301 {
302 	// Figure out what parameters to use for PLLU.
303 	uint32_t divm, divn, cpcon, lfcon;
304 	switch (get_osc_freq()) {
305 	case OSC_FREQ_12:
306 	case OSC_FREQ_48:
307 		divm = 0x0c;
308 		divn = 0x3c0;
309 		cpcon = 0x0c;
310 		lfcon = 0x02;
311 		break;
312 	case OSC_FREQ_16P8:
313 		divm = 0x07;
314 		divn = 0x190;
315 		cpcon = 0x05;
316 		lfcon = 0x02;
317 		break;
318 	case OSC_FREQ_19P2:
319 	case OSC_FREQ_38P4:
320 		divm = 0x04;
321 		divn = 0xc8;
322 		cpcon = 0x03;
323 		lfcon = 0x02;
324 		break;
325 	case OSC_FREQ_26:
326 		divm = 0x1a;
327 		divn = 0x3c0;
328 		cpcon = 0x0c;
329 		lfcon = 0x02;
330 		break;
331 	default:
332 		// Map anything that's not recognized to 13MHz.
333 		divm = 0x0d;
334 		divn = 0x3c0;
335 		cpcon = 0x0c;
336 		lfcon = 0x02;
337 	}
338 
339 	// Configure PLLU.
340 	uint32_t base = PLLU_BYPASS | PLLU_OVERRIDE |
341 			(divn << PLLU_DIVN_SHIFT) | (divm << PLLU_DIVM_SHIFT);
342 	write32(clk_rst_pllu_base_ptr, base);
343 	uint32_t misc = (cpcon << PLLU_CPCON_SHIFT) |
344 			(lfcon << PLLU_LFCON_SHIFT);
345 	write32(clk_rst_pllu_misc_ptr, misc);
346 
347 	// Enable PLLU.
348 	base &= ~PLLU_BYPASS;
349 	base |= PLLU_ENABLE;
350 	write32(clk_rst_pllu_base_ptr, base);
351 	misc |= PLLU_LOCK_ENABLE;
352 	write32(clk_rst_pllu_misc_ptr, misc);
353 }
354 
config_tsc(void)355 static void config_tsc(void)
356 {
357 	// Tell the TSC the oscillator frequency.
358 	switch (get_osc_freq()) {
359 	case OSC_FREQ_12:
360 		write32(sysctr_cntfid0_ptr, 12000000);
361 		break;
362 	case OSC_FREQ_48:
363 		write32(sysctr_cntfid0_ptr, 48000000);
364 		break;
365 	case OSC_FREQ_16P8:
366 		write32(sysctr_cntfid0_ptr, 16800000);
367 		break;
368 	case OSC_FREQ_19P2:
369 		write32(sysctr_cntfid0_ptr, 19200000);
370 		break;
371 	case OSC_FREQ_38P4:
372 		write32(sysctr_cntfid0_ptr, 38400000);
373 		break;
374 	case OSC_FREQ_26:
375 		write32(sysctr_cntfid0_ptr, 26000000);
376 		break;
377 	default:
378 		// Default to 13MHz.
379 		write32(sysctr_cntfid0_ptr, 13000000);
380 		break;
381 	}
382 
383 	// Enable the TSC.
384 	setbits32(TSC_CNTCR_ENABLE | TSC_CNTCR_HDBG, sysctr_cntcr_ptr);
385 }
386 
enable_cpu_clocks(void)387 static void enable_cpu_clocks(void)
388 {
389 	// Enable the CPU complex clock.
390 	write32(clk_rst_clk_enb_l_set_ptr, CLK_ENB_CPU);
391 	write32(clk_rst_clk_enb_v_set_ptr, CLK_ENB_CPUG | CLK_ENB_CPULP);
392 }
393 
394 /* Function unit configuration. */
config_core_sight(void)395 static void config_core_sight(void)
396 {
397 	// Enable the CoreSight clock.
398 	write32(clk_rst_clk_out_enb_u_set_ptr, CLK_ENB_CSITE);
399 
400 	/*
401 	 * De-assert CoreSight reset.
402 	 * NOTE: We're leaving the CoreSight clock on the oscillator for
403 	 *       now. It will be restored to its original clock source
404 	 *       when the CPU-side restoration code runs.
405 	 */
406 	write32(clk_rst_rst_dev_u_clr_ptr, SWR_CSITE_RST);
407 }
408 
config_mselect(void)409 static void config_mselect(void)
410 {
411 	// Set MSELECT clock source to PLLP with 1:4 divider.
412 	write32(clk_rst_clk_src_mselect_ptr,
413 		(6 << MSELECT_CLK_DIV_SHIFT) | MSELECT_CLK_SRC_PLLP_OUT0);
414 
415 	// Enable clock to MSELECT.
416 	write32(clk_rst_clk_enb_v_set_ptr, CLK_ENB_MSELECT);
417 
418 	udelay(2);
419 
420 	// Bring MSELECT out of reset.
421 	write32(clk_rst_rst_dev_v_clr_ptr, SWR_MSELECT_RST);
422 }
423 
424 /* Resets. */
clear_cpu_resets(void)425 static void clear_cpu_resets(void)
426 {
427 	// Take the non-cpu of the G and LP clusters out of reset.
428 	write32(clk_rst_rst_cpulp_cmplx_clr_ptr, CLR_NONCPURESET);
429 	write32(clk_rst_rst_cpug_cmplx_clr_ptr, CLR_NONCPURESET);
430 
431 	// Clear software controlled reset of the slow cluster.
432 	write32(clk_rst_rst_cpulp_cmplx_clr_ptr,
433 		CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0);
434 
435 	// Clear software controlled reset of the fast cluster.
436 	write32(clk_rst_rst_cpug_cmplx_clr_ptr,
437 		CLR_CPURESET0 | CLR_DBGRESET0 | CLR_CORERESET0 | CLR_CXRESET0 |
438 		CLR_CPURESET1 | CLR_DBGRESET1 | CLR_CORERESET1 | CLR_CXRESET1 |
439 		CLR_CPURESET2 | CLR_DBGRESET2 | CLR_CORERESET2 | CLR_CXRESET2 |
440 		CLR_CPURESET3 | CLR_DBGRESET3 | CLR_CORERESET3 | CLR_CXRESET3);
441 }
442 
443 /* RAM repair */
ram_repair(void)444 void ram_repair(void)
445 {
446 	// Request Cluster0 RAM repair.
447 	setbits32(RAM_REPAIR_REQ, flow_ctlr_ram_repair_ptr);
448 	// Poll for Cluster0 RAM repair status.
449 	while (!(read32(flow_ctlr_ram_repair_ptr) & RAM_REPAIR_STS))
450 		;
451 
452 	// Request Cluster1 RAM repair.
453 	setbits32(RAM_REPAIR_REQ, flow_ctlr_ram_repair_cluster1_ptr);
454 	// Poll for Cluster1 RAM repair status.
455 	while (!(read32(flow_ctlr_ram_repair_cluster1_ptr) & RAM_REPAIR_STS))
456 		;
457 }
458 
459 /* Power. */
power_on_partition(unsigned int id)460 static void power_on_partition(unsigned int id)
461 {
462 	uint32_t bit = 0x1 << id;
463 	if (!(read32(pmc_ctlr_pwrgate_status_ptr) & bit)) {
464 		// Partition is not on. Turn it on.
465 		write32(pmc_ctlr_pwrgate_toggle_ptr, id | PWRGATE_TOGGLE_START);
466 
467 		// Wait until the partition is powerd on.
468 		while (!(read32(pmc_ctlr_pwrgate_status_ptr) & bit))
469 			;
470 
471 		// Wait until clamp is off.
472 		while (read32(pmc_ctlr_clamp_status_ptr) & bit)
473 			;
474 	}
475 }
476 
power_on_main_cpu(void)477 static void power_on_main_cpu(void)
478 {
479 	/*
480 	 * Reprogram PMC_CPUPWRGOOD_TIMER register:
481 	 *
482 	 * XXX This is a fragile assumption. XXX
483 	 * The kernel prepares PMC_CPUPWRGOOD_TIMER based on a 32768Hz clock.
484 	 * Note that PMC_CPUPWRGOOD_TIMER is running at pclk.
485 	 *
486 	 * We need to reprogram PMC_CPUPWRGOOD_TIMER based on the current pclk
487 	 * which is at 204Mhz (pclk = sclk = pllp_out2) after BootROM. Multiply
488 	 * PMC_CPUPWRGOOD_TIMER by 204M / 32K.
489 	 *
490 	 * Save the original PMC_CPUPWRGOOD_TIMER register which we need to
491 	 * restore after the CPU is powered up.
492 	 */
493 	uint32_t orig_timer = read32(pmc_ctlr_cpupwrgood_timer_ptr);
494 
495 	write32(pmc_ctlr_cpupwrgood_timer_ptr,
496 		orig_timer * (204000000 / 32768));
497 
498 	if (wakeup_on_lp()) {
499 		power_on_partition(PARTID_C1NC);
500 		power_on_partition(PARTID_CELP);
501 	} else {
502 		power_on_partition(PARTID_CRAIL);
503 		power_on_partition(PARTID_C0NC);
504 		power_on_partition(PARTID_CE0);
505 	}
506 
507 	// Restore the original PMC_CPUPWRGOOD_TIMER.
508 	write32(pmc_ctlr_cpupwrgood_timer_ptr, orig_timer);
509 }
510 
511 /* Entry point. */
lp0_resume(void)512 void lp0_resume(void)
513 {
514 	// If not on the AVP, reset.
515 	if (read32(up_tag_ptr) != UP_TAG_AVP)
516 		reset();
517 
518 	config_oscillator();
519 
520 	// Tell the flow controller which cluster to wake up. The default is
521 	// the fast cluster.
522 	if (wakeup_on_lp())
523 		setbits32(FLOW_CLUSTER_ACTIVE_LP,
524 			  flow_ctlr_cluster_control_ptr);
525 
526 	// Program SUPER_CCLK_DIVIDER.
527 	write32(clk_rst_super_cclk_div_ptr, SUPER_CDIV_ENB);
528 
529 	config_core_sight();
530 
531 	config_pllu();
532 
533 	// Set the CPU reset vector.
534 	write32(evp_cpu_reset_ptr, get_wakeup_vector());
535 
536 	// Select CPU complex clock source.
537 	write32(clk_rst_cclk_burst_policy_ptr, CCLK_PLLP_BURST_POLICY);
538 
539 	config_mselect();
540 
541 	// Disable PLLX since it isn't used as CPU clock source.
542 	clrbits32(PLLX_ENABLE, clk_rst_pllx_base_ptr);
543 
544 	// Set CAR2PMC_CPU_ACK_WIDTH to 408.
545 	uint32_t ack_width = read32(clk_rst_cpu_softrst_ctrl2_ptr);
546 	ack_width &= ~CAR2PMC_CPU_ACK_WIDTH_MASK;
547 	ack_width |= 408 << CAR2PMC_CPU_ACK_WIDTH_SHIFT;
548 	write32(clk_rst_cpu_softrst_ctrl2_ptr, ack_width);
549 
550 	config_tsc();
551 
552 	// Disable VPR.
553 	write32(mc_video_protect_size_mb_ptr, 0);
554 	write32(mc_video_protect_reg_ctrl_ptr,
555 		VIDEO_PROTECT_WRITE_ACCESS_DISABLE);
556 
557 	enable_cpu_clocks();
558 
559 	power_on_main_cpu();
560 
561 	// Perform RAM repair after CPU is powered on.
562 	ram_repair();
563 
564 	clear_cpu_resets();
565 
566 	// Halt the AVP.
567 	while (1)
568 		write32(flow_ctlr_halt_cop_events_ptr,
569 		        FLOW_MODE_STOP | EVENT_JTAG);
570 }
571 
572 /* Header. */
573 extern uint8_t blob_data;
574 extern uint8_t blob_data_size;
575 extern uint8_t blob_total_size;
576 
577 struct lp0_header {
578 	uint32_t length_insecure;	// Insecure total length.
579 	uint32_t reserved[3];
580 	uint8_t rsa_modulus[256];	// RSA key modulus.
581 	uint8_t aes_signature[16];	// AES signature.
582 	uint8_t rsa_signature[256];	// RSA-PSS signature.
583 	uint8_t random_aes_block[16];	// Random data, may be zero.
584 	uint32_t length_secure;		// Secure total length.
585 	uint32_t destination;		// Where to load the blob in iRAM.
586 	uint32_t entry_point;		// Entry point for the blob.
587 	uint32_t code_length;		// Length of just the data.
588 } __packed;
589 
590 struct lp0_header header __attribute__((section(".header"))) =
591 {
592 	.length_insecure = (uintptr_t)&blob_total_size,
593 	.length_secure = (uintptr_t)&blob_total_size,
594 	.destination = (uintptr_t)&blob_data,
595 	.entry_point = (uintptr_t)&lp0_resume,
596 	.code_length = (uintptr_t)&blob_data_size
597 };
598