From 87fb1a6cdbb58d5031f0dcf9b8ddf200df70a068 Mon Sep 17 00:00:00 2001 From: Andrey Petrov Date: Wed, 10 Feb 2016 17:47:03 -0800 Subject: [PATCH] soc/apollolake: Add early serial driver for BOOTBLOCK_CONSOLE Early UART driver is for bootblock and romstage. It is supposed to be used when BOOTBLOCK_CONSOLE is enabled. This also adds few configuration bits in bootblock requiered for serial to be set up. Change-Id: I15520d566f107797e68d618885d4379e73d0fa45 Signed-off-by: Andrey Petrov Reviewed-on: https://review.coreboot.org/13677 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- .../intel/apollolake_rvp/Makefile.inc | 2 +- .../intel/apollolake_rvp/bootblock.c | 30 +++++++++ src/soc/intel/apollolake/Kconfig | 12 ++++ src/soc/intel/apollolake/Makefile.inc | 6 ++ .../intel/apollolake/bootblock/bootblock.c | 30 ++++++++- .../intel/apollolake/include/soc/bootblock.h | 2 + src/soc/intel/apollolake/include/soc/cpu.h | 24 ++++++++ .../apollolake/include/soc/northbridge.h | 26 ++++++++ .../intel/apollolake/include/soc/pci_devs.h | 40 ++++++++++++ src/soc/intel/apollolake/include/soc/uart.h | 28 +++++++++ src/soc/intel/apollolake/tsc_freq.c | 20 ++++++ src/soc/intel/apollolake/uart_early.c | 61 +++++++++++++++++++ 12 files changed, 279 insertions(+), 2 deletions(-) create mode 100644 src/mainboard/intel/apollolake_rvp/bootblock.c create mode 100644 src/soc/intel/apollolake/include/soc/cpu.h create mode 100644 src/soc/intel/apollolake/include/soc/northbridge.h create mode 100644 src/soc/intel/apollolake/include/soc/pci_devs.h create mode 100644 src/soc/intel/apollolake/include/soc/uart.h create mode 100644 src/soc/intel/apollolake/tsc_freq.c create mode 100644 src/soc/intel/apollolake/uart_early.c diff --git a/src/mainboard/intel/apollolake_rvp/Makefile.inc b/src/mainboard/intel/apollolake_rvp/Makefile.inc index a48936e5da..8501868fbf 100644 --- a/src/mainboard/intel/apollolake_rvp/Makefile.inc +++ b/src/mainboard/intel/apollolake_rvp/Makefile.inc @@ -1 +1 @@ -# Nothing yet here +bootblock-y += bootblock.c diff --git a/src/mainboard/intel/apollolake_rvp/bootblock.c b/src/mainboard/intel/apollolake_rvp/bootblock.c new file mode 100644 index 0000000000..c1b7d411aa --- /dev/null +++ b/src/mainboard/intel/apollolake_rvp/bootblock.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2016 Intel Corp. + * (Written by Andrey Petrov for 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. + */ + +#include +#include +#include +#include +#include + +static struct pad_config aplk_rvp_gpios[] = { + PAD_CFG_NF(GPIO_46, NATIVE, DEEP, NF1), /* UART2 RX*/ + PAD_CFG_NF(GPIO_47, NATIVE, DEEP, NF1) /* UART2 TX*/ +}; + +void bootblock_mainboard_early_init(void) +{ + if (IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE)) { + gpio_configure_pads(aplk_rvp_gpios, ARRAY_SIZE(aplk_rvp_gpios)); + lpss_console_uart_init(); + } +} diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig index e39fc9c25f..dcfbad65a8 100644 --- a/src/soc/intel/apollolake/Kconfig +++ b/src/soc/intel/apollolake/Kconfig @@ -32,6 +32,13 @@ config CPU_SPECIFIC_OPTIONS select RELOCATABLE_RAMSTAGE # Build fails if this is not selected select SOC_INTEL_COMMON select UDELAY_TSC + select CONSOLE_SERIAL + select BOOTBLOCK_CONSOLE + select TSC_CONSTANT_RATE + select UDELAY_TSC + select TSC_CONSTANT_RATE + select NO_UART_ON_SUPERIO + select DRIVERS_UART_8250MEM_32 config MMCONF_BASE_ADDRESS hex "PCI MMIO Base Address" @@ -63,4 +70,9 @@ config CPU_ADDR_BITS int default 36 +config CONSOLE_UART_BASE_ADDRESS + depends on CONSOLE_SERIAL + hex "MMIO base address for UART" + default 0xde000000 + endif diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc index e58be867fc..7f8beb0c62 100644 --- a/src/soc/intel/apollolake/Makefile.inc +++ b/src/soc/intel/apollolake/Makefile.inc @@ -9,14 +9,20 @@ subdirs-y += ../../../cpu/x86/tsc bootblock-y += bootblock/bootblock.c bootblock-y += bootblock/cache_as_ram.S +bootblock-y += bootblock/bootblock.c bootblock-y += gpio.c bootblock-y += placeholders.c +bootblock-y += tsc_freq.c +bootblock-y += uart_early.c romstage-y += placeholders.c romstage-y += gpio.c +romstage-y += uart_early.c + smm-y += placeholders.c ramstage-y += placeholders.c ramstage-y += gpio.c +ramstage-y += uart_early.c CPPFLAGS_common += -I$(src)/soc/intel/apollolake/include diff --git a/src/soc/intel/apollolake/bootblock/bootblock.c b/src/soc/intel/apollolake/bootblock/bootblock.c index dc0b183bba..d3a78e106f 100644 --- a/src/soc/intel/apollolake/bootblock/bootblock.c +++ b/src/soc/intel/apollolake/bootblock/bootblock.c @@ -1,6 +1,34 @@ -#include +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2016 Intel Corp. + * (Written by Andrey Petrov for 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. + */ #include +#include +#include +#include +#include +#include void asmlinkage bootblock_c_entry(void) { + device_t dev = NB_DEV_ROOT; + + /* Set PCI Express BAR */ + pci_io_write_config32(dev, PCIEXBAR, CONFIG_MMCONF_BASE_ADDRESS | 1); + + dev = P2SB_DEV; + /* BAR and MMIO enable for IOSF, so that GPIOs can be configured */ + pci_write_config32(dev, PCI_BASE_ADDRESS_0, CONFIG_IOSF_BASE_ADDRESS); + pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0); + pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + + /* Call lib/bootblock.c main */ + main(); } diff --git a/src/soc/intel/apollolake/include/soc/bootblock.h b/src/soc/intel/apollolake/include/soc/bootblock.h index 933c7fecd4..655188bf62 100644 --- a/src/soc/intel/apollolake/include/soc/bootblock.h +++ b/src/soc/intel/apollolake/include/soc/bootblock.h @@ -3,4 +3,6 @@ #include void asmlinkage bootblock_c_entry(void); +/* provide prototype for lib/bootblock.c main as workaround */ +void main(void); #endif diff --git a/src/soc/intel/apollolake/include/soc/cpu.h b/src/soc/intel/apollolake/include/soc/cpu.h new file mode 100644 index 0000000000..bee58b206e --- /dev/null +++ b/src/soc/intel/apollolake/include/soc/cpu.h @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Intel Corp. + * (Written by Alexandru Gagniuc for 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. + */ + +#ifndef _SOC_APOLLOLAKE_CPU_H_ +#define _SOC_APOLLOLAKE_CPU_H_ + +#include + +#define CPUID_APOLLOLAKE_A0 0x506c8 + +#define MSR_PLATFORM_INFO 0xce + +#define BASE_CLOCK_MHZ 100 + +#endif /* _SOC_APOLLOLAKE_CPU_H_ */ diff --git a/src/soc/intel/apollolake/include/soc/northbridge.h b/src/soc/intel/apollolake/include/soc/northbridge.h new file mode 100644 index 0000000000..4a071cb788 --- /dev/null +++ b/src/soc/intel/apollolake/include/soc/northbridge.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Intel Corp. + * (Written by Andrey Petrov for 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. + */ + +#ifndef _SOC_APOLLOLAKE_NORTHBRIDGE_H_ +#define _SOC_APOLLOLAKE_NORTHBRIDGE_H_ + +#define MCHBAR 0x48 +#define PCIEXBAR 0x60 +#define PCIEX_SIZE (256 * MiB) + +#define BDSM 0xb0 /* Base Data Stolen Memory */ +#define BGSM 0xb4 /* Base GTT Stolen Memory */ +#define TSEG 0xb8 /* TSEG base */ +#define TOLUD 0xbc /* Top of Low Used Memory */ +#define TOUUD 0xa8 /* Top of Upper Usable DRAM */ + +#endif /* _SOC_APOLLOLAKE_NORTHBRIDGE_H_ */ diff --git a/src/soc/intel/apollolake/include/soc/pci_devs.h b/src/soc/intel/apollolake/include/soc/pci_devs.h new file mode 100644 index 0000000000..3116389090 --- /dev/null +++ b/src/soc/intel/apollolake/include/soc/pci_devs.h @@ -0,0 +1,40 @@ +#ifndef _SOC_APOLLOLAKE_PCI_DEVS_H_ +#define _SOC_APOLLOLAKE_PCI_DEVS_H_ + +#include + +#define _NB_DEVFN(slot) PCI_DEVFN(NB_DEV_SLOT_ ## slot, 0) +#define _LPSS_PCI_DEVFN(slot, func) PCI_DEVFN(LPSS_DEV_SLOT_##slot, func) + + +#if ENV_RAMSTAGE +#include +#include +#define _NB_DEV(slot) dev_find_slot(0, _NB_DEVFN(slot)) +#define _LPSS_PCI_DEV(slot, func) dev_find_slot(0, _LPSS_PCI_DEVFN(slot, func)) +#else +#include +#define _NB_DEV(slot) PCI_DEV(0, NB_DEV_SLOT_ ## slot, 0) +#define _LPSS_PCI_DEV(slot, func) PCI_DEV(0, LPSS_DEV_SLOT_##slot, func) +#endif + +/* North bridge devices */ +#define NB_DEV_SLOT_ROOT 0x00 +#define NB_DEVFN_ROOT _NB_DEVFN(ROOT) +#define NB_DEV_ROOT _NB_DEV(ROOT) + +/* LPSS UART */ +#define LPSS_DEV_SLOT_UART 0x18 +#define LPSS_DEVFN_UART0 _LPSS_PCI_DEVFN(UART, 0) +#define LPSS_DEVFN_UART1 _LPSS_PCI_DEVFN(UART, 1) +#define LPSS_DEVFN_UART2 _LPSS_PCI_DEVFN(UART, 2) +#define LPSS_DEVFN_UART3 _LPSS_PCI_DEVFN(UART, 3) +#define LPSS_DEV_UART0 _LPSS_PCI_DEV(UART, 0) +#define LPSS_DEV_UART1 _LPSS_PCI_DEV(UART, 1) +#define LPSS_DEV_UART2 _LPSS_PCI_DEV(UART, 2) +#define LPSS_DEV_UART3 _LPSS_PCI_DEV(UART, 3) + +#define P2SB_DEV PCI_DEV(0, 0xd, 0) +#define PMC_DEV PCI_DEV(0, 0xd, 1) + +#endif diff --git a/src/soc/intel/apollolake/include/soc/uart.h b/src/soc/intel/apollolake/include/soc/uart.h new file mode 100644 index 0000000000..fd535fba23 --- /dev/null +++ b/src/soc/intel/apollolake/include/soc/uart.h @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Intel Corp. + * (Written by Alexandru Gagniuc for 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. + */ + +#ifndef _SOC_APOLLOLAKE_UART_H_ +#define _SOC_APOLLOLAKE_UART_H_ + +/* Clock is 100MHz * (M / N).*/ +#define UART_CLK 0x200 +# define UART_CLK_UPDATE (1 << 31) +# define UART_CLK_DIV_N(n) (((n) & 0x7fff) << 16) +# define UART_CLK_DIV_M(m) (((m) & 0x7fff) << 1) +# define UART_CLK_EN (1 << 0) +#define UART_RESET 0x204 +# define UART_RESET_DMA_EN (1 << 2) +# define UART_RESET_UART_EN (3 << 0) + +void lpss_console_uart_init(void); + +#endif /* _SOC_APOLLOLAKE_UART_H_ */ diff --git a/src/soc/intel/apollolake/tsc_freq.c b/src/soc/intel/apollolake/tsc_freq.c new file mode 100644 index 0000000000..b6320eda8f --- /dev/null +++ b/src/soc/intel/apollolake/tsc_freq.c @@ -0,0 +1,20 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 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. + */ + +#include +#include +#include + +unsigned long tsc_freq_mhz(void) +{ + msr_t msr = rdmsr(MSR_PLATFORM_INFO); + return (BASE_CLOCK_MHZ * ((msr.lo >> 8) & 0xff)); +} diff --git a/src/soc/intel/apollolake/uart_early.c b/src/soc/intel/apollolake/uart_early.c new file mode 100644 index 0000000000..d3b1d80fc3 --- /dev/null +++ b/src/soc/intel/apollolake/uart_early.c @@ -0,0 +1,61 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Intel Corp. + * (Written by Alexandru Gagniuc for 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. + */ + +#include +#include +#include +#include +#include + +static void lpss_uart_write(uint16_t reg, uint32_t val) +{ + uintptr_t base = CONFIG_CONSOLE_UART_BASE_ADDRESS | reg; + write32((void *)base, val); +} + +void lpss_console_uart_init(void) +{ + uint32_t clk_sel; + device_t uart = _LPSS_PCI_DEV(UART, CONFIG_UART_FOR_CONSOLE & 3); + + if (CONFIG_UART_FOR_CONSOLE > 2) + return; + + /* Enable BAR0 for the UART -- this is where the 8250 registers hide */ + pci_write_config32(uart, PCI_BASE_ADDRESS_0, + CONFIG_CONSOLE_UART_BASE_ADDRESS); + + /* Enable memory access and bus master */ + pci_write_config32(uart, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + /* Take UART out of reset */ + lpss_uart_write(UART_RESET, UART_RESET_UART_EN); + + /* These values get us a 1.836 MHz clock (ideally we want 1.843 MHz) */ + clk_sel = UART_CLK_DIV_N(0x7fff) | UART_CLK_DIV_M(0x025a); + /* Set M and N divisor inputs and enable clock */ + lpss_uart_write(UART_CLK, clk_sel | UART_CLK_UPDATE); + lpss_uart_write(UART_CLK, clk_sel | UART_CLK_EN); + +} + +uintptr_t uart_platform_base(int idx) +{ + return (CONFIG_CONSOLE_UART_BASE_ADDRESS); +} + +unsigned int uart_platform_refclk(void) +{ + /* That's within 0.5% of the actual value we've set earlier */ + return 115200 * 16; +}