uboot/arch/x86/cpu/apollolake/cpu_spl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright 2019 Google LLC
   4 *
   5 * Portions taken from coreboot
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <ec_commands.h>
  11#include <init.h>
  12#include <log.h>
  13#include <spi_flash.h>
  14#include <spl.h>
  15#include <syscon.h>
  16#include <acpi/acpi_s3.h>
  17#include <asm/cpu.h>
  18#include <asm/cpu_common.h>
  19#include <asm/cpu_x86.h>
  20#include <asm/fast_spi.h>
  21#include <asm/global_data.h>
  22#include <asm/intel_pinctrl.h>
  23#include <asm/intel_regs.h>
  24#include <asm/io.h>
  25#include <asm/msr.h>
  26#include <asm/mtrr.h>
  27#include <asm/pci.h>
  28#include <asm/arch/cpu.h>
  29#include <asm/arch/gpio.h>
  30#include <asm/arch/iomap.h>
  31#include <asm/arch/lpc.h>
  32#include <asm/arch/pch.h>
  33#include <asm/arch/systemagent.h>
  34#include <asm/fsp2/fsp_api.h>
  35#include <linux/sizes.h>
  36#include <power/acpi_pmc.h>
  37
  38static int fast_spi_cache_bios_region(void)
  39{
  40        uint map_size, offset;
  41        ulong map_base, base;
  42        int ret;
  43
  44        ret = fast_spi_early_init(PCH_DEV_SPI, IOMAP_SPI_BASE);
  45        if (ret)
  46                return log_msg_ret("early_init", ret);
  47
  48        ret = fast_spi_get_bios_mmap(PCH_DEV_SPI, &map_base, &map_size,
  49                                     &offset);
  50        if (ret)
  51                return log_msg_ret("get_mmap", ret);
  52
  53        base = SZ_4G - map_size;
  54        mtrr_set_next_var(MTRR_TYPE_WRPROT, base, map_size);
  55        log_debug("BIOS cache base=%lx, size=%x\n", base, (uint)map_size);
  56
  57        return 0;
  58}
  59
  60static void google_chromeec_ioport_range(uint *out_basep, uint *out_sizep)
  61{
  62        uint base;
  63        uint size;
  64
  65        if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_MEC)) {
  66                base = MEC_EMI_BASE;
  67                size = MEC_EMI_SIZE;
  68        } else {
  69                base = EC_HOST_CMD_REGION0;
  70                size = 2 * EC_HOST_CMD_REGION_SIZE;
  71                /* Make sure MEMMAP region follows host cmd region */
  72                assert(base + size == EC_LPC_ADDR_MEMMAP);
  73                size += EC_MEMMAP_SIZE;
  74        }
  75
  76        *out_basep = base;
  77        *out_sizep = size;
  78}
  79
  80static void early_ec_init(void)
  81{
  82        uint base, size;
  83
  84        /*
  85         * Set up LPC decoding for the Chrome OS EC I/O port ranges:
  86         * - Ports 62/66, 60/64, and 200->208
  87         * - Chrome OS EC communication I/O ports
  88         */
  89        lpc_enable_fixed_io_ranges(LPC_IOE_EC_62_66 | LPC_IOE_KBC_60_64 |
  90                                   LPC_IOE_LGE_200);
  91        google_chromeec_ioport_range(&base, &size);
  92        lpc_open_pmio_window(base, size);
  93}
  94
  95static int arch_cpu_init_tpl(void)
  96{
  97        struct udevice *pmc, *sa, *p2sb, *serial, *spi, *lpc;
  98        int ret;
  99
 100        ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
 101        if (ret)
 102                return log_msg_ret("PMC", ret);
 103
 104        /* Clear global reset promotion bit */
 105        ret = pmc_global_reset_set_enable(pmc, false);
 106        if (ret)
 107                return log_msg_ret("disable global reset", ret);
 108
 109        enable_pm_timer_emulation(pmc);
 110
 111        ret = uclass_first_device_err(UCLASS_P2SB, &p2sb);
 112        if (ret)
 113                return log_msg_ret("p2sb", ret);
 114        ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &sa);
 115        if (ret)
 116                return log_msg_ret("northbridge", ret);
 117        gd->baudrate = CONFIG_BAUDRATE;
 118        ret = uclass_first_device_err(UCLASS_SERIAL, &serial);
 119        if (ret)
 120                return log_msg_ret("serial", ret);
 121        if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) {
 122                ret = uclass_first_device_err(UCLASS_SPI, &spi);
 123                if (ret)
 124                        return log_msg_ret("SPI", ret);
 125        } else {
 126                /* Alternative code if we don't have SPI in TPL */
 127                if (IS_ENABLED(CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH))
 128                        printf("Warning: Enable APL_SPI_FLASHBOOT to use SPI-flash driver in TPL");
 129                ret = fast_spi_cache_bios_region();
 130                if (ret)
 131                        return log_msg_ret("BIOS cache", ret);
 132        }
 133        ret = pmc_disable_tco(pmc);
 134        if (ret)
 135                return log_msg_ret("disable TCO", ret);
 136        ret = pmc_gpe_init(pmc);
 137        if (ret)
 138                return log_msg_ret("pmc_gpe", ret);
 139        ret = uclass_first_device_err(UCLASS_LPC, &lpc);
 140        if (ret)
 141                return log_msg_ret("lpc", ret);
 142
 143        early_ec_init();
 144
 145        return 0;
 146}
 147
 148/*
 149 * Enables several BARs and devices which are needed for memory init
 150 * - MCH_BASE_ADDR is needed in order to talk to the memory controller
 151 * - HPET is enabled because FSP wants to store a pointer to global data in the
 152 *   HPET comparator register
 153 */
 154static int arch_cpu_init_spl(void)
 155{
 156        struct udevice *pmc, *p2sb;
 157        int ret;
 158
 159        ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
 160        if (ret)
 161                return log_msg_ret("Could not probe PMC", ret);
 162        ret = uclass_first_device_err(UCLASS_P2SB, &p2sb);
 163        if (ret)
 164                return log_msg_ret("Cannot set up p2sb", ret);
 165
 166        lpc_io_setup_comm_a_b();
 167
 168        /* TODO(sjg@chromium.org): Enable upper RTC bank here */
 169
 170        ret = pmc_init(pmc);
 171        if (ret < 0)
 172                return log_msg_ret("Could not init PMC", ret);
 173        if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) {
 174                ret = pmc_prev_sleep_state(pmc);
 175                if (ret < 0)
 176                        return log_msg_ret("Could not get PMC sleep state",
 177                                           ret);
 178                gd->arch.prev_sleep_state = ret;
 179        }
 180
 181        return 0;
 182}
 183
 184int arch_cpu_init(void)
 185{
 186        int ret = 0;
 187
 188        if (spl_phase() == PHASE_TPL)
 189                ret = arch_cpu_init_tpl();
 190        else if (spl_phase() == PHASE_SPL)
 191                ret = arch_cpu_init_spl();
 192        if (ret)
 193                printf("%s: Error %d\n", __func__, ret);
 194
 195        return ret;
 196}
 197