1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <dm.h>
9*4882a593Smuzhiyun #include <errno.h>
10*4882a593Smuzhiyun #include <rtc.h>
11*4882a593Smuzhiyun #include <asm/acpi_s3.h>
12*4882a593Smuzhiyun #include <asm/cmos_layout.h>
13*4882a593Smuzhiyun #include <asm/early_cmos.h>
14*4882a593Smuzhiyun #include <asm/io.h>
15*4882a593Smuzhiyun #include <asm/mrccache.h>
16*4882a593Smuzhiyun #include <asm/post.h>
17*4882a593Smuzhiyun #include <asm/processor.h>
18*4882a593Smuzhiyun #include <asm/fsp/fsp_support.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun extern void ich_spi_config_opcode(struct udevice *dev);
23*4882a593Smuzhiyun
checkcpu(void)24*4882a593Smuzhiyun int checkcpu(void)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun return 0;
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun
print_cpuinfo(void)29*4882a593Smuzhiyun int print_cpuinfo(void)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun post_code(POST_CPU_INFO);
32*4882a593Smuzhiyun return default_print_cpuinfo();
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun
fsp_init_phase_pci(void)35*4882a593Smuzhiyun int fsp_init_phase_pci(void)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun u32 status;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /* call into FspNotify */
40*4882a593Smuzhiyun debug("Calling into FSP (notify phase INIT_PHASE_PCI): ");
41*4882a593Smuzhiyun status = fsp_notify(NULL, INIT_PHASE_PCI);
42*4882a593Smuzhiyun if (status)
43*4882a593Smuzhiyun debug("fail, error code %x\n", status);
44*4882a593Smuzhiyun else
45*4882a593Smuzhiyun debug("OK\n");
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun return status ? -EPERM : 0;
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun
board_final_cleanup(void)50*4882a593Smuzhiyun void board_final_cleanup(void)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun u32 status;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #ifdef CONFIG_FSP_LOCKDOWN_SPI
55*4882a593Smuzhiyun struct udevice *dev;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /*
58*4882a593Smuzhiyun * Some Intel FSP (like Braswell) does SPI lock-down during the call
59*4882a593Smuzhiyun * to fsp_notify(INIT_PHASE_BOOT). But before SPI lock-down is done,
60*4882a593Smuzhiyun * it's bootloader's responsibility to configure the SPI controller's
61*4882a593Smuzhiyun * opcode registers properly otherwise SPI controller driver doesn't
62*4882a593Smuzhiyun * know how to communicate with the SPI flash device.
63*4882a593Smuzhiyun *
64*4882a593Smuzhiyun * Note we cannot do such configuration elsewhere (eg: during the SPI
65*4882a593Smuzhiyun * controller driver's probe() routine), because:
66*4882a593Smuzhiyun *
67*4882a593Smuzhiyun * 1). U-Boot SPI controller driver does not set the lock-down bit
68*4882a593Smuzhiyun * 2). Any SPI transfer will corrupt the contents of these registers
69*4882a593Smuzhiyun *
70*4882a593Smuzhiyun * Hence we have to do it right here before SPI lock-down bit is set.
71*4882a593Smuzhiyun */
72*4882a593Smuzhiyun if (!uclass_first_device_err(UCLASS_SPI, &dev))
73*4882a593Smuzhiyun ich_spi_config_opcode(dev);
74*4882a593Smuzhiyun #endif
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /* call into FspNotify */
77*4882a593Smuzhiyun debug("Calling into FSP (notify phase INIT_PHASE_BOOT): ");
78*4882a593Smuzhiyun status = fsp_notify(NULL, INIT_PHASE_BOOT);
79*4882a593Smuzhiyun if (status)
80*4882a593Smuzhiyun debug("fail, error code %x\n", status);
81*4882a593Smuzhiyun else
82*4882a593Smuzhiyun debug("OK\n");
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun return;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
fsp_prepare_mrc_cache(void)87*4882a593Smuzhiyun static __maybe_unused void *fsp_prepare_mrc_cache(void)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun struct mrc_data_container *cache;
90*4882a593Smuzhiyun struct mrc_region entry;
91*4882a593Smuzhiyun int ret;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun ret = mrccache_get_region(NULL, &entry);
94*4882a593Smuzhiyun if (ret)
95*4882a593Smuzhiyun return NULL;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun cache = mrccache_find_current(&entry);
98*4882a593Smuzhiyun if (!cache)
99*4882a593Smuzhiyun return NULL;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__,
102*4882a593Smuzhiyun cache->data, cache->data_size, cache->checksum);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun return cache->data;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun #ifdef CONFIG_HAVE_ACPI_RESUME
fsp_save_s3_stack(void)108*4882a593Smuzhiyun int fsp_save_s3_stack(void)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun struct udevice *dev;
111*4882a593Smuzhiyun int ret;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun if (gd->arch.prev_sleep_state == ACPI_S3)
114*4882a593Smuzhiyun return 0;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun ret = uclass_get_device(UCLASS_RTC, 0, &dev);
117*4882a593Smuzhiyun if (ret) {
118*4882a593Smuzhiyun debug("Cannot find RTC: err=%d\n", ret);
119*4882a593Smuzhiyun return -ENODEV;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun /* Save the stack address to CMOS */
123*4882a593Smuzhiyun ret = rtc_write32(dev, CMOS_FSP_STACK_ADDR, gd->start_addr_sp);
124*4882a593Smuzhiyun if (ret) {
125*4882a593Smuzhiyun debug("Save stack address to CMOS: err=%d\n", ret);
126*4882a593Smuzhiyun return -EIO;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun return 0;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun #endif
132*4882a593Smuzhiyun
arch_fsp_init(void)133*4882a593Smuzhiyun int arch_fsp_init(void)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun void *nvs;
136*4882a593Smuzhiyun int stack = CONFIG_FSP_TEMP_RAM_ADDR;
137*4882a593Smuzhiyun int boot_mode = BOOT_FULL_CONFIG;
138*4882a593Smuzhiyun #ifdef CONFIG_HAVE_ACPI_RESUME
139*4882a593Smuzhiyun int prev_sleep_state = chipset_prev_sleep_state();
140*4882a593Smuzhiyun gd->arch.prev_sleep_state = prev_sleep_state;
141*4882a593Smuzhiyun #endif
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun if (!gd->arch.hob_list) {
144*4882a593Smuzhiyun #ifdef CONFIG_ENABLE_MRC_CACHE
145*4882a593Smuzhiyun nvs = fsp_prepare_mrc_cache();
146*4882a593Smuzhiyun #else
147*4882a593Smuzhiyun nvs = NULL;
148*4882a593Smuzhiyun #endif
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun #ifdef CONFIG_HAVE_ACPI_RESUME
151*4882a593Smuzhiyun if (prev_sleep_state == ACPI_S3) {
152*4882a593Smuzhiyun if (nvs == NULL) {
153*4882a593Smuzhiyun /* If waking from S3 and no cache then */
154*4882a593Smuzhiyun debug("No MRC cache found in S3 resume path\n");
155*4882a593Smuzhiyun post_code(POST_RESUME_FAILURE);
156*4882a593Smuzhiyun /* Clear Sleep Type */
157*4882a593Smuzhiyun chipset_clear_sleep_state();
158*4882a593Smuzhiyun /* Reboot */
159*4882a593Smuzhiyun debug("Rebooting..\n");
160*4882a593Smuzhiyun reset_cpu(0);
161*4882a593Smuzhiyun /* Should not reach here.. */
162*4882a593Smuzhiyun panic("Reboot System");
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /*
166*4882a593Smuzhiyun * DM is not avaiable yet at this point, hence call
167*4882a593Smuzhiyun * CMOS access library which does not depend on DM.
168*4882a593Smuzhiyun */
169*4882a593Smuzhiyun stack = cmos_read32(CMOS_FSP_STACK_ADDR);
170*4882a593Smuzhiyun boot_mode = BOOT_ON_S3_RESUME;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun #endif
173*4882a593Smuzhiyun /*
174*4882a593Smuzhiyun * The first time we enter here, call fsp_init().
175*4882a593Smuzhiyun * Note the execution does not return to this function,
176*4882a593Smuzhiyun * instead it jumps to fsp_continue().
177*4882a593Smuzhiyun */
178*4882a593Smuzhiyun fsp_init(stack, boot_mode, nvs);
179*4882a593Smuzhiyun } else {
180*4882a593Smuzhiyun /*
181*4882a593Smuzhiyun * The second time we enter here, adjust the size of malloc()
182*4882a593Smuzhiyun * pool before relocation. Given gd->malloc_base was adjusted
183*4882a593Smuzhiyun * after the call to board_init_f_init_reserve() in arch/x86/
184*4882a593Smuzhiyun * cpu/start.S, we should fix up gd->malloc_limit here.
185*4882a593Smuzhiyun */
186*4882a593Smuzhiyun gd->malloc_limit += CONFIG_FSP_SYS_MALLOC_F_LEN;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun return 0;
190*4882a593Smuzhiyun }
191