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: 8660661 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 0924CC0553 for ; Thu, 24 Mar 2016 12:59:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EC1C6203A0 for ; Thu, 24 Mar 2016 12:59:52 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D7A9E20220 for ; Thu, 24 Mar 2016 12:59:51 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aj4q0-0002Xt-C8; Thu, 24 Mar 2016 12:58:08 +0000 Received: from mail-lf0-x232.google.com ([2a00:1450:4010:c07::232]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1aj4mq-0006wl-UL for linux-arm-kernel@lists.infradead.org; Thu, 24 Mar 2016 12:55:04 +0000 Received: by mail-lf0-x232.google.com with SMTP id d82so33487393lfe.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=Al6SNU/RSbooCKqzXjoexYHZXmb2PoxjqewAvldo9Sx6L6Y/Lq9fUIq6ioL4VZd0Bf x99LTr1hPI2vHeUiMGMtm2yF2G/GgSVZQMvSWeL8fJbuCagtgGhTwp3zagOYnNEGH/4t 8aqD4viLPMRbYcJycfIDWUlLaPhc7Az74Exy308rABdEPeia2RmSn7gCYP+d6rSg2+74 vUhGWBva7oEfSjfSiSCNnFRQMiKyiLHg+gd5mrWn1LpailmekNpHtf8Wbr5435CnIg7B wtMBsKiYOIXYsbuNXjqhJt+Rh7ETCuL+MAZ7+qP7KauP6W+FvJ1+GCms/INjNxEDl9mj Ha8w== X-Gm-Message-State: AD7BkJJY+UuhZODarSBgd2+M4TVjdvDdTOVRiTiSKi/5XA4NBSvhGyyA1lfsuTRUeSGINYDc 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 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> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160324_055453_834994_0903C10C X-CRM114-Status: GOOD ( 23.63 ) X-Spam-Score: -2.7 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Russell King , Peter Hurley , Graeme Gregory , linux-kernel@vger.kernel.org, Leif Lindholm , linux-acpi@vger.kernel.org, Aleksey Makarov , Yury Norov , Christopher Covington , linux-serial@vger.kernel.org, Jiri Slaby , Al Stone , linux-arm-kernel@lists.infradead.org, "Zheng, Lv" MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP '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 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*/