From afa07f7ae48d9e9d79aef712933777a56551f5be Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Thu, 24 May 2018 12:21:06 +0530 Subject: soc/intel/common/block: Move common uart function to block/uart This patch moves uart functions which are common across multiple soc to block/uart. This will remove redundant code copy from soc {skylake/apollolake/cannonlake}. BUG=b:78109109 BRANCH=none TEST=Build and boot on KBL/APL/CNL platform. Change-Id: I109d0e5c942e499cb763bde47cb7d53dfbf5cef6 Signed-off-by: Maulik V Vaghela Signed-off-by: Subrata Banik Reviewed-on: https://review.coreboot.org/26164 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/soc/intel/common/block/acpi/acpi.c | 2 +- .../intel/common/block/include/intelblocks/uart.h | 56 +++++++-- src/soc/intel/common/block/smm/smihandler.c | 2 +- src/soc/intel/common/block/uart/Makefile.inc | 3 + src/soc/intel/common/block/uart/uart.c | 136 +++++++++++++++++---- 5 files changed, 162 insertions(+), 37 deletions(-) (limited to 'src/soc/intel/common') diff --git a/src/soc/intel/common/block/acpi/acpi.c b/src/soc/intel/common/block/acpi/acpi.c index 01a4928b14..dd42f76d33 100644 --- a/src/soc/intel/common/block/acpi/acpi.c +++ b/src/soc/intel/common/block/acpi/acpi.c @@ -169,7 +169,7 @@ unsigned long southbridge_write_acpi_tables(struct device *device, struct acpi_rsdp *rsdp) { current = acpi_write_dbg2_pci_uart(rsdp, current, - pch_uart_get_debug_controller(), + uart_get_device(), ACPI_ACCESS_SIZE_DWORD_ACCESS); return acpi_write_hpet(device, current, rsdp); } diff --git a/src/soc/intel/common/block/include/intelblocks/uart.h b/src/soc/intel/common/block/include/intelblocks/uart.h index 78feb3e246..545e158b61 100644 --- a/src/soc/intel/common/block/include/intelblocks/uart.h +++ b/src/soc/intel/common/block/include/intelblocks/uart.h @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2017 Intel Corporation. + * Copyright (C) 2017-2018 Intel Corporation. * * 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 @@ -17,14 +17,31 @@ #define SOC_INTEL_COMMON_BLOCK_UART_H #include +#include #include +#include #include +#define MAX_GPIO_PAD_PER_UART 2 + +struct uart_gpio_pad_config { + int console_index; + struct pad_config gpios[MAX_GPIO_PAD_PER_UART]; +}; + +/* + * While using this common UART block for any SOC following is expected from soc + * 1. SOC will define proper UART_BASE which is base address for UART console. + * 2. SOC will return correct device pointer based on console index + * 3. SOC will provide appropriate GPIO pad configuration for UART console + * 4. SOC will allow common code to set UART into legacy mode if supported. + */ + /* * Common routine to initialize UART controller PCI config space, take it out of * reset and configure M/N dividers. */ -void uart_common_init(device_t dev, uintptr_t baseaddr); +void uart_common_init(struct device *dev, uintptr_t baseaddr); /* * Check if UART debug controller is initialized @@ -33,7 +50,7 @@ void uart_common_init(device_t dev, uintptr_t baseaddr); * out of reset * false = otherwise */ -bool uart_debug_controller_is_initialized(void); +bool uart_is_controller_initialized(void); /* * Check if dev corresponds to UART debug port controller. @@ -44,26 +61,41 @@ bool uart_debug_controller_is_initialized(void); */ bool uart_is_debug_controller(struct device *dev); -/**************************** SoC callbacks ***********************************/ - -void pch_uart_read_resources(struct device *dev); +/* + * BootBlock pre initialization of UART console + */ +void uart_bootblock_init(void); /* - * Check if UART debug port controller needs to be initialized on resume. + * Get UART debug controller device structure * * Returns: - * true = when SoC wants common code to do the UART debug port initialization - * false = otherwise + * Pointer to device structure = If device has a UART debug controller. + * NULL = otherwise */ -bool pch_uart_init_debug_controller_on_resume(void); +struct device *uart_get_device(void); + +/**************************** SoC callbacks ***********************************/ /* - * Get UART debug controller device structure + * SoC should implement soc_uart_console_to_device() function to + * get UART debug controller device structure based on console number + * Caller needs to check proper UART console index supported by SoC. + * If wrong UART console index is passed to function, it'll return NULL. + * + * Input: + * UART console index selected in config * * Returns: * Pointer to device structure = If device has a UART debug controller. * NULL = otherwise */ -device_t pch_uart_get_debug_controller(void); +struct device *soc_uart_console_to_device(int uart_console); + +/* + * Set UART to legacy mode + * Put UART in byte access mode for 16550 compatibility + */ +void soc_uart_set_legacy_mode(void); #endif /* SOC_INTEL_COMMON_BLOCK_UART_H */ diff --git a/src/soc/intel/common/block/smm/smihandler.c b/src/soc/intel/common/block/smm/smihandler.c index b49f2a3f3b..c6f9692d81 100644 --- a/src/soc/intel/common/block/smm/smihandler.c +++ b/src/soc/intel/common/block/smm/smihandler.c @@ -208,7 +208,7 @@ void smihandler_southbridge_sleep( case ACPI_S3: printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n"); - gnvs->uior = uart_debug_controller_is_initialized(); + gnvs->uior = uart_is_controller_initialized(); /* Invalidate the cache before going to S3 */ wbinvd(); diff --git a/src/soc/intel/common/block/uart/Makefile.inc b/src/soc/intel/common/block/uart/Makefile.inc index 348b153907..d7a770258f 100644 --- a/src/soc/intel/common/block/uart/Makefile.inc +++ b/src/soc/intel/common/block/uart/Makefile.inc @@ -1,3 +1,6 @@ bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_UART) += uart.c +romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_UART) += uart.c ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_UART) += uart.c smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_UART) += uart.c +postcar-$(CONFIG_SOC_INTEL_COMMON_BLOCK_UART) += uart.c +verstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_UART) += uart.c diff --git a/src/soc/intel/common/block/uart/uart.c b/src/soc/intel/common/block/uart/uart.c index b84a7ec534..12b99e737e 100644 --- a/src/soc/intel/common/block/uart/uart.c +++ b/src/soc/intel/common/block/uart/uart.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2017 Intel Corporation. + * Copyright (C) 2017-2018 Intel Corporation. * * 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 @@ -14,7 +14,10 @@ */ #include +#include #include +#include +#include #include #include #include @@ -22,8 +25,16 @@ #include #include #include +#include +#include +#include +#include #define UART_PCI_ENABLE (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER) +#define UART_CONSOLE_INVALID_INDEX 0xFF + +extern const struct uart_gpio_pad_config uart_gpio_pads[]; +extern const int uart_max_index; static void uart_lpss_init(uintptr_t baseaddr) { @@ -35,8 +46,37 @@ static void uart_lpss_init(uintptr_t baseaddr) CONFIG_SOC_INTEL_COMMON_LPSS_UART_CLK_N_VAL); } -void uart_common_init(device_t dev, uintptr_t baseaddr) +#if IS_ENABLED(CONFIG_DRIVERS_UART_8250MEM) +uintptr_t uart_platform_base(int idx) +{ + /* return Base address for UART console index */ + return UART_BASE_0_ADDR(idx); +} +#endif + +static int uart_get_valid_index(void) +{ + int index; + + for (index = 0; index < uart_max_index; index++) { + if (uart_gpio_pads[index].console_index == + CONFIG_UART_FOR_CONSOLE) + return index; + } + /* For valid index, code should not reach here */ + return UART_CONSOLE_INVALID_INDEX; +} + +void uart_common_init(struct device *device, uintptr_t baseaddr) { +#if defined(__SIMPLE_DEVICE__) + pci_devfn_t dev = (pci_devfn_t)(uintptr_t)device; +#else + struct device *dev = device; +#endif + if (!dev) + return; + /* Set UART base address */ pci_write_config32(dev, PCI_BASE_ADDRESS_0, baseaddr); @@ -46,27 +86,34 @@ void uart_common_init(device_t dev, uintptr_t baseaddr) uart_lpss_init(baseaddr); } -__weak device_t pch_uart_get_debug_controller(void) +struct device *uart_get_device(void) { /* - * device_t can either be a pointer to struct device (e.g. ramstage) or - * a simple integer (e.g. SMM) depending upon whether __SIMPLE_DEVICE__ - * is defined for the stage. Thus, the return requires additional - * casting to uintptr_t. + * This function will get called even if UART_DEBUG config options is + * not selected. + * By default returning NULL in case CONFIG_UART_DEBUG option is not + * selected to avoid compilation errors. */ - return (device_t)(uintptr_t)NULL; + if (!IS_ENABLED(CONFIG_UART_DEBUG)) + return NULL; + + int console_index = uart_get_valid_index(); + + if (console_index != UART_CONSOLE_INVALID_INDEX) + return soc_uart_console_to_device(CONFIG_UART_FOR_CONSOLE); + else + return NULL; } -bool uart_debug_controller_is_initialized(void) +bool uart_is_controller_initialized(void) { + uintptr_t base; + #if defined(__SIMPLE_DEVICE__) - pci_devfn_t dev; + pci_devfn_t dev = (pci_devfn_t)(uintptr_t)uart_get_device(); #else - struct device *dev; + struct device *dev = uart_get_device(); #endif - uintptr_t base; - - dev = pch_uart_get_debug_controller(); if (!dev) return false; @@ -81,22 +128,66 @@ bool uart_debug_controller_is_initialized(void) return !lpss_is_controller_in_reset(base); } +static void uart_configure_gpio_pads(void) +{ + int index = uart_get_valid_index(); + + if (index != UART_CONSOLE_INVALID_INDEX) + gpio_configure_pads(uart_gpio_pads[index].gpios, + MAX_GPIO_PAD_PER_UART); +} + +void uart_bootblock_init(void) +{ + /* Program UART BAR0, command, reset and clock register */ + uart_common_init(uart_get_device(), + UART_BASE(CONFIG_UART_FOR_CONSOLE)); + + if (!IS_ENABLED(CONFIG_DRIVERS_UART_8250MEM_32)) + /* Put UART in byte access mode for 16550 compatibility */ + soc_uart_set_legacy_mode(); + + /* Configure the 2 pads per UART. */ + uart_configure_gpio_pads(); +} + #if ENV_RAMSTAGE -__weak void pch_uart_read_resources(struct device *dev) +static void uart_read_resources(struct device *dev) { pci_dev_read_resources(dev); + + /* Set the configured UART base address for the debug port */ + if (IS_ENABLED(CONFIG_UART_DEBUG) && uart_is_debug_controller(dev)) { + struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0); + /* Need to set the base and size for the resource allocator. */ + res->base = UART_BASE(CONFIG_UART_FOR_CONSOLE); + res->size = UART_BASE_SIZE; + res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | + IORESOURCE_FIXED; + } } -__weak bool pch_uart_init_debug_controller_on_resume(void) +/* + * Check if UART debug port controller needs to be initialized on resume. + * + * Returns: + * true = when SoC wants debug port initialization on resume + * false = otherwise + */ +static bool pch_uart_init_debug_controller_on_resume(void) { - /* By default, do not initialize controller. */ + global_nvs_t *gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + + if (gnvs) + return !!gnvs->uior; + return false; } bool uart_is_debug_controller(struct device *dev) { - return dev == pch_uart_get_debug_controller(); + return dev == uart_get_device(); } /* @@ -126,8 +217,7 @@ static bool uart_controller_needs_init(struct device *dev) return false; /* - * Call SoC specific routine to confirm it wants to initialize - * controller. + * check if SOC wants to initialize UART on resume */ return pch_uart_init_debug_controller_on_resume(); } @@ -146,7 +236,7 @@ static void uart_common_enable_resources(struct device *dev) } static struct device_operations device_ops = { - .read_resources = &pch_uart_read_resources, + .read_resources = &uart_read_resources, .set_resources = &pci_dev_set_resources, .enable_resources = &uart_common_enable_resources, .ops_pci = &pci_dev_ops_pci, @@ -177,8 +267,8 @@ static const unsigned short pci_device_ids[] = { }; static const struct pci_driver pch_uart __pci_driver = { - .ops = &device_ops, - .vendor = PCI_VENDOR_ID_INTEL, + .ops = &device_ops, + .vendor = PCI_VENDOR_ID_INTEL, .devices = pci_device_ids, }; #endif /* ENV_RAMSTAGE */ -- cgit v1.2.3