From patchwork Thu Mar 24 12:52:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksey Makarov X-Patchwork-Id: 64348 Delivered-To: patch@linaro.org Received: by 10.112.199.169 with SMTP id jl9csp623004lbc; Thu, 24 Mar 2016 05:55:13 -0700 (PDT) X-Received: by 10.66.156.232 with SMTP id wh8mr12599885pab.159.1458824109848; Thu, 24 Mar 2016 05:55:09 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o129si12168796pfo.19.2016.03.24.05.55.09; Thu, 24 Mar 2016 05:55:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-serial-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-serial-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-serial-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757494AbcCXMyn (ORCPT + 1 other); Thu, 24 Mar 2016 08:54:43 -0400 Received: from mail-lf0-f43.google.com ([209.85.215.43]:36346 "EHLO mail-lf0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757425AbcCXMyd (ORCPT ); Thu, 24 Mar 2016 08:54:33 -0400 Received: by mail-lf0-f43.google.com with SMTP id d82so33487395lfe.3 for ; Thu, 24 Mar 2016 05:54:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=0O8nDRgr8udXqNnJF8Yaz/+nmlvKKDbmNfQOfGF4l3k=; b=TYfMTqwUMvW8yxi5AJ93TpX4hO78XGHMDOBzmQ0mfjUqDjSPAmHxj0jXksAHzdZjkS RhakIveX2UqJVCQo035B9WQTi2biFnTUBRWTn5MKEj9TE78cxKniLn6xAQA1eHAvIdvM V80EmyvACV4N1s02bJTGhcdGUpRh9f0Yumw20= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=0O8nDRgr8udXqNnJF8Yaz/+nmlvKKDbmNfQOfGF4l3k=; b=BJsgEHlZgDvZuGSIndF3dXL0TDc9PwNx5DZSxoVmKWnArNgu39H/CF06FZl1wWBGzs IjKWx/UA6swOfA2JNQwVfe/pN/Hs7fnjOHAN8AodJYL/6vnG8qK62p1y+SE8xdnhDG6L AcllGDpXh2lJrwphvMdZKpXV9vsnZ8yVfNutLc1t8ushlcQiSEoeq3KLeAV5JTaTsfsx gztpAK5yC/gxSvgR9FZQ5sUU0rhpmDXOPMkU3G4TBST6mUg6Kc4GUAx2wxx7k8PzA1rp u5gAq7XqshyH6JND7369gooCveu0quVnHybfo/rv4HIiViNgFbHOPn2pvF4W9dgpxY8W z3cg== X-Gm-Message-State: AD7BkJITDWurliNaaC4D/LdVUts2lWt9Ti/WJ0iPFmMkY7E7sixv7Y+CX1VU4Re5n+PhpfZD X-Received: by 10.25.27.200 with SMTP id b191mr3595300lfb.8.1458824071023; Thu, 24 Mar 2016 05:54:31 -0700 (PDT) Received: from turnip.localdomain (nivc-213.auriga.ru. [80.240.102.213]) by smtp.gmail.com with ESMTPSA id rh2sm1167378lbb.36.2016.03.24.05.54.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 24 Mar 2016 05:54:30 -0700 (PDT) From: Aleksey Makarov To: Greg Kroah-Hartman , "Rafael J . Wysocki" , Len Brown Cc: linux-serial@vger.kernel.org, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Aleksey Makarov , Russell King , Leif Lindholm , Graeme Gregory , Al Stone , Christopher Covington , Yury Norov , Peter Hurley , "Zheng, Lv" , Jiri Slaby Subject: [PATCH v6 3/5] ACPI: parse SPCR and enable matching console Date: Thu, 24 Mar 2016 15:52:01 +0300 Message-Id: <1458823925-19560-4-git-send-email-aleksey.makarov@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1458823925-19560-1-git-send-email-aleksey.makarov@linaro.org> References: <1458823925-19560-1-git-send-email-aleksey.makarov@linaro.org> Sender: linux-serial-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-serial@vger.kernel.org 'ARM Server Base Boot Requiremets' [1] mentions SPCR (Serial Port Console Redirection Table) [2] as a mandatory ACPI table that specifies the configuration of serial console. Defer initialization of DT earlycon until ACPI/DT decision is made. If ACPI is enabled, parse the table, setup earlycon and enable the specified console. If it is disabled, try to set up earlycon from DT. Thanks to Peter Hurley for explaining how this should work. [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0044a/index.html [2] https://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx Signed-off-by: Aleksey Makarov --- drivers/acpi/Kconfig | 3 + drivers/acpi/Makefile | 1 + drivers/acpi/spcr.c | 125 ++++++++++++++++++++++++++++++++++++++++++ drivers/tty/serial/earlycon.c | 11 +++- include/linux/acpi.h | 8 +++ 5 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 drivers/acpi/spcr.c -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 65fb483..5611eb6 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -77,6 +77,9 @@ config ACPI_DEBUGGER_USER endif +config ACPI_SPCR_TABLE + bool + config ACPI_SLEEP bool depends on SUSPEND || HIBERNATION diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 7395928..f70ae14 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -82,6 +82,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o obj-$(CONFIG_ACPI_BGRT) += bgrt.o obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o +obj-$(CONFIG_ACPI_SPCR_TABLE) += spcr.o obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o # processor has its own "processor." module_param namespace diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c new file mode 100644 index 0000000..31e667e --- /dev/null +++ b/drivers/acpi/spcr.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2012, Intel Corporation + * Copyright (c) 2015, Red Hat, Inc. + * Copyright (c) 2015, 2016 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#define pr_fmt(fmt) "ACPI: SPCR: " fmt + +#include +#include +#include +#include +#include + +static bool earlycon_init_is_deferred __initdata; + +void __init defer_earlycon_init(void) +{ + earlycon_init_is_deferred = true; +} + +/** + * parse_spcr() - parse ACPI SPCR table and add preferred console + * + * For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be + * defined to parse ACPI SPCR table. As a result of the parsing preferred + * console is registered. + * + * When CONFIG_ACPI_SPCR_TABLE is defined, this function should should be called + * from arch inintialization code as soon as the DT/ACPI decision is made. + * + * When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in + * command line does not start DT earlycon immediately, instead it defers + * starting it until DT/ACPI decision is made. If ACPI is enabled at that time, + * parse_spcr() parses the table, adds preferred console and sets up it as an + * earlycon. If ACPI is disabled at that time, it tries to set up earlycon + * from DT. + */ +int __init parse_spcr(void) +{ +#define OPTS_LEN 64 + static char opts[OPTS_LEN]; + struct acpi_table_spcr *table; + acpi_size table_size; + acpi_status status; + char *uart; + char *iotype; + int baud_rate; + int err; + + if (acpi_disabled) + return earlycon_init_is_deferred ? + early_init_dt_scan_chosen_stdout() : 0; + + status = acpi_get_table_with_size(ACPI_SIG_SPCR, 0, + (struct acpi_table_header **)&table, + &table_size); + + if (ACPI_FAILURE(status)) + return -ENOENT; + + if (table->header.revision < 2) { + err = -EINVAL; + pr_err("wrong table version\n"); + goto done; + } + + iotype = (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) ? + "mmio" : "io"; + + switch (table->interface_type) { + case ACPI_DBG2_ARM_SBSA_32BIT: + iotype = "mmio32"; + /* fall through */ + case ACPI_DBG2_ARM_PL011: + case ACPI_DBG2_ARM_SBSA_GENERIC: + case ACPI_DBG2_BCM2835: + uart = "pl011"; + break; + case ACPI_DBG2_16550_COMPATIBLE: + case ACPI_DBG2_16550_SUBSET: + uart = "uart"; + break; + default: + err = -ENOENT; + goto done; + } + + switch (table->baud_rate) { + case 3: + baud_rate = 9600; + break; + case 4: + baud_rate = 19200; + break; + case 6: + baud_rate = 57600; + break; + case 7: + baud_rate = 115200; + break; + default: + err = -ENOENT; + goto done; + } + + snprintf(opts, OPTS_LEN, "%s,%s,0x%llx,%d", uart, iotype, + table->serial_port.address, baud_rate); + + pr_info("console: %s", opts); + + if (earlycon_init_is_deferred) + setup_earlycon(opts); + + err = add_preferred_console(uart, 0, opts + strlen(uart) + 1); + +done: + early_acpi_os_unmap_memory((void __iomem *)table, table_size); + return err; +} diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 7aae655..ed6aaf8 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef CONFIG_FIX_EARLYCON_MEM #include @@ -208,8 +209,14 @@ static int __init param_setup_earlycon(char *buf) * Just 'earlycon' is a valid param for devicetree earlycons; * don't generate a warning from parse_early_params() in that case */ - if (!buf || !buf[0]) - return early_init_dt_scan_chosen_stdout(); + if (!buf || !buf[0]) { + if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) { + defer_earlycon_init(); + return 0; + } else { + return early_init_dt_scan_chosen_stdout(); + } + } err = setup_earlycon(buf); if (err == -ENOENT || err == -EALREADY) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 06ed7e5..3523995 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1004,4 +1004,12 @@ static inline struct fwnode_handle *acpi_get_next_subnode(struct device *dev, #define acpi_probe_device_table(t) ({ int __r = 0; __r;}) #endif +#ifdef CONFIG_ACPI_SPCR_TABLE +int parse_spcr(void); +void defer_earlycon_init(void); +#else +static inline int parse_spcr(void) { return 0; } +static inline void defer_earlycon_init(void) { } +#endif + #endif /*_LINUX_ACPI_H*/