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/intel_pinctrl.h>
  22#include <asm/intel_regs.h>
  23#include <asm/io.h>
  24#include <asm/msr.h>
  25#include <asm/mtrr.h>
  26#include <asm/pci.h>
  27#include <asm/arch/cpu.h>
  28#include <asm/arch/gpio.h>
  29#include <asm/arch/iomap.h>
  30#include <asm/arch/lpc.h>
  31#include <asm/arch/pch.h>
  32#include <asm/arch/systemagent.h>
  33#include <asm/arch/uart.h>
  34#include <asm/fsp2/fsp_api.h>
  35#include <linux/sizes.h>
  36#include <power/acpi_pmc.h>
  37
  38/* Define this here to avoid referencing any drivers for the debug UART 1 */
  39#define PCH_DEV_P2SB    PCI_BDF(0, 0x0d, 0)
  40
  41static void pch_uart_init(void)
  42{
  43        /*
  44         * Set up the pinmux so that the UART rx/tx signals are connected
  45         * outside the SoC.
  46         *
  47         * There are about 500 lines of code required to program the GPIO
  48         * configuration for the UARTs. But it boils down to four writes, and
  49         * for the debug UART we want the minimum possible amount of code before
  50         * the UART is running. So just add the magic writes here. See
  51         * apl_hostbridge_early_init_pinctrl() for the full horror.
  52         */
  53        if (PCI_FUNC(PCH_DEV_UART) == 1) {
  54                writel(0x40000402, 0xd0c50650);
  55                writel(0x3c47, 0xd0c50654);
  56                writel(0x40000400, 0xd0c50658);
  57                writel(0x3c48, 0xd0c5065c);
  58        } else { /* UART2 */
  59                writel(0x40000402, 0xd0c50670);
  60                writel(0x3c4b, 0xd0c50674);
  61                writel(0x40000400, 0xd0c50678);
  62                writel(0x3c4c, 0xd0c5067c);
  63        }
  64
  65#ifdef CONFIG_DEBUG_UART
  66        apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE);
  67#endif
  68}
  69
  70static void p2sb_enable_bar(ulong bar)
  71{
  72        /* Enable PCR Base address in PCH */
  73        pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar,
  74                             PCI_SIZE_32);
  75        pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32);
  76
  77        /* Enable P2SB MSE */
  78        pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND,
  79                             PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY,
  80                             PCI_SIZE_8);
  81}
  82
  83/*
  84 * board_debug_uart_init() - Init the debug UART ready for use
  85 *
  86 * This is the minimum init needed to get the UART running. It avoids any
  87 * drivers or complex code, so that the UART is running as soon as possible.
  88 */
  89void board_debug_uart_init(void)
  90{
  91        p2sb_enable_bar(IOMAP_P2SB_BAR);
  92        pch_uart_init();
  93}
  94
  95static int fast_spi_cache_bios_region(void)
  96{
  97        uint map_size, offset;
  98        ulong map_base, base;
  99        int ret;
 100
 101        ret = fast_spi_early_init(PCH_DEV_SPI, IOMAP_SPI_BASE);
 102        if (ret)
 103                return log_msg_ret("early_init", ret);
 104
 105        ret = fast_spi_get_bios_mmap(PCH_DEV_SPI, &map_base, &map_size,
 106                                     &offset);
 107        if (ret)
 108                return log_msg_ret("get_mmap", ret);
 109
 110        base = SZ_4G - map_size;
 111        mtrr_set_next_var(MTRR_TYPE_WRPROT, base, map_size);
 112        log_debug("BIOS cache base=%lx, size=%x\n", base, (uint)map_size);
 113
 114        return 0;
 115}
 116
 117static void enable_pm_timer_emulation(struct udevice *pmc)
 118{
 119        struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(pmc);
 120        msr_t msr;
 121
 122        /*
 123         * The derived frequency is calculated as follows:
 124         *    (CTC_FREQ * msr[63:32]) >> 32 = target frequency.
 125         *
 126         * Back-solve the multiplier so the 3.579545MHz ACPI timer frequency is
 127         * used.
 128         */
 129        msr.hi = (3579545ULL << 32) / CTC_FREQ;
 130
 131        /* Set PM1 timer IO port and enable */
 132        msr.lo = EMULATE_PM_TMR_EN | (upriv->acpi_base + R_ACPI_PM1_TMR);
 133        debug("PM timer %x %x\n", msr.hi, msr.lo);
 134        msr_write(MSR_EMULATE_PM_TIMER, msr);
 135}
 136
 137static void google_chromeec_ioport_range(uint *out_basep, uint *out_sizep)
 138{
 139        uint base;
 140        uint size;
 141
 142        if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC_MEC)) {
 143                base = MEC_EMI_BASE;
 144                size = MEC_EMI_SIZE;
 145        } else {
 146                base = EC_HOST_CMD_REGION0;
 147                size = 2 * EC_HOST_CMD_REGION_SIZE;
 148                /* Make sure MEMMAP region follows host cmd region */
 149                assert(base + size == EC_LPC_ADDR_MEMMAP);
 150                size += EC_MEMMAP_SIZE;
 151        }
 152
 153        *out_basep = base;
 154        *out_sizep = size;
 155}
 156
 157static void early_ec_init(void)
 158{
 159        uint base, size;
 160
 161        /*
 162         * Set up LPC decoding for the Chrome OS EC I/O port ranges:
 163         * - Ports 62/66, 60/64, and 200->208
 164         * - Chrome OS EC communication I/O ports
 165         */
 166        lpc_enable_fixed_io_ranges(LPC_IOE_EC_62_66 | LPC_IOE_KBC_60_64 |
 167                                   LPC_IOE_LGE_200);
 168        google_chromeec_ioport_range(&base, &size);
 169        lpc_open_pmio_window(base, size);
 170}
 171
 172static int arch_cpu_init_tpl(void)
 173{
 174        struct udevice *pmc, *sa, *p2sb, *serial, *spi, *lpc;
 175        int ret;
 176
 177        ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
 178        if (ret)
 179                return log_msg_ret("PMC", ret);
 180
 181        /* Clear global reset promotion bit */
 182        ret = pmc_global_reset_set_enable(pmc, false);
 183        if (ret)
 184                return log_msg_ret("disable global reset", ret);
 185
 186        enable_pm_timer_emulation(pmc);
 187
 188        ret = uclass_first_device_err(UCLASS_P2SB, &p2sb);
 189        if (ret)
 190                return log_msg_ret("p2sb", ret);
 191        ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &sa);
 192        if (ret)
 193                return log_msg_ret("northbridge", ret);
 194        gd->baudrate = CONFIG_BAUDRATE;
 195        ret = uclass_first_device_err(UCLASS_SERIAL, &serial);
 196        if (ret)
 197                return log_msg_ret("serial", ret);
 198        if (CONFIG_IS_ENABLED(SPI_FLASH_SUPPORT)) {
 199                ret = uclass_first_device_err(UCLASS_SPI, &spi);
 200                if (ret)
 201                        return log_msg_ret("SPI", ret);
 202        } else {
 203                /* Alternative code if we don't have SPI in TPL */
 204                if (IS_ENABLED(CONFIG_APL_BOOT_FROM_FAST_SPI_FLASH))
 205                        printf("Warning: Enable APL_SPI_FLASHBOOT to use SPI-flash driver in TPL");
 206                ret = fast_spi_cache_bios_region();
 207                if (ret)
 208                        return log_msg_ret("BIOS cache", ret);
 209        }
 210        ret = pmc_disable_tco(pmc);
 211        if (ret)
 212                return log_msg_ret("disable TCO", ret);
 213        ret = pmc_gpe_init(pmc);
 214        if (ret)
 215                return log_msg_ret("pmc_gpe", ret);
 216        ret = uclass_first_device_err(UCLASS_LPC, &lpc);
 217        if (ret)
 218                return log_msg_ret("lpc", ret);
 219
 220        early_ec_init();
 221
 222        return 0;
 223}
 224
 225/*
 226 * Enables several BARs and devices which are needed for memory init
 227 * - MCH_BASE_ADDR is needed in order to talk to the memory controller
 228 * - HPET is enabled because FSP wants to store a pointer to global data in the
 229 *   HPET comparator register
 230 */
 231static int arch_cpu_init_spl(void)
 232{
 233        struct udevice *pmc, *p2sb;
 234        int ret;
 235
 236        ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
 237        if (ret)
 238                return log_msg_ret("Could not probe PMC", ret);
 239        ret = uclass_first_device_err(UCLASS_P2SB, &p2sb);
 240        if (ret)
 241                return log_msg_ret("Cannot set up p2sb", ret);
 242
 243        lpc_io_setup_comm_a_b();
 244
 245        /* TODO(sjg@chromium.org): Enable upper RTC bank here */
 246
 247        ret = pmc_init(pmc);
 248        if (ret < 0)
 249                return log_msg_ret("Could not init PMC", ret);
 250        if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) {
 251                ret = pmc_prev_sleep_state(pmc);
 252                if (ret < 0)
 253                        return log_msg_ret("Could not get PMC sleep state",
 254                                           ret);
 255                gd->arch.prev_sleep_state = ret;
 256        }
 257
 258        return 0;
 259}
 260
 261int arch_cpu_init(void)
 262{
 263        int ret = 0;
 264
 265        if (spl_phase() == PHASE_TPL)
 266                ret = arch_cpu_init_tpl();
 267        else if (spl_phase() == PHASE_SPL)
 268                ret = arch_cpu_init_spl();
 269        if (ret)
 270                printf("%s: Error %d\n", __func__, ret);
 271
 272        return ret;
 273}
 274