soc/intel/fsp_broadwell_de: Enable early integrated UART

In order to use internal UART it needs to 'enabled'. This is normally done
by FSP. However sometimes internal UART is needed before FSP is invoked.

TEST=check if printk() show up in early romstage. Tested on OCP Monolake.
Tested on out-of-tree mainboard to see if UART on LPC still works.

Signed-off-by: Andrey Petrov <anpetrov@fb.com>
Change-Id: I88a7b1a38abf9a09137f6dd75a5a9dee104daaca
Reviewed-on: https://review.coreboot.org/c/coreboot/+/34683
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-by: Patrick Rudolph <siro@das-labor.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Andrey Petrov 2019-08-01 17:07:47 -07:00
parent 8ce36ac548
commit c0193c9237
4 changed files with 110 additions and 1 deletions

View File

@ -70,7 +70,6 @@ config INTEGRATED_UART
bool "Integrated UART ports"
default y
select DRIVERS_UART_8250IO
select DRIVERS_UART_8250IO_SKIP_INIT
select CONSOLE_SERIAL
help
Use Broadwell-DE Integrated UART ports @3F8h and 2F8h.

View File

@ -0,0 +1,36 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2019 Facebook, Inc.
*
* 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; version 2 of the License.
*
* 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.
*/
/*
* As per "Intel Xeon Processor D-1500 Product Family" volume 2,
* "The UBOX [Processor Utility Box] is the piece of processor logic that deals with
* the non mainstream flows in the system. This includes transactions like the register
* accesses, interrupt flows, lock flows and events. In addition, the UBOX houses
* coordination for the performance architecture, and also houses scratchpad and
* semaphore registers."
*
* In other words, this is a one-die block that has all the useful magic registers.
*/
#ifndef _BROADWELL_UBOX_H_
#define _BROADWELL_UBOX_H_
#define UBOX_UART_ENABLE 0xf8
#define UBOX_UART_ENABLE_PORT0 (1u << 0)
#define UBOX_UART_ENABLE_PORT1 (1u << 1)
#define UBOX_SC_RESET_STATUS 0xc8
#define UBOX_SC_BYPASS (1u << 3)
#endif

View File

@ -0,0 +1,29 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2019 Facebook, Inc.
*
* 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; version 2 of the License.
*
* 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.
*/
#ifndef _BROADWELL_VTD_H_
#define _BROADWELL_VTD_H_
#define VTD_CPUBUSNO 0x108
#define VTD_CPUBUSNO_BUS0_MASK 0xff
#define VTD_CPUBUSNO_BUS0_SHIFT 0
#define VTD_CPUBUSNO_BUS1_MASK 0xff
#define VTD_CPUBUSNO_BUS1_SHIFT 8
#define VTD_CPUBUSNO_ISVALID (1u << 16)
#define VTD_DFX1 0x804
#define VTD_DFX1_RANGE_3F8_DISABLE (1u << 29)
#define VTD_DFX1_RANGE_2F8_DISABLE (1u << 30)
#endif

View File

@ -32,6 +32,8 @@
#include <soc/pci_devs.h>
#include <soc/romstage.h>
#include <soc/gpio.h>
#include <soc/vtd.h>
#include <soc/ubox.h>
#include <build.h>
static void init_rtc(void)
@ -55,6 +57,47 @@ static void setup_gpio_io_address(void)
}
static void enable_integrated_uart(uint8_t port)
{
uint32_t reg32, busno1 = 0, ubox_uart_en = 0, dfx1 = 0;
pci_devfn_t vtd_dev, ubox_dev;
vtd_dev = PCI_DEV(BUS0, VTD_DEV, VTD_FUNC);
/* Figure out what bus number is assigned for CPUBUSNO(1) */
reg32 = pci_mmio_read_config32(vtd_dev, VTD_CPUBUSNO);
busno1 = (reg32 >> VTD_CPUBUSNO_BUS1_SHIFT) & VTD_CPUBUSNO_BUS1_MASK;
/* UBOX sits on CPUBUSNO(1) */
ubox_dev = PCI_DEV(busno1, UBOX_DEV, UBOX_FUNC);
uint32_t reset_sts = pci_mmio_read_config32(ubox_dev, UBOX_SC_RESET_STATUS);
/* In case we are in bypass mode do nothing */
if (reset_sts & UBOX_SC_BYPASS)
return;
dfx1 = pci_mmio_read_config32(vtd_dev, VTD_DFX1);
ubox_uart_en = pci_mmio_read_config32(ubox_dev, UBOX_UART_ENABLE);
switch (port) {
case 0:
ubox_uart_en |= UBOX_UART_ENABLE_PORT0;
dfx1 |= VTD_DFX1_RANGE_3F8_DISABLE;
break;
case 1:
ubox_uart_en |= UBOX_UART_ENABLE_PORT1;
dfx1 |= VTD_DFX1_RANGE_2F8_DISABLE;
break;
default:
printk(BIOS_ERR, "incorrect port number\n");
return;
}
/* Disable decoding and enable the port we want */
pci_mmio_write_config32(vtd_dev, VTD_DFX1, dfx1);
pci_mmio_write_config32(ubox_dev, UBOX_UART_ENABLE, ubox_uart_en);
}
/* Entry from cache-as-ram.inc. */
void *asmlinkage main(FSP_INFO_HEADER *fsp_info_header)
{
@ -65,6 +108,8 @@ void *asmlinkage main(FSP_INFO_HEADER *fsp_info_header)
LPC_IO_DEC, 0x0010);
pci_write_config16(PCI_DEV(0x0, LPC_DEV, LPC_FUNC),
LPC_EN, 0x340f);
} else {
enable_integrated_uart(CONFIG_UART_FOR_CONSOLE);
}
/* Call into mainboard. */