From patchwork Tue Sep 8 12:43:36 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leif Lindholm X-Patchwork-Id: 53269 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f197.google.com (mail-lb0-f197.google.com [209.85.217.197]) by patches.linaro.org (Postfix) with ESMTPS id 9BC8B22B05 for ; Tue, 8 Sep 2015 12:46:07 +0000 (UTC) Received: by lbbti1 with SMTP id ti1sf35107868lbb.3 for ; Tue, 08 Sep 2015 05:46:06 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=6tazCR5Lxugbmb0meJYwVRXIvTJQpoWL+x3qCv94fCs=; b=IuKt8AFARx1IpN4mU6dMKhlKqGeiZ5KB1Ly/1wItS2bi9ZCtAMI7/Zb0YriFEPumpr gFbK4UTyu5zA70ijeEdECpEp5Pisw3wztUew2HuvPeP0pemYYu0Ij+hhReuT9aA6Fmlz dvlt+v/vJQUEGTsHQpoqHxDOvDkvPDU9lVAk+w4nJY9DOaVTUFgwM0YUZcXfv24LMtdW IemkcAkkPqSLmWD2aFavFubQ/uvbsYscypDzwabW6yHdCbtOp5mwyBA1fRQi0JHqE5sZ sXiPNUUMJSwnNS85644UmmhxzQf9AgUlZH0bii5SbUxnZTGJa+wp3AGly8jR428ZaMIa JArA== X-Gm-Message-State: ALoCoQmhJ/lWBrntTWozpQyie5e+kDKrOjWeB3zldkiNYZ3VLv1PviMSQC29MmBotyWA6sivNCdD X-Received: by 10.180.81.165 with SMTP id b5mr1017783wiy.1.1441716366382; Tue, 08 Sep 2015 05:46:06 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.9.7 with SMTP id v7ls744409laa.107.gmail; Tue, 08 Sep 2015 05:46:06 -0700 (PDT) X-Received: by 10.112.55.6 with SMTP id n6mr1284912lbp.88.1441716366182; Tue, 08 Sep 2015 05:46:06 -0700 (PDT) Received: from mail-lb0-f177.google.com (mail-lb0-f177.google.com. [209.85.217.177]) by mx.google.com with ESMTPS id yo1si3109448lbb.167.2015.09.08.05.46.06 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 08 Sep 2015 05:46:06 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.177 as permitted sender) client-ip=209.85.217.177; Received: by lbcao8 with SMTP id ao8so52374784lbc.3 for ; Tue, 08 Sep 2015 05:46:06 -0700 (PDT) X-Received: by 10.112.166.106 with SMTP id zf10mr22118114lbb.36.1441716366034; Tue, 08 Sep 2015 05:46:06 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp952417lbq; Tue, 8 Sep 2015 05:46:04 -0700 (PDT) X-Received: by 10.202.200.79 with SMTP id y76mr19050995oif.5.1441716364720; Tue, 08 Sep 2015 05:46:04 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id pi10si5283196pac.230.2015.09.08.05.46.03; Tue, 08 Sep 2015 05:46:04 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754775AbbIHMom (ORCPT + 28 others); Tue, 8 Sep 2015 08:44:42 -0400 Received: from mail-wi0-f170.google.com ([209.85.212.170]:33063 "EHLO mail-wi0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754669AbbIHMnw (ORCPT ); Tue, 8 Sep 2015 08:43:52 -0400 Received: by wiclk2 with SMTP id lk2so118935389wic.0 for ; Tue, 08 Sep 2015 05:43:51 -0700 (PDT) X-Received: by 10.180.76.231 with SMTP id n7mr44410705wiw.65.1441716231649; Tue, 08 Sep 2015 05:43:51 -0700 (PDT) Received: from mohikan.mushroom.smurfnet.nu (cpc4-cmbg17-2-0-cust71.5-4.cable.virginm.net. [86.14.224.72]) by smtp.gmail.com with ESMTPSA id i7sm4696047wib.15.2015.09.08.05.43.50 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 08 Sep 2015 05:43:51 -0700 (PDT) From: Leif Lindholm To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-serial@vger.kernel.org, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org Cc: mark.rutland@arm.com, al.stone@linaro.org, torez@redhat.com, jcm@redhat.com, graeme.gregory@linaro.org, linaro-acpi@lists.linaro.org, lv.zheng@intel.com Subject: [RFC 4/5] tty/console: use SPCR table to define console Date: Tue, 8 Sep 2015 13:43:36 +0100 Message-Id: <1441716217-23786-5-git-send-email-leif.lindholm@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1441716217-23786-1-git-send-email-leif.lindholm@linaro.org> References: <1441716217-23786-1-git-send-email-leif.lindholm@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: leif.lindholm@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.177 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Torez Smith If console= is not added to the kernel command line, the console is not registered until much further into the booting process. This patch adds support to parse the SPCR ACPI table to pull console support out, then use the appropriate drivers to set up console support earlier in the boot process. Signed-off-by: Jon Masters [rebased and cleaned up] Signed-off-by: Torez Smith [reworked to use _CRS, moved to drivers/acpi] Signed-off-by: Leif Lindholm --- drivers/acpi/console.c | 157 +++++++++++++++++++++++++++++++++++++++ drivers/tty/serial/serial_core.c | 14 +++- include/linux/acpi.h | 11 ++- 3 files changed, 179 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/console.c b/drivers/acpi/console.c index a985890..02883a1 100644 --- a/drivers/acpi/console.c +++ b/drivers/acpi/console.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012, Intel Corporation + * Copyright (c) 2015, Red Hat, Inc. * Copyright (c) 2015, Linaro Ltd. * * This program is free software; you can redistribute it and/or modify @@ -12,11 +13,17 @@ #define pr_fmt(fmt) "ACPI: " KBUILD_MODNAME ": " fmt #include +#include #include #include +#include #define NUM_ELEMS(x) (sizeof(x) / sizeof(*x)) +static u64 acpi_serial_addr; +static struct acpi_device *acpi_serial_device; +static char *acpi_serial_options; + #ifdef CONFIG_SERIAL_EARLYCON static int use_earlycon __initdata; static int __init setup_acpi_earlycon(char *buf) @@ -101,3 +108,153 @@ int __init acpi_early_console_probe(void) return 0; } #endif /* CONFIG_SERIAL_EARLYCON */ + +/* + * Parse the SPCR table. If we are not working with version 2 or + * higher, bail. + * Otherwise, pull out the baud rate and address to the console device. + */ +static int __init acpi_parse_spcr(struct acpi_table_header *table) +{ + struct acpi_table_spcr *spcr = (struct acpi_table_spcr *)table; + + if (table->revision < 2) + return -EOPNOTSUPP; + + /* Handle possible alignment issues */ + memcpy(&acpi_serial_addr, + &spcr->serial_port.address, sizeof(acpi_serial_addr)); + + /* + * The baud rate the BIOS used for redirection. Valid values are.... + * 3 = 9600 + * 4 = 19200 + * 6 = 57600 + * 7 = 115200 + * 0-2, 5, 8 - 255 = reserved + */ + switch (spcr->baud_rate) { + case 3: + acpi_serial_options = "9600"; + break; + case 4: + acpi_serial_options = "19200"; + break; + case 6: + acpi_serial_options = "57600"; + break; + case 7: + acpi_serial_options = "115200"; + break; + default: + acpi_serial_options = ""; + break; + } + + pr_info("SPCR serial device: 0x%llx (options: %s)\n", + acpi_serial_addr, acpi_serial_options); + + return 0; +} + +/* + * Parse an ACPI "Device" to determine if it represents the + * data found in the SPCR table. If the associated Device has + * and Address entry, and, that Address matches the one found + * in our SPCR table, it's the entry we are interested in. + * + */ +static acpi_status acpi_spcr_device_scan(acpi_handle handle, + u32 level, void *context, void **retv) +{ + unsigned long long addr = 0; + struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_status status = AE_OK; + struct acpi_device *adev; + struct list_head resource_list; + struct resource_entry *rentry; + + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer); + if (ACPI_FAILURE(status)) + return status; + + adev = acpi_bus_get_acpi_device(handle); + if (!adev) { + pr_err("Err locating SPCR device from ACPI handle\n"); + return AE_OK; /* skip this one */ + } + + /* + * Read device address from _CRS. + */ + INIT_LIST_HEAD(&resource_list); + if (acpi_dev_get_resources(adev, &resource_list, NULL, NULL) <= 0) + return AE_OK; + + list_for_each_entry(rentry, &resource_list, node) { + if (resource_type(rentry->res) == IORESOURCE_MEM) + addr = rentry->res->start; + } + acpi_dev_free_resource_list(&resource_list); + + if (addr == acpi_serial_addr) { + acpi_serial_device = adev; + + pr_info("SPCR serial console: %s (0x%llx)\n", + (char *)(name_buffer.pointer), addr); + + return AE_OK; /* harmless to continue */ + } + + /* continue */ + return AE_OK; /* continue */ +} + +static int __init acpi_setup_spcr(void) +{ + if (0 != acpi_table_parse(ACPI_SIG_SPCR, acpi_parse_spcr)) { + pr_warn("SPCR table not found - auto console disabled\n"); + return -ENODEV; + } + + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_spcr_device_scan, + NULL, NULL, NULL); + + return 0; +} + +static int __init acpi_spcr_setup(void) +{ + /* + * If ACPI is enabled, scan the tables for + * automatic console configuration + */ + if (!acpi_disabled) + acpi_setup_spcr(); + + return 0; +} +subsys_initcall_sync(acpi_spcr_setup); + +/** + * acpi_console_check() - Check for and configure console from ACPI information + * @adev - Pointer to device + * @name - Name to use for preferred console without index. ex. "ttyS" + * @index - Index to use for preferred console. + * + * Check if the given device matches the information provided in the SPCR table + * If it does then register it as the preferred console and return TRUE. + * Otherwise return FALSE. + */ +bool acpi_console_check(struct acpi_device *adev, char *name, int index) +{ + if (acpi_disabled || !adev || adev != acpi_serial_device + || console_set_on_cmdline) + return false; + + pr_info("adding preferred console [%s]\n", name); + + return !add_preferred_console(name, index, + kstrdup(acpi_serial_options, GFP_KERNEL)); +} diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 603d2cc..4b20bc6 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -2696,9 +2697,18 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) spin_lock_init(&uport->lock); lockdep_set_class(&uport->lock, &port_lock_key); } - if (uport->cons && uport->dev) - of_console_check(uport->dev->of_node, uport->cons->name, uport->line); + /* + * Support both open FW and ACPI access to console definitions. + * Both of_console_check() and acpi_console_check() will call + * add_preferred_console() if a console definition is found. + */ + if (uport->cons && uport->dev) { + if (!acpi_console_check(ACPI_COMPANION(uport->dev), + uport->cons->name, uport->line)) + of_console_check(uport->dev->of_node, + uport->cons->name, uport->line); + } uart_configure_port(drv, state, uport); num_groups = 2; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 88cb9c1..f1b9a64 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -811,8 +811,17 @@ static inline struct acpi_device *acpi_get_next_child(struct device *dev, #endif -#if defined(CONFIG_ACPI) && defined(CONFIG_SERIAL_EARLYCON) +#if defined(CONFIG_ACPI) +# if defined(CONFIG_SERIAL_EARLYCON) int __init acpi_early_console_probe(void); +# endif +bool acpi_console_check(struct acpi_device *adev, char *name, int index); +#else +static inline bool acpi_console_check(struct acpi_device *adev, char *name, + int index) +{ + return FALSE; +} #endif #endif /*_LINUX_ACPI_H*/