e4b3d2e
From patchwork Fri Aug 12 11:07:14 2016
e4b3d2e
Content-Type: text/plain; charset="utf-8"
e4b3d2e
MIME-Version: 1.0
e4b3d2e
Content-Transfer-Encoding: 7bit
e4b3d2e
Subject: [v9,1/4] of/serial: move earlycon early_param handling to serial
e4b3d2e
From: Aleksey Makarov <aleksey.makarov@linaro.org>
e4b3d2e
X-Patchwork-Id: 9276727
e4b3d2e
Message-Id: <20160812110717.12351-1-aleksey.makarov@linaro.org>
e4b3d2e
To: "Rafael J . Wysocki" <rjw@rjwysocki.net>,
e4b3d2e
 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
e4b3d2e
Cc: linux-serial@vger.kernel.org, linux-acpi@vger.kernel.org,
e4b3d2e
 linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
e4b3d2e
 Aleksey Makarov <aleksey.makarov@linaro.org>,
e4b3d2e
 Russell King <linux@arm.linux.org.uk>, Len Brown <lenb@kernel.org>,
e4b3d2e
 Leif Lindholm <leif.lindholm@linaro.org>,
e4b3d2e
 Graeme Gregory <graeme.gregory@linaro.org>, Al Stone <ahs3@redhat.com>,
e4b3d2e
 Christopher Covington <cov@codeaurora.org>,
e4b3d2e
 Yury Norov <ynorov@caviumnetworks.com>,
e4b3d2e
 Peter Hurley <peter@hurleysoftware.com>,
e4b3d2e
 Andy Shevchenko <andy.shevchenko@gmail.com>,
e4b3d2e
 "Zheng, Lv" <lv.zheng@intel.com>, Mark Salter <msalter@redhat.com>,
e4b3d2e
 Kefeng Wang <wangkefeng.wang@huawei.com>,
e4b3d2e
 Rob Herring <robh+dt@kernel.org>, Frank Rowand <frowand.list@gmail.com>,
e4b3d2e
 Jiri Slaby <jslaby@suse.com>, devicetree@vger.kernel.org
e4b3d2e
Date: Fri, 12 Aug 2016 14:07:14 +0300
e4b3d2e
e4b3d2e
From: Leif Lindholm <leif.lindholm@linaro.org>
e4b3d2e
e4b3d2e
We have multiple "earlycon" early_param handlers - merge the DT one into
e4b3d2e
the main earlycon one.  It's a cleanup that also will be useful
e4b3d2e
to defer setting up DT console until ACPI/DT decision is made.
e4b3d2e
e4b3d2e
Rename the exported function to avoid clashing with the function from
e4b3d2e
arch/microblaze/kernel/prom.c
e4b3d2e
e4b3d2e
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
e4b3d2e
Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>
e4b3d2e
Acked-by: Rob Herring <robh@kernel.org>
e4b3d2e
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
e4b3d2e
Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
e4b3d2e
Tested-by: Kefeng Wang <wangkefeng.wang@huawei.com>
e4b3d2e
---
e4b3d2e
 drivers/of/fdt.c              | 11 +----------
e4b3d2e
 drivers/tty/serial/earlycon.c |  2 +-
e4b3d2e
 include/linux/of_fdt.h        |  3 +++
e4b3d2e
 3 files changed, 5 insertions(+), 11 deletions(-)
e4b3d2e
e4b3d2e
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
e4b3d2e
index 55f1b83..741cac53 100644
e4b3d2e
--- a/drivers/of/fdt.c
e4b3d2e
+++ b/drivers/of/fdt.c
e4b3d2e
@@ -924,7 +924,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node)
e4b3d2e
 
e4b3d2e
 #ifdef CONFIG_SERIAL_EARLYCON
e4b3d2e
 
e4b3d2e
-static int __init early_init_dt_scan_chosen_serial(void)
e4b3d2e
+int __init early_init_dt_scan_chosen_stdout(void)
e4b3d2e
 {
e4b3d2e
 	int offset;
e4b3d2e
 	const char *p, *q, *options = NULL;
e4b3d2e
@@ -968,15 +968,6 @@ static int __init early_init_dt_scan_chosen_serial(void)
e4b3d2e
 	}
e4b3d2e
 	return -ENODEV;
e4b3d2e
 }
e4b3d2e
-
e4b3d2e
-static int __init setup_of_earlycon(char *buf)
e4b3d2e
-{
e4b3d2e
-	if (buf)
e4b3d2e
-		return 0;
e4b3d2e
-
e4b3d2e
-	return early_init_dt_scan_chosen_serial();
e4b3d2e
-}
e4b3d2e
-early_param("earlycon", setup_of_earlycon);
e4b3d2e
 #endif
e4b3d2e
 
e4b3d2e
 /**
e4b3d2e
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
e4b3d2e
index 067783f..7aae655 100644
e4b3d2e
--- a/drivers/tty/serial/earlycon.c
e4b3d2e
+++ b/drivers/tty/serial/earlycon.c
e4b3d2e
@@ -209,7 +209,7 @@ static int __init param_setup_earlycon(char *buf)
e4b3d2e
 	 * don't generate a warning from parse_early_params() in that case
e4b3d2e
 	 */
e4b3d2e
 	if (!buf || !buf[0])
e4b3d2e
-		return 0;
e4b3d2e
+		return early_init_dt_scan_chosen_stdout();
e4b3d2e
 
e4b3d2e
 	err = setup_earlycon(buf);
e4b3d2e
 	if (err == -ENOENT || err == -EALREADY)
e4b3d2e
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
e4b3d2e
index 26c3302..4341f32 100644
e4b3d2e
--- a/include/linux/of_fdt.h
e4b3d2e
+++ b/include/linux/of_fdt.h
e4b3d2e
@@ -14,6 +14,7 @@
e4b3d2e
 
e4b3d2e
 #include <linux/types.h>
e4b3d2e
 #include <linux/init.h>
e4b3d2e
+#include <linux/errno.h>
e4b3d2e
 
e4b3d2e
 /* Definitions used by the flattened device tree */
e4b3d2e
 #define OF_DT_HEADER		0xd00dfeed	/* marker */
e4b3d2e
@@ -66,6 +67,7 @@ extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
e4b3d2e
 				     int depth, void *data);
e4b3d2e
 extern int early_init_dt_scan_memory(unsigned long node, const char *uname,
e4b3d2e
 				     int depth, void *data);
e4b3d2e
+extern int early_init_dt_scan_chosen_stdout(void);
e4b3d2e
 extern void early_init_fdt_scan_reserved_mem(void);
e4b3d2e
 extern void early_init_fdt_reserve_self(void);
e4b3d2e
 extern void early_init_dt_add_memory_arch(u64 base, u64 size);
e4b3d2e
@@ -94,6 +96,7 @@ extern void early_get_first_memblock_info(void *, phys_addr_t *);
e4b3d2e
 extern u64 of_flat_dt_translate_address(unsigned long node);
e4b3d2e
 extern void of_fdt_limit_memory(int limit);
e4b3d2e
 #else /* CONFIG_OF_FLATTREE */
e4b3d2e
+static inline int early_init_dt_scan_chosen_stdout(void) { return -ENODEV; }
e4b3d2e
 static inline void early_init_fdt_scan_reserved_mem(void) {}
e4b3d2e
 static inline void early_init_fdt_reserve_self(void) {}
e4b3d2e
 static inline const char *of_flat_dt_get_machine_name(void) { return NULL; }
e4b3d2e
From patchwork Thu Aug 11 15:31:39 2016
e4b3d2e
Content-Type: text/plain; charset="utf-8"
e4b3d2e
MIME-Version: 1.0
e4b3d2e
Content-Transfer-Encoding: 7bit
e4b3d2e
Subject: [v9,2/4] ACPI: parse SPCR and enable matching console
e4b3d2e
From: Aleksey Makarov <aleksey.makarov@linaro.org>
e4b3d2e
X-Patchwork-Id: 9275443
e4b3d2e
Message-Id: <20160811153152.755-3-aleksey.makarov@linaro.org>
e4b3d2e
To: "Rafael J . Wysocki" <rjw@rjwysocki.net>,
e4b3d2e
 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
e4b3d2e
Cc: linux-serial@vger.kernel.org, linux-acpi@vger.kernel.org,
e4b3d2e
 linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
e4b3d2e
 Aleksey Makarov <aleksey.makarov@linaro.org>,
e4b3d2e
 Russell King <linux@arm.linux.org.uk>, Len Brown <lenb@kernel.org>,
e4b3d2e
 Leif Lindholm <leif.lindholm@linaro.org>,
e4b3d2e
 Graeme Gregory <graeme.gregory@linaro.org>, Al Stone <ahs3@redhat.com>,
e4b3d2e
 Christopher Covington <cov@codeaurora.org>,
e4b3d2e
 Yury Norov <ynorov@caviumnetworks.com>,
e4b3d2e
 Peter Hurley <peter@hurleysoftware.com>,
e4b3d2e
 Andy Shevchenko <andy.shevchenko@gmail.com>,
e4b3d2e
 "Zheng, Lv" <lv.zheng@intel.com>, Mark Salter <msalter@redhat.com>,
e4b3d2e
 Kefeng Wang <wangkefeng.wang@huawei.com>, Jiri Slaby <jslaby@suse.com>
e4b3d2e
Date: Thu, 11 Aug 2016 18:31:39 +0300
e4b3d2e
e4b3d2e
'ARM Server Base Boot Requiremets' [1] mentions SPCR (Serial Port
e4b3d2e
Console Redirection Table) [2] as a mandatory ACPI table that
e4b3d2e
specifies the configuration of serial console.
e4b3d2e
e4b3d2e
Defer initialization of DT earlycon until ACPI/DT decision is made.
e4b3d2e
e4b3d2e
Parse the ACPI SPCR table, setup earlycon if required,
e4b3d2e
enable specified console.
e4b3d2e
e4b3d2e
Thanks to Peter Hurley for explaining how this should work.
e4b3d2e
e4b3d2e
[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0044a/index.html
e4b3d2e
[2] https://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx
e4b3d2e
e4b3d2e
Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>
e4b3d2e
Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
e4b3d2e
Tested-by: Kefeng Wang <wangkefeng.wang@huawei.com>
e4b3d2e
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
e4b3d2e
---
e4b3d2e
 drivers/acpi/Kconfig          |   3 ++
e4b3d2e
 drivers/acpi/Makefile         |   1 +
e4b3d2e
 drivers/acpi/spcr.c           | 111 ++++++++++++++++++++++++++++++++++++++++++
e4b3d2e
 drivers/tty/serial/earlycon.c |  19 +++++++-
e4b3d2e
 include/linux/acpi.h          |   6 +++
e4b3d2e
 include/linux/serial_core.h   |   9 +++-
e4b3d2e
 6 files changed, 146 insertions(+), 3 deletions(-)
e4b3d2e
 create mode 100644 drivers/acpi/spcr.c
e4b3d2e
e4b3d2e
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
e4b3d2e
index 6cef2d1..4a269f9 100644
e4b3d2e
--- a/drivers/acpi/Kconfig
e4b3d2e
+++ b/drivers/acpi/Kconfig
e4b3d2e
@@ -77,6 +77,9 @@ config ACPI_DEBUGGER_USER
e4b3d2e
 
e4b3d2e
 endif
e4b3d2e
 
e4b3d2e
+config ACPI_SPCR_TABLE
e4b3d2e
+	bool
e4b3d2e
+
e4b3d2e
 config ACPI_SLEEP
e4b3d2e
 	bool
e4b3d2e
 	depends on SUSPEND || HIBERNATION
e4b3d2e
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
e4b3d2e
index e5ada78..d799593 100644
e4b3d2e
--- a/drivers/acpi/Makefile
e4b3d2e
+++ b/drivers/acpi/Makefile
e4b3d2e
@@ -81,6 +81,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS)	+= ec_sys.o
e4b3d2e
 obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
e4b3d2e
 obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
e4b3d2e
 obj-$(CONFIG_ACPI_CPPC_LIB)	+= cppc_acpi.o
e4b3d2e
+obj-$(CONFIG_ACPI_SPCR_TABLE)	+= spcr.o
e4b3d2e
 obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o
e4b3d2e
 
e4b3d2e
 # processor has its own "processor." module_param namespace
e4b3d2e
diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c
e4b3d2e
new file mode 100644
e4b3d2e
index 0000000..e8d7bc7
e4b3d2e
--- /dev/null
e4b3d2e
+++ b/drivers/acpi/spcr.c
e4b3d2e
@@ -0,0 +1,111 @@
e4b3d2e
+/*
e4b3d2e
+ * Copyright (c) 2012, Intel Corporation
e4b3d2e
+ * Copyright (c) 2015, Red Hat, Inc.
e4b3d2e
+ * Copyright (c) 2015, 2016 Linaro Ltd.
e4b3d2e
+ *
e4b3d2e
+ * This program is free software; you can redistribute it and/or modify
e4b3d2e
+ * it under the terms of the GNU General Public License version 2 as
e4b3d2e
+ * published by the Free Software Foundation.
e4b3d2e
+ *
e4b3d2e
+ */
e4b3d2e
+
e4b3d2e
+#define pr_fmt(fmt) "ACPI: SPCR: " fmt
e4b3d2e
+
e4b3d2e
+#include <linux/acpi.h>
e4b3d2e
+#include <linux/console.h>
e4b3d2e
+#include <linux/kernel.h>
e4b3d2e
+#include <linux/serial_core.h>
e4b3d2e
+
e4b3d2e
+/**
e4b3d2e
+ * parse_spcr() - parse ACPI SPCR table and add preferred console
e4b3d2e
+ *
e4b3d2e
+ * @earlycon: set up earlycon for the console specified by the table
e4b3d2e
+ *
e4b3d2e
+ * For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be
e4b3d2e
+ * defined to parse ACPI SPCR table.  As a result of the parsing preferred
e4b3d2e
+ * console is registered and if @earlycon is true, earlycon is set up.
e4b3d2e
+ *
e4b3d2e
+ * When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called
e4b3d2e
+ * from arch inintialization code as soon as the DT/ACPI decision is made.
e4b3d2e
+ *
e4b3d2e
+ */
e4b3d2e
+int __init parse_spcr(bool earlycon)
e4b3d2e
+{
e4b3d2e
+	static char opts[64];
e4b3d2e
+	struct acpi_table_spcr *table;
e4b3d2e
+	acpi_size table_size;
e4b3d2e
+	acpi_status status;
e4b3d2e
+	char *uart;
e4b3d2e
+	char *iotype;
e4b3d2e
+	int baud_rate;
e4b3d2e
+	int err;
e4b3d2e
+
e4b3d2e
+	if (acpi_disabled)
e4b3d2e
+		return -ENODEV;
e4b3d2e
+
e4b3d2e
+	status = acpi_get_table_with_size(ACPI_SIG_SPCR, 0,
e4b3d2e
+					  (struct acpi_table_header **)&table,
e4b3d2e
+					  &table_size);
e4b3d2e
+
e4b3d2e
+	if (ACPI_FAILURE(status))
e4b3d2e
+		return -ENOENT;
e4b3d2e
+
e4b3d2e
+	if (table->header.revision < 2) {
e4b3d2e
+		err = -ENOENT;
e4b3d2e
+		pr_err("wrong table version\n");
e4b3d2e
+		goto done;
e4b3d2e
+	}
e4b3d2e
+
e4b3d2e
+	iotype = table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY ?
e4b3d2e
+			"mmio" : "io";
e4b3d2e
+
e4b3d2e
+	switch (table->interface_type) {
e4b3d2e
+	case ACPI_DBG2_ARM_SBSA_32BIT:
e4b3d2e
+		iotype = "mmio32";
e4b3d2e
+		/* fall through */
e4b3d2e
+	case ACPI_DBG2_ARM_PL011:
e4b3d2e
+	case ACPI_DBG2_ARM_SBSA_GENERIC:
e4b3d2e
+	case ACPI_DBG2_BCM2835:
e4b3d2e
+		uart = "pl011";
e4b3d2e
+		break;
e4b3d2e
+	case ACPI_DBG2_16550_COMPATIBLE:
e4b3d2e
+	case ACPI_DBG2_16550_SUBSET:
e4b3d2e
+		uart = "uart";
e4b3d2e
+		break;
e4b3d2e
+	default:
e4b3d2e
+		err = -ENOENT;
e4b3d2e
+		goto done;
e4b3d2e
+	}
e4b3d2e
+
e4b3d2e
+	switch (table->baud_rate) {
e4b3d2e
+	case 3:
e4b3d2e
+		baud_rate = 9600;
e4b3d2e
+		break;
e4b3d2e
+	case 4:
e4b3d2e
+		baud_rate = 19200;
e4b3d2e
+		break;
e4b3d2e
+	case 6:
e4b3d2e
+		baud_rate = 57600;
e4b3d2e
+		break;
e4b3d2e
+	case 7:
e4b3d2e
+		baud_rate = 115200;
e4b3d2e
+		break;
e4b3d2e
+	default:
e4b3d2e
+		err = -ENOENT;
e4b3d2e
+		goto done;
e4b3d2e
+	}
e4b3d2e
+
e4b3d2e
+	snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype,
e4b3d2e
+		 table->serial_port.address, baud_rate);
e4b3d2e
+
e4b3d2e
+	pr_info("console: %s\n", opts);
e4b3d2e
+
e4b3d2e
+	if (earlycon)
e4b3d2e
+		setup_earlycon(opts);
e4b3d2e
+
e4b3d2e
+	err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);
e4b3d2e
+
e4b3d2e
+done:
e4b3d2e
+	early_acpi_os_unmap_memory((void __iomem *)table, table_size);
e4b3d2e
+	return err;
e4b3d2e
+}
e4b3d2e
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
e4b3d2e
index 7aae655..ea00b9f 100644
e4b3d2e
--- a/drivers/tty/serial/earlycon.c
e4b3d2e
+++ b/drivers/tty/serial/earlycon.c
e4b3d2e
@@ -21,6 +21,7 @@
e4b3d2e
 #include <linux/sizes.h>
e4b3d2e
 #include <linux/of.h>
e4b3d2e
 #include <linux/of_fdt.h>
e4b3d2e
+#include <linux/acpi.h>
e4b3d2e
 
e4b3d2e
 #ifdef CONFIG_FIX_EARLYCON_MEM
e4b3d2e
 #include <asm/fixmap.h>
e4b3d2e
@@ -199,6 +200,14 @@ int __init setup_earlycon(char *buf)
e4b3d2e
 	return -ENOENT;
e4b3d2e
 }
e4b3d2e
 
e4b3d2e
+/*
e4b3d2e
+ * When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in
e4b3d2e
+ * command line does not start DT earlycon immediately, instead it defers
e4b3d2e
+ * starting it until DT/ACPI decision is made.  At that time if ACPI is enabled
e4b3d2e
+ * call parse_spcr(), else call early_init_dt_scan_chosen_stdout()
e4b3d2e
+ */
e4b3d2e
+bool earlycon_init_is_deferred __initdata;
e4b3d2e
+
e4b3d2e
 /* early_param wrapper for setup_earlycon() */
e4b3d2e
 static int __init param_setup_earlycon(char *buf)
e4b3d2e
 {
e4b3d2e
@@ -208,8 +217,14 @@ static int __init param_setup_earlycon(char *buf)
e4b3d2e
 	 * Just 'earlycon' is a valid param for devicetree earlycons;
e4b3d2e
 	 * don't generate a warning from parse_early_params() in that case
e4b3d2e
 	 */
e4b3d2e
-	if (!buf || !buf[0])
e4b3d2e
-		return early_init_dt_scan_chosen_stdout();
e4b3d2e
+	if (!buf || !buf[0]) {
e4b3d2e
+		if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) {
e4b3d2e
+			earlycon_init_is_deferred = true;
e4b3d2e
+			return 0;
e4b3d2e
+		} else {
e4b3d2e
+			return early_init_dt_scan_chosen_stdout();
e4b3d2e
+		}
e4b3d2e
+	}
e4b3d2e
 
e4b3d2e
 	err = setup_earlycon(buf);
e4b3d2e
 	if (err == -ENOENT || err == -EALREADY)
e4b3d2e
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
e4b3d2e
index 4d8452c..32407e4 100644
e4b3d2e
--- a/include/linux/acpi.h
e4b3d2e
+++ b/include/linux/acpi.h
e4b3d2e
@@ -1074,4 +1074,10 @@ void acpi_table_upgrade(void);
e4b3d2e
 static inline void acpi_table_upgrade(void) { }
e4b3d2e
 #endif
e4b3d2e
 
e4b3d2e
+#ifdef CONFIG_ACPI_SPCR_TABLE
e4b3d2e
+int parse_spcr(bool earlycon);
e4b3d2e
+#else
e4b3d2e
+static inline int parse_spcr(bool earlycon) { return 0; }
e4b3d2e
+#endif
e4b3d2e
+
e4b3d2e
 #endif	/*_LINUX_ACPI_H*/
e4b3d2e
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
e4b3d2e
index 2f44e20..04b8cfb 100644
e4b3d2e
--- a/include/linux/serial_core.h
e4b3d2e
+++ b/include/linux/serial_core.h
e4b3d2e
@@ -367,11 +367,18 @@ extern const struct earlycon_id __earlycon_table_end[];
e4b3d2e
 
e4b3d2e
 #define EARLYCON_DECLARE(_name, fn)	OF_EARLYCON_DECLARE(_name, "", fn)
e4b3d2e
 
e4b3d2e
-extern int setup_earlycon(char *buf);
e4b3d2e
 extern int of_setup_earlycon(const struct earlycon_id *match,
e4b3d2e
 			     unsigned long node,
e4b3d2e
 			     const char *options);
e4b3d2e
 
e4b3d2e
+#ifdef CONFIG_SERIAL_EARLYCON
e4b3d2e
+extern bool earlycon_init_is_deferred __initdata;
e4b3d2e
+extern int setup_earlycon(char *buf);
e4b3d2e
+#else
e4b3d2e
+static const bool earlycon_init_is_deferred;
e4b3d2e
+static inline int setup_earlycon(char *buf) { return 0; }
e4b3d2e
+#endif
e4b3d2e
+
e4b3d2e
 struct uart_port *uart_get_console(struct uart_port *ports, int nr,
e4b3d2e
 				   struct console *c);
e4b3d2e
 int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
e4b3d2e
From patchwork Thu Aug 11 15:31:40 2016
e4b3d2e
Content-Type: text/plain; charset="utf-8"
e4b3d2e
MIME-Version: 1.0
e4b3d2e
Content-Transfer-Encoding: 7bit
e4b3d2e
Subject: [v9,3/4] ARM64: ACPI: enable ACPI_SPCR_TABLE
e4b3d2e
From: Aleksey Makarov <aleksey.makarov@linaro.org>
e4b3d2e
X-Patchwork-Id: 9275457
e4b3d2e
Message-Id: <20160811153152.755-4-aleksey.makarov@linaro.org>
e4b3d2e
To: "Rafael J . Wysocki" <rjw@rjwysocki.net>,
e4b3d2e
 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
e4b3d2e
Cc: linux-serial@vger.kernel.org, linux-acpi@vger.kernel.org,
e4b3d2e
 linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
e4b3d2e
 Aleksey Makarov <aleksey.makarov@linaro.org>,
e4b3d2e
 Russell King <linux@arm.linux.org.uk>, Len Brown <lenb@kernel.org>,
e4b3d2e
 Leif Lindholm <leif.lindholm@linaro.org>,
e4b3d2e
 Graeme Gregory <graeme.gregory@linaro.org>, Al Stone <ahs3@redhat.com>,
e4b3d2e
 Christopher Covington <cov@codeaurora.org>,
e4b3d2e
 Yury Norov <ynorov@caviumnetworks.com>,
e4b3d2e
 Peter Hurley <peter@hurleysoftware.com>,
e4b3d2e
 Andy Shevchenko <andy.shevchenko@gmail.com>,
e4b3d2e
 "Zheng, Lv" <lv.zheng@intel.com>, Mark Salter <msalter@redhat.com>,
e4b3d2e
 Kefeng Wang <wangkefeng.wang@huawei.com>,
e4b3d2e
 Catalin Marinas <catalin.marinas@arm.com>,
e4b3d2e
 Will Deacon <will.deacon@arm.com>
e4b3d2e
Date: Thu, 11 Aug 2016 18:31:40 +0300
e4b3d2e
e4b3d2e
SBBR mentions SPCR as a mandatory ACPI table.  So enable it for ARM64
e4b3d2e
e4b3d2e
Earlycon should be set up as early as possible.  ACPI boot tables are
e4b3d2e
mapped in arch/arm64/kernel/acpi.c:acpi_boot_table_init() that
e4b3d2e
is called from setup_arch() and that's where we parse SPCR.
e4b3d2e
So it has to be opted-in per-arch.
e4b3d2e
e4b3d2e
When ACPI_SPCR_TABLE is defined initialization of DT earlycon is
e4b3d2e
deferred until the DT/ACPI decision is done.  Initialize DT earlycon
e4b3d2e
if ACPI is disabled.
e4b3d2e
e4b3d2e
Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>
e4b3d2e
Tested-by: Kefeng Wang <wangkefeng.wang@huawei.com>
e4b3d2e
---
e4b3d2e
 arch/arm64/Kconfig       |  1 +
e4b3d2e
 arch/arm64/kernel/acpi.c | 11 ++++++++++-
e4b3d2e
 2 files changed, 11 insertions(+), 1 deletion(-)
e4b3d2e
e4b3d2e
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
e4b3d2e
index 69c8787..a54dfc0 100644
e4b3d2e
--- a/arch/arm64/Kconfig
e4b3d2e
+++ b/arch/arm64/Kconfig
e4b3d2e
@@ -4,6 +4,7 @@ config ARM64
e4b3d2e
 	select ACPI_GENERIC_GSI if ACPI
e4b3d2e
 	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
e4b3d2e
 	select ACPI_MCFG if ACPI
e4b3d2e
+	select ACPI_SPCR_TABLE if ACPI
e4b3d2e
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
e4b3d2e
 	select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
e4b3d2e
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
e4b3d2e
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
e4b3d2e
index 3e4f1a4..252a6d9 100644
e4b3d2e
--- a/arch/arm64/kernel/acpi.c
e4b3d2e
+++ b/arch/arm64/kernel/acpi.c
e4b3d2e
@@ -24,6 +24,7 @@
e4b3d2e
 #include <linux/memblock.h>
e4b3d2e
 #include <linux/of_fdt.h>
e4b3d2e
 #include <linux/smp.h>
e4b3d2e
+#include <linux/serial_core.h>
e4b3d2e
 
e4b3d2e
 #include <asm/cputype.h>
e4b3d2e
 #include <asm/cpu_ops.h>
e4b3d2e
@@ -206,7 +207,7 @@ void __init acpi_boot_table_init(void)
e4b3d2e
 	if (param_acpi_off ||
e4b3d2e
 	    (!param_acpi_on && !param_acpi_force &&
e4b3d2e
 	     of_scan_flat_dt(dt_scan_depth1_nodes, NULL)))
e4b3d2e
-		return;
e4b3d2e
+		goto done;
e4b3d2e
 
e4b3d2e
 	/*
e4b3d2e
 	 * ACPI is disabled at this point. Enable it in order to parse
e4b3d2e
@@ -226,6 +227,14 @@ void __init acpi_boot_table_init(void)
e4b3d2e
 		if (!param_acpi_force)
e4b3d2e
 			disable_acpi();
e4b3d2e
 	}
e4b3d2e
+
e4b3d2e
+done:
e4b3d2e
+	if (acpi_disabled) {
e4b3d2e
+		if (earlycon_init_is_deferred)
e4b3d2e
+			early_init_dt_scan_chosen_stdout();
e4b3d2e
+	} else {
e4b3d2e
+		parse_spcr(earlycon_init_is_deferred);
e4b3d2e
+	}
e4b3d2e
 }
e4b3d2e
 
e4b3d2e
 #ifdef CONFIG_ACPI_APEI
e4b3d2e
From patchwork Mon Aug 15 13:35:03 2016
e4b3d2e
Content-Type: text/plain; charset="utf-8"
e4b3d2e
MIME-Version: 1.0
e4b3d2e
Content-Transfer-Encoding: 7bit
e4b3d2e
Subject: [v9,4/4] serial: pl011: add console matching function
e4b3d2e
From: Aleksey Makarov <aleksey.makarov@linaro.org>
e4b3d2e
X-Patchwork-Id: 9280971
e4b3d2e
Message-Id: <20160815133505.15294-1-aleksey.makarov@linaro.org>
e4b3d2e
To: "Rafael J . Wysocki" <rjw@rjwysocki.net>,
e4b3d2e
 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
e4b3d2e
Cc: linux-serial@vger.kernel.org, linux-acpi@vger.kernel.org,
e4b3d2e
 linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
e4b3d2e
 Aleksey Makarov <aleksey.makarov@linaro.org>,
e4b3d2e
 Russell King <linux@arm.linux.org.uk>, Len Brown <lenb@kernel.org>,
e4b3d2e
 Leif Lindholm <leif.lindholm@linaro.org>,
e4b3d2e
 Graeme Gregory <graeme.gregory@linaro.org>, Al Stone <ahs3@redhat.com>,
e4b3d2e
 Christopher Covington <cov@codeaurora.org>,
e4b3d2e
 Yury Norov <ynorov@caviumnetworks.com>,
e4b3d2e
 Peter Hurley <peter@hurleysoftware.com>,
e4b3d2e
 Andy Shevchenko <andy.shevchenko@gmail.com>,
e4b3d2e
 "Zheng, Lv" <lv.zheng@intel.com>, Mark Salter <msalter@redhat.com>,
e4b3d2e
 Kefeng Wang <wangkefeng.wang@huawei.com>,
e4b3d2e
 Russell King <linux@armlinux.org.uk>, Jiri Slaby <jslaby@suse.com>
e4b3d2e
Date: Mon, 15 Aug 2016 16:35:03 +0300
e4b3d2e
e4b3d2e
This patch adds function pl011_console_match() that implements
e4b3d2e
method match of struct console.  It allows to match consoles against
e4b3d2e
data specified in a string, for example taken from command line or
e4b3d2e
compiled by ACPI SPCR table handler.
e4b3d2e
e4b3d2e
Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>
e4b3d2e
Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
e4b3d2e
Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
e4b3d2e
---
e4b3d2e
 drivers/tty/serial/amba-pl011.c | 55 +++++++++++++++++++++++++++++++++++++++++
e4b3d2e
 1 file changed, 55 insertions(+)
e4b3d2e
e4b3d2e
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
e4b3d2e
index 8a9e213..2f9af8a 100644
e4b3d2e
--- a/drivers/tty/serial/amba-pl011.c
e4b3d2e
+++ b/drivers/tty/serial/amba-pl011.c
e4b3d2e
@@ -2288,12 +2288,67 @@ static int __init pl011_console_setup(struct console *co, char *options)
e4b3d2e
 	return uart_set_options(&uap->port, co, baud, parity, bits, flow);
e4b3d2e
 }
e4b3d2e
 
e4b3d2e
+/**
e4b3d2e
+ *	pl011_console_match - non-standard console matching
e4b3d2e
+ *	@co:	  registering console
e4b3d2e
+ *	@name:	  name from console command line
e4b3d2e
+ *	@idx:	  index from console command line
e4b3d2e
+ *	@options: ptr to option string from console command line
e4b3d2e
+ *
e4b3d2e
+ *	Only attempts to match console command lines of the form:
e4b3d2e
+ *	    console=pl011,mmio|mmio32,<addr>[,<options>]
e4b3d2e
+ *	    console=pl011,0x<addr>[,<options>]
e4b3d2e
+ *	This form is used to register an initial earlycon boot console and
e4b3d2e
+ *	replace it with the amba_console at pl011 driver init.
e4b3d2e
+ *
e4b3d2e
+ *	Performs console setup for a match (as required by interface)
e4b3d2e
+ *	If no <options> are specified, then assume the h/w is already setup.
e4b3d2e
+ *
e4b3d2e
+ *	Returns 0 if console matches; otherwise non-zero to use default matching
e4b3d2e
+ */
e4b3d2e
+static int __init pl011_console_match(struct console *co, char *name, int idx,
e4b3d2e
+				      char *options)
e4b3d2e
+{
e4b3d2e
+	unsigned char iotype;
e4b3d2e
+	unsigned long addr;
e4b3d2e
+	int i;
e4b3d2e
+
e4b3d2e
+	if (strcmp(name, "pl011") != 0)
e4b3d2e
+		return -ENODEV;
e4b3d2e
+
e4b3d2e
+	if (uart_parse_earlycon(options, &iotype, &addr, &options))
e4b3d2e
+		return -ENODEV;
e4b3d2e
+
e4b3d2e
+	if (iotype != UPIO_MEM && iotype != UPIO_MEM32)
e4b3d2e
+		return -ENODEV;
e4b3d2e
+
e4b3d2e
+	/* try to match the port specified on the command line */
e4b3d2e
+	for (i = 0; i < ARRAY_SIZE(amba_ports); i++) {
e4b3d2e
+		struct uart_port *port;
e4b3d2e
+
e4b3d2e
+		if (!amba_ports[i])
e4b3d2e
+			continue;
e4b3d2e
+
e4b3d2e
+		port = &amba_ports[i]->port;
e4b3d2e
+
e4b3d2e
+		if (port->mapbase != addr)
e4b3d2e
+			continue;
e4b3d2e
+
e4b3d2e
+		co->index = i;
e4b3d2e
+		port->cons = co;
e4b3d2e
+		return pl011_console_setup(co, options);
e4b3d2e
+	}
e4b3d2e
+
e4b3d2e
+	return -ENODEV;
e4b3d2e
+}
e4b3d2e
+
e4b3d2e
 static struct uart_driver amba_reg;
e4b3d2e
 static struct console amba_console = {
e4b3d2e
 	.name		= "ttyAMA",
e4b3d2e
 	.write		= pl011_console_write,
e4b3d2e
 	.device		= uart_console_device,
e4b3d2e
 	.setup		= pl011_console_setup,
e4b3d2e
+	.match		= pl011_console_match,
e4b3d2e
 	.flags		= CON_PRINTBUFFER,
e4b3d2e
 	.index		= -1,
e4b3d2e
 	.data		= &amba_reg,