summaryrefslogtreecommitdiff
path: root/src/soc/intel/denverton_ns/bootblock
diff options
context:
space:
mode:
authorMariusz Szafranski <mariuszx.szafranski@intel.com>2017-08-02 17:28:17 +0200
committerPatrick Georgi <pgeorgi@google.com>2017-09-05 13:39:54 +0000
commita404133547c98094a326f60b83e1576ba94b8c06 (patch)
tree59847d084c0462833878627491cfbf3e67fca4af /src/soc/intel/denverton_ns/bootblock
parent84c4987eae9f8686e6d92e38ee18744d69576f2d (diff)
downloadcoreboot-a404133547c98094a326f60b83e1576ba94b8c06.tar.xz
soc/intel/denverton_ns: Add support for Intel Atom C3000 SoC
This change adds support for Intel Atom C3000 SoC ("Denverton" and "Denverton-NS"). Code is partially based on Apollo Lake/Skylake code. Change-Id: I53d69aede3b92f1fe06b74a96cc40187fb9825f1 Signed-off-by: Mariusz Szafranski <mariuszx.szafranski@intel.com> Reviewed-on: https://review.coreboot.org/20861 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: FEI WANG <wangfei.jimei@gmail.com>
Diffstat (limited to 'src/soc/intel/denverton_ns/bootblock')
-rw-r--r--src/soc/intel/denverton_ns/bootblock/bootblock.c72
-rw-r--r--src/soc/intel/denverton_ns/bootblock/cache_as_ram_fsp.S122
-rw-r--r--src/soc/intel/denverton_ns/bootblock/uart.c198
3 files changed, 392 insertions, 0 deletions
diff --git a/src/soc/intel/denverton_ns/bootblock/bootblock.c b/src/soc/intel/denverton_ns/bootblock/bootblock.c
new file mode 100644
index 0000000000..6179bf7c21
--- /dev/null
+++ b/src/soc/intel/denverton_ns/bootblock/bootblock.c
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 - 2017 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/cpu.h>
+#include <bootblock_common.h>
+#include <cpu/x86/mtrr.h>
+#include <device/pci.h>
+#include <FsptUpd.h>
+#include <intelblocks/fast_spi.h>
+#include <lib.h>
+#include <soc/bootblock.h>
+#include <soc/iomap.h>
+#include <spi-generic.h>
+#include <timestamp.h>
+#include <console/console.h>
+
+const FSPT_UPD temp_ram_init_params = {
+ .FspUpdHeader = {
+ .Signature = 0x545F445055564E44ULL,
+ .Revision = 1,
+ .Reserved = {0},
+ },
+ .FsptCoreUpd = {
+ .MicrocodeRegionBase =
+ (UINT32)CONFIG_CPU_MICROCODE_CBFS_LOC,
+ .MicrocodeRegionLength =
+ (UINT32)CONFIG_CPU_MICROCODE_CBFS_LEN,
+ .CodeRegionBase =
+ (UINT32)(0x100000000ULL - CONFIG_CBFS_SIZE),
+ .CodeRegionLength = (UINT32)CONFIG_CBFS_SIZE,
+ .Reserved1 = {0},
+ },
+ .FsptConfig = {
+ .PcdFsptPort80RouteDisable = 0,
+ .ReservedTempRamInitUpd = {0},
+ },
+ .UnusedUpdSpace0 = {0},
+ .UpdTerminator = 0x55AA,
+};
+
+asmlinkage void bootblock_c_entry(uint64_t base_timestamp)
+{
+ /* Call lib/bootblock.c main */
+ bootblock_main_with_timestamp(base_timestamp);
+};
+
+void bootblock_soc_early_init(void)
+{
+
+#if (IS_ENABLED(CONFIG_CONSOLE_SERIAL))
+ early_uart_init();
+#endif
+};
+
+void bootblock_soc_init(void)
+{
+ if (IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE))
+ printk(BIOS_DEBUG, "FSP TempRamInit successful...\n");
+};
diff --git a/src/soc/intel/denverton_ns/bootblock/cache_as_ram_fsp.S b/src/soc/intel/denverton_ns/bootblock/cache_as_ram_fsp.S
new file mode 100644
index 0000000000..b998c21ff7
--- /dev/null
+++ b/src/soc/intel/denverton_ns/bootblock/cache_as_ram_fsp.S
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 - 2017 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <device/pci_def.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/cr.h>
+#include <cpu/x86/post_code.h>
+
+#include <../../../arch/x86/walkcbfs.S>
+
+#define FSP_HDR_OFFSET 0x94
+
+.extern temp_ram_init_params
+
+.global bootblock_pre_c_entry
+bootblock_pre_c_entry:
+
+.global cache_as_ram
+cache_as_ram:
+ post_code(0x2f)
+
+ /* find fsp in cbfs */
+ lea fsp_name, %esi
+ mov $1f, %esp
+ jmp walkcbfs_asm
+1:
+ cmp $0, %eax
+ jz .halt_forever
+ mov CBFS_FILE_OFFSET(%eax), %ebx
+ bswap %ebx
+ add %eax, %ebx
+
+ addl $FSP_HDR_OFFSET, %ebx
+
+ /*
+ * save mm2 into ebp, because TempRamInit API doesn't preserve
+ * mm2 register
+ */
+ movd %mm2, %ebp
+
+ /*
+ * ebx = FSP INFO HEADER
+ * Calculate entry into FSP
+ */
+ movl 0x30(%ebx), %eax /* Load TempRamInitEntryOffset */
+ addl 0x1c(%ebx), %eax /* add the FSP ImageBase */
+
+ /*
+ * Pass early init variables on a fake stack (no memory yet)
+ * as well as the return location
+ */
+ leal CAR_init_stack, %esp
+
+ /* call FSP binary to setup temporary stack */
+ jmp *%eax
+
+/*
+ * If the TempRamInit API is successful, then when returning, the ECX and
+ * EDX registers will point to the temporary but writeable memory range
+ * available to the bootloader where ECX is the start and EDX is the end of
+ * the range i.e. [ECX,EDX). See Denverton_ns FSP Integration Guide for more
+ * information.
+ *
+ * Return Values:
+ * EAX | Return Status
+ * ECX | Temporary Memory Start
+ * EDX | Temporary Memory End
+ * EBX, EDI, ESI, EBP, MM0, MM1 | Preserved Through API Call
+ */
+
+CAR_init_done:
+ cmp $0, %eax
+ jnz .halt_forever
+
+ /* clear CAR_GLOBAL area as it is not shared */
+ cld
+ xor %eax, %eax
+ movl $(_car_global_end), %ecx
+ movl $(_car_global_start), %edi
+ sub %edi, %ecx
+ shrl $2, %ecx
+ rep stosl
+
+ /* Setup bootblock stack */
+ movl $(_car_stack_end), %esp
+
+ /* Restore the timestamp from bootblock_crt0.S (ebp:mm1) */
+ push %ebp
+ movd %mm1, %eax
+ push %eax
+
+ /* We can call into C functions now */
+ call bootblock_c_entry
+
+ /* Never reached */
+
+.halt_forever:
+ post_code(POST_DEAD_CODE)
+ hlt
+ jmp .halt_forever
+
+ .align 4
+CAR_init_stack:
+ .long CAR_init_done
+ .long temp_ram_init_params
+
+fsp_name:
+ .ascii "fspt.bin\x00"
diff --git a/src/soc/intel/denverton_ns/bootblock/uart.c b/src/soc/intel/denverton_ns/bootblock/uart.c
new file mode 100644
index 0000000000..bad16de6b7
--- /dev/null
+++ b/src/soc/intel/denverton_ns/bootblock/uart.c
@@ -0,0 +1,198 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 - 2017 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <device/pci_def.h>
+#include <fsp/soc_binding.h>
+#include <commonlib/helpers.h>
+
+#include <soc/bootblock.h>
+#include <soc/gpio_defs.h>
+#include <soc/uart.h>
+
+static uint16_t legacy_uart_ioadr_tab[] = {0x3F8, 0x2F8, 0x3E8, 0x2E8};
+
+#define ELEM_OF_UART_TAB ARRAY_SIZE(legacy_uart_ioadr_tab)
+
+static void pci_early_hsuart_device_probe(u8 bus, u8 dev, u8 func,
+ u32 mmio_base)
+{
+ register uint16_t reg16;
+
+ device_t uart_dev = PCI_DEV(bus, dev, func);
+
+ /* We're using MMIO for HSUARTs. This section is needed for logging
+ * from FSP only
+ */
+ /* Decode IOBASE at IOBA (BAR0). */
+ reg16 = pci_read_config16(uart_dev, PCI_BASE_ADDRESS_0) | mmio_base;
+ pci_write_config16(uart_dev, PCI_BASE_ADDRESS_0, reg16);
+
+#if (IS_ENABLED(CONFIG_NON_LEGACY_UART_MODE))
+ /* Decode MMIO at MEMBA (BAR1) */
+ pci_write_config32(uart_dev, PCI_BASE_ADDRESS_1,
+ CONFIG_CONSOLE_UART_BASE_ADDRESS +
+ SIZE_OF_HSUART_RES * func);
+#endif
+
+ /* Enable memory/io space and allow to initiate
+ * a transaction as a master
+ */
+ pci_write_config16(uart_dev, PCI_COMMAND,
+ pci_read_config16(uart_dev, PCI_COMMAND) |
+#if (IS_ENABLED(CONFIG_NON_LEGACY_UART_MODE))
+ PCI_COMMAND_MEMORY |
+#endif
+ PCI_COMMAND_MASTER | PCI_COMMAND_IO);
+
+#if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_230400))
+ /* Change the highest speed to 230400 */
+ uint32_t *psr_reg =
+ (uint32_t *)(CONFIG_CONSOLE_UART_BASE_ADDRESS +
+ SIZE_OF_HSUART_RES * func + PSR_OFFSET);
+ *psr_reg >>= 1;
+#endif
+
+#if (IS_ENABLED(CONFIG_LEGACY_UART_MODE))
+ /* Hide HSUART on PCI to prevent re-enumeration
+ * and enable legacy mode.
+ */
+ pci_write_config32(uart_dev, PCI_FUNC_RDCFG_HIDE,
+ pci_read_config32(uart_dev, PCI_FUNC_RDCFG_HIDE) |
+ 1);
+#endif
+}
+
+static void early_config_gpio(void)
+{
+ uint32_t reg32;
+
+ // HSUART0:
+ // UART0_RXD
+ reg32 = read32(
+ (void *)PCH_PCR_ADDRESS(PID_GPIOCOM1, R_PAD_CFG_DW0_UART0_RXD));
+ if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
+ V_PCH_GPIO_PAD_MODE_NAT_1) {
+ reg32 &= ~B_PCH_GPIO_PAD_MODE;
+ reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
+ << N_PCH_GPIO_PAD_MODE);
+ write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_UART0_RXD),
+ reg32);
+ }
+ // UART0_TXD
+ reg32 = read32(
+ (void *)PCH_PCR_ADDRESS(PID_GPIOCOM1, R_PAD_CFG_DW0_UART0_TXD));
+ if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
+ V_PCH_GPIO_PAD_MODE_NAT_1) {
+ reg32 &= ~B_PCH_GPIO_PAD_MODE;
+ reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
+ << N_PCH_GPIO_PAD_MODE);
+ write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_UART0_TXD),
+ reg32);
+ }
+ // UART0_CTS
+ reg32 = read32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_SMB3_CLTT_CLK));
+ if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
+ V_PCH_GPIO_PAD_MODE_NAT_2) {
+ reg32 &= ~B_PCH_GPIO_PAD_MODE;
+ reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_2
+ << N_PCH_GPIO_PAD_MODE);
+ write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_SMB3_CLTT_CLK),
+ reg32);
+ }
+ // UART0_RTS
+ reg32 = read32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_PCIE_CLKREQ5_N));
+ if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
+ V_PCH_GPIO_PAD_MODE_NAT_3) {
+ reg32 &= ~B_PCH_GPIO_PAD_MODE;
+ reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_3
+ << N_PCH_GPIO_PAD_MODE);
+ write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_PCIE_CLKREQ5_N),
+ reg32);
+ }
+
+ // HSUART1:
+ // UART1_RXD
+ reg32 = read32(
+ (void *)PCH_PCR_ADDRESS(PID_GPIOCOM1, R_PAD_CFG_DW0_UART1_RXD));
+ if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
+ V_PCH_GPIO_PAD_MODE_NAT_1) {
+ reg32 &= ~B_PCH_GPIO_PAD_MODE;
+ reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
+ << N_PCH_GPIO_PAD_MODE);
+ write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_UART1_RXD),
+ reg32);
+ }
+ // UART1_TXD
+ reg32 = read32(
+ (void *)PCH_PCR_ADDRESS(PID_GPIOCOM1, R_PAD_CFG_DW0_UART1_TXD));
+ if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
+ V_PCH_GPIO_PAD_MODE_NAT_1) {
+ reg32 &= ~B_PCH_GPIO_PAD_MODE;
+ reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
+ << N_PCH_GPIO_PAD_MODE);
+ write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_UART1_TXD),
+ reg32);
+ }
+ // UART1_CTS
+ reg32 = read32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_SATA1_SDOUT));
+ if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
+ V_PCH_GPIO_PAD_MODE_NAT_1) {
+ reg32 &= ~B_PCH_GPIO_PAD_MODE;
+ reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
+ << N_PCH_GPIO_PAD_MODE);
+ write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_SATA1_SDOUT),
+ reg32);
+ }
+ // UART1_RTS
+ reg32 = read32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_SATA0_SDOUT));
+ if (((reg32 & B_PCH_GPIO_PAD_MODE) >> N_PCH_GPIO_PAD_MODE) !=
+ V_PCH_GPIO_PAD_MODE_NAT_1) {
+ reg32 &= ~B_PCH_GPIO_PAD_MODE;
+ reg32 |= (UINT32)(V_PCH_GPIO_PAD_MODE_NAT_1
+ << N_PCH_GPIO_PAD_MODE);
+ write32((void *)PCH_PCR_ADDRESS(PID_GPIOCOM1,
+ R_PAD_CFG_DW0_SATA0_SDOUT),
+ reg32);
+ }
+}
+
+void early_uart_init(void)
+{
+ register int i;
+
+ /* Check: do we have enought elements to init. ? */
+ BUILD_BUG_ON(HARCUVAR_UARTS_TO_INI > ELEM_OF_UART_TAB);
+
+ /* HSUART(B0:D26:0-1) GPIO init. */
+ early_config_gpio();
+
+ for (i = HARCUVAR_UARTS_TO_INI - 1; i >= 0; --i) {
+ pci_early_hsuart_device_probe(0, CONFIG_HSUART_DEV, i,
+ legacy_uart_ioadr_tab[i]);
+ }
+}