From a404133547c98094a326f60b83e1576ba94b8c06 Mon Sep 17 00:00:00 2001 From: Mariusz Szafranski Date: Wed, 2 Aug 2017 17:28:17 +0200 Subject: 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 Reviewed-on: https://review.coreboot.org/20861 Tested-by: build bot (Jenkins) Reviewed-by: FEI WANG --- src/soc/intel/denverton_ns/bootblock/bootblock.c | 72 ++++++++ .../denverton_ns/bootblock/cache_as_ram_fsp.S | 122 +++++++++++++ src/soc/intel/denverton_ns/bootblock/uart.c | 198 +++++++++++++++++++++ 3 files changed, 392 insertions(+) create mode 100644 src/soc/intel/denverton_ns/bootblock/bootblock.c create mode 100644 src/soc/intel/denverton_ns/bootblock/cache_as_ram_fsp.S create mode 100644 src/soc/intel/denverton_ns/bootblock/uart.c (limited to 'src/soc/intel/denverton_ns/bootblock') 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 +#include +#include +#include +#include + +#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 +#include +#include +#include + +#include +#include +#include + +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]); + } +} -- cgit v1.2.3