191785f70SSimon Glass /*
291785f70SSimon Glass * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
391785f70SSimon Glass *
491785f70SSimon Glass * SPDX-License-Identifier: GPL-2.0+
591785f70SSimon Glass */
691785f70SSimon Glass
791785f70SSimon Glass #include <common.h>
8ba65808eSBin Meng #include <dm.h>
991785f70SSimon Glass #include <errno.h>
10ba65808eSBin Meng #include <rtc.h>
111206723bSBin Meng #include <asm/acpi_s3.h>
12ba65808eSBin Meng #include <asm/cmos_layout.h>
13ba65808eSBin Meng #include <asm/early_cmos.h>
1491785f70SSimon Glass #include <asm/io.h>
15ff1e18afSBin Meng #include <asm/mrccache.h>
1691785f70SSimon Glass #include <asm/post.h>
1791785f70SSimon Glass #include <asm/processor.h>
1891785f70SSimon Glass #include <asm/fsp/fsp_support.h>
1991785f70SSimon Glass
208b097916SSimon Glass DECLARE_GLOBAL_DATA_PTR;
218b097916SSimon Glass
22*1e6ebee6SBin Meng extern void ich_spi_config_opcode(struct udevice *dev);
23*1e6ebee6SBin Meng
checkcpu(void)2476d1d02fSSimon Glass int checkcpu(void)
2576d1d02fSSimon Glass {
2676d1d02fSSimon Glass return 0;
2776d1d02fSSimon Glass }
2876d1d02fSSimon Glass
print_cpuinfo(void)2991785f70SSimon Glass int print_cpuinfo(void)
3091785f70SSimon Glass {
3191785f70SSimon Glass post_code(POST_CPU_INFO);
3291785f70SSimon Glass return default_print_cpuinfo();
3391785f70SSimon Glass }
3491785f70SSimon Glass
fsp_init_phase_pci(void)35412400abSSimon Glass int fsp_init_phase_pci(void)
3691785f70SSimon Glass {
3791785f70SSimon Glass u32 status;
3891785f70SSimon Glass
3991785f70SSimon Glass /* call into FspNotify */
4091785f70SSimon Glass debug("Calling into FSP (notify phase INIT_PHASE_PCI): ");
4191785f70SSimon Glass status = fsp_notify(NULL, INIT_PHASE_PCI);
42412400abSSimon Glass if (status)
4391785f70SSimon Glass debug("fail, error code %x\n", status);
4491785f70SSimon Glass else
4591785f70SSimon Glass debug("OK\n");
4691785f70SSimon Glass
47412400abSSimon Glass return status ? -EPERM : 0;
48412400abSSimon Glass }
49412400abSSimon Glass
board_final_cleanup(void)5091785f70SSimon Glass void board_final_cleanup(void)
5191785f70SSimon Glass {
5291785f70SSimon Glass u32 status;
5391785f70SSimon Glass
54*1e6ebee6SBin Meng #ifdef CONFIG_FSP_LOCKDOWN_SPI
55*1e6ebee6SBin Meng struct udevice *dev;
56*1e6ebee6SBin Meng
57*1e6ebee6SBin Meng /*
58*1e6ebee6SBin Meng * Some Intel FSP (like Braswell) does SPI lock-down during the call
59*1e6ebee6SBin Meng * to fsp_notify(INIT_PHASE_BOOT). But before SPI lock-down is done,
60*1e6ebee6SBin Meng * it's bootloader's responsibility to configure the SPI controller's
61*1e6ebee6SBin Meng * opcode registers properly otherwise SPI controller driver doesn't
62*1e6ebee6SBin Meng * know how to communicate with the SPI flash device.
63*1e6ebee6SBin Meng *
64*1e6ebee6SBin Meng * Note we cannot do such configuration elsewhere (eg: during the SPI
65*1e6ebee6SBin Meng * controller driver's probe() routine), because:
66*1e6ebee6SBin Meng *
67*1e6ebee6SBin Meng * 1). U-Boot SPI controller driver does not set the lock-down bit
68*1e6ebee6SBin Meng * 2). Any SPI transfer will corrupt the contents of these registers
69*1e6ebee6SBin Meng *
70*1e6ebee6SBin Meng * Hence we have to do it right here before SPI lock-down bit is set.
71*1e6ebee6SBin Meng */
72*1e6ebee6SBin Meng if (!uclass_first_device_err(UCLASS_SPI, &dev))
73*1e6ebee6SBin Meng ich_spi_config_opcode(dev);
74*1e6ebee6SBin Meng #endif
75*1e6ebee6SBin Meng
7691785f70SSimon Glass /* call into FspNotify */
7791785f70SSimon Glass debug("Calling into FSP (notify phase INIT_PHASE_BOOT): ");
7891785f70SSimon Glass status = fsp_notify(NULL, INIT_PHASE_BOOT);
79ecf674b7SSimon Glass if (status)
8091785f70SSimon Glass debug("fail, error code %x\n", status);
8191785f70SSimon Glass else
8291785f70SSimon Glass debug("OK\n");
8391785f70SSimon Glass
8491785f70SSimon Glass return;
8591785f70SSimon Glass }
86aefaff8eSBin Meng
fsp_prepare_mrc_cache(void)87ff1e18afSBin Meng static __maybe_unused void *fsp_prepare_mrc_cache(void)
88ff1e18afSBin Meng {
89ff1e18afSBin Meng struct mrc_data_container *cache;
90ff1e18afSBin Meng struct mrc_region entry;
91ff1e18afSBin Meng int ret;
92ff1e18afSBin Meng
93ff1e18afSBin Meng ret = mrccache_get_region(NULL, &entry);
94ff1e18afSBin Meng if (ret)
95ff1e18afSBin Meng return NULL;
96ff1e18afSBin Meng
97ff1e18afSBin Meng cache = mrccache_find_current(&entry);
98ff1e18afSBin Meng if (!cache)
99ff1e18afSBin Meng return NULL;
100ff1e18afSBin Meng
101ff1e18afSBin Meng debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__,
102ff1e18afSBin Meng cache->data, cache->data_size, cache->checksum);
103ff1e18afSBin Meng
104ff1e18afSBin Meng return cache->data;
105ff1e18afSBin Meng }
106ff1e18afSBin Meng
107ba65808eSBin Meng #ifdef CONFIG_HAVE_ACPI_RESUME
fsp_save_s3_stack(void)108ba65808eSBin Meng int fsp_save_s3_stack(void)
109ba65808eSBin Meng {
110ba65808eSBin Meng struct udevice *dev;
111ba65808eSBin Meng int ret;
112ba65808eSBin Meng
113ba65808eSBin Meng if (gd->arch.prev_sleep_state == ACPI_S3)
114ba65808eSBin Meng return 0;
115ba65808eSBin Meng
116ba65808eSBin Meng ret = uclass_get_device(UCLASS_RTC, 0, &dev);
117ba65808eSBin Meng if (ret) {
118ba65808eSBin Meng debug("Cannot find RTC: err=%d\n", ret);
119ba65808eSBin Meng return -ENODEV;
120ba65808eSBin Meng }
121ba65808eSBin Meng
122ba65808eSBin Meng /* Save the stack address to CMOS */
123ba65808eSBin Meng ret = rtc_write32(dev, CMOS_FSP_STACK_ADDR, gd->start_addr_sp);
124ba65808eSBin Meng if (ret) {
125ba65808eSBin Meng debug("Save stack address to CMOS: err=%d\n", ret);
126ba65808eSBin Meng return -EIO;
127ba65808eSBin Meng }
128ba65808eSBin Meng
129ba65808eSBin Meng return 0;
130ba65808eSBin Meng }
131ba65808eSBin Meng #endif
132ba65808eSBin Meng
arch_fsp_init(void)133671549e5SSimon Glass int arch_fsp_init(void)
134aefaff8eSBin Meng {
135ff1e18afSBin Meng void *nvs;
136ba65808eSBin Meng int stack = CONFIG_FSP_TEMP_RAM_ADDR;
1371206723bSBin Meng int boot_mode = BOOT_FULL_CONFIG;
1381206723bSBin Meng #ifdef CONFIG_HAVE_ACPI_RESUME
1391206723bSBin Meng int prev_sleep_state = chipset_prev_sleep_state();
140b727961bSBin Meng gd->arch.prev_sleep_state = prev_sleep_state;
1411206723bSBin Meng #endif
142ff1e18afSBin Meng
14357b10f59SBin Meng if (!gd->arch.hob_list) {
144ff1e18afSBin Meng #ifdef CONFIG_ENABLE_MRC_CACHE
145ff1e18afSBin Meng nvs = fsp_prepare_mrc_cache();
146ff1e18afSBin Meng #else
147ff1e18afSBin Meng nvs = NULL;
148ff1e18afSBin Meng #endif
1491206723bSBin Meng
1501206723bSBin Meng #ifdef CONFIG_HAVE_ACPI_RESUME
1511206723bSBin Meng if (prev_sleep_state == ACPI_S3) {
1521206723bSBin Meng if (nvs == NULL) {
1531206723bSBin Meng /* If waking from S3 and no cache then */
1541206723bSBin Meng debug("No MRC cache found in S3 resume path\n");
1551206723bSBin Meng post_code(POST_RESUME_FAILURE);
1561206723bSBin Meng /* Clear Sleep Type */
1571206723bSBin Meng chipset_clear_sleep_state();
1581206723bSBin Meng /* Reboot */
1591206723bSBin Meng debug("Rebooting..\n");
1601206723bSBin Meng reset_cpu(0);
1611206723bSBin Meng /* Should not reach here.. */
1621206723bSBin Meng panic("Reboot System");
1631206723bSBin Meng }
1641206723bSBin Meng
165ba65808eSBin Meng /*
166ba65808eSBin Meng * DM is not avaiable yet at this point, hence call
167ba65808eSBin Meng * CMOS access library which does not depend on DM.
168ba65808eSBin Meng */
169ba65808eSBin Meng stack = cmos_read32(CMOS_FSP_STACK_ADDR);
1701206723bSBin Meng boot_mode = BOOT_ON_S3_RESUME;
1711206723bSBin Meng }
1721206723bSBin Meng #endif
17357b10f59SBin Meng /*
17457b10f59SBin Meng * The first time we enter here, call fsp_init().
17557b10f59SBin Meng * Note the execution does not return to this function,
17657b10f59SBin Meng * instead it jumps to fsp_continue().
17757b10f59SBin Meng */
178ba65808eSBin Meng fsp_init(stack, boot_mode, nvs);
17957b10f59SBin Meng } else {
18057b10f59SBin Meng /*
18157b10f59SBin Meng * The second time we enter here, adjust the size of malloc()
18257b10f59SBin Meng * pool before relocation. Given gd->malloc_base was adjusted
183ecc30663SAlbert ARIBAUD * after the call to board_init_f_init_reserve() in arch/x86/
184ecc30663SAlbert ARIBAUD * cpu/start.S, we should fix up gd->malloc_limit here.
18557b10f59SBin Meng */
18657b10f59SBin Meng gd->malloc_limit += CONFIG_FSP_SYS_MALLOC_F_LEN;
18757b10f59SBin Meng }
188aefaff8eSBin Meng
189aefaff8eSBin Meng return 0;
190aefaff8eSBin Meng }
191