linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA.
       [not found] <cover.1347453194.git.zetalog@gmail.com>
@ 2012-09-28  2:39 ` Lv Zheng
  2012-09-28  2:40   ` [PATCH v4 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
                     ` (5 more replies)
  2012-10-09  2:36 ` [PATCH v5 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
  2012-10-09  2:37 ` [PATCH v5 2/2] ACPI: Add Intel MID SPI early console support Lv Zheng
  2 siblings, 6 replies; 26+ messages in thread
From: Lv Zheng @ 2012-09-28  2:39 UTC (permalink / raw)
  To: Len Brown; +Cc: linux-kernel, linux-acpi, Lv Zheng

Microsoft Debug Port Table (DBGP or DBG2) is used by the Windows SoC
platforms to describe their debugging facilities.
Recent Low Power Intel Architecture (LPIA) platforms have utilized
this for the SPI UART debug ports that are resident on their debug
boards.

This patch set enables the DBGP/DBG2 debug ports as an Linux early
console launcher.
The SPI UART debug ports support is also refined to co-exist with this
new usage model.

To use this facility on LPIA platforms, you need to enable the following
kernel configurations:
  CONFIG_EARLY_PRINTK_ACPI=y
  CONFIG_EARLY_PRINTK_INTEL_MID_SPI=y
Then you need to append the following kernel parameter to the kernel
command line in your the boot loader configuration file:
  earlyprintk=acpi

There is a dilemma in designing this patch set.  There should be three
steps to enable an early console for an operating system:
1. Probe: In this stage, the Linux kernel can detect the early consoles
          and the base address of their register block can be determined.
          This can be done by parsing the descriptors in the ACPI DBGP/DBG2
          tables.  Note that acpi_table_init() must be called before
          parsing.
2. Setup: In this stage, the Linux kernel can apply user specified
          configuration options (ex. baudrate of serial ports) for the
          early consoles.  This is done by parsing the early parameters
          passed to the kernel from the boot loaders.  Note that
          parse_early_params() is called very early to allow parameters to
          be passed to other kernel subsystems.
3. Start: In this stage, the Linux kernel can make the console available
          to output messages.  Since early consoles are always used for
          kernel boot up debugging, this must be done as early as possible
          to arm the kernel with more testability the kernel subsystems.
          Note that, this stage happens when the register_console() is
          called.
The preferred sequence for the above steps is:
   +-----------------+    +-------------------+    +--------------------+
   | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-----------------+    +-------------------+    +--------------------+
But unfortunately, in the current x86 implementation, early parameters and
early printk initialization are called before acpi_table_init() which
requires early memory mapping facility.
There are some choices for me to design this patch set:
1. Invoking acpi_table_init() before parse_early_param() to maintain the
   sequence:
   +-----------------+    +-------------------+    +--------------------+
   | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-----------------+    +-------------------+    +--------------------+
   This requires other subsystem maintainers' review to ensure no
   regressions will be introduced.  As far as I know, one kind of issue
   might be found in EFI subsystsm:
   The EFI boot services and runtime services are mixed up in the x86
   specific initialization process before the ACPI table initialization.
   Things are much worse that you even cannot disable the runtime services
   while still allow the boot services codes to be executed in the kernel
   compilation stage.  Enabling the early consoles after the ACPI table
   initialization will make it difficult to debug the runtime BIOS bugs.
   If any progress is made to the kernel boot sequences, please let me
   know.  I'll be willing to redesign the ACPI DBGP/DBG2 console probing
   facility.  You can reach me at <zetalog@gmail.com>.
2. Modifying above sequece to make it look like:
   +-------------------+    +-----------------+    +--------------------+
   | EARLY_PARAM SETUP | -> | ACPI DBGP PROBE | -> | EARLY_RPINTK START |
   +-------------------+    +-----------------+    +--------------------+
   Early consoles started in this style will lose some debuggabilities in
   the kernel boot up.  If the system does not crash very early,
   developers still can see the bufferred kernel outputs when the
   register_console() is called.
   Current early console implementation need to be modified to split their
   initialization codes into tow part:
   1. Detecting hardware.  This can be called in the PROBE stage.
   2. Applying user parameters.  This can be called in the SETUP stage.
   Individual early console drver maintainers need to be involved to avoid
   regressions that might occur on this modification as the maintainers
   might offer the real tests rather than I can do. 
3. Introducing a barely new debugging facility that does not relate to the
   current early console implementation to allow automatic detection for
   the early consoles.
   +-------------------+    +--------------------+
   | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-------------------+    +--------------------+
   +-----------------+    +--------------------+
   | ACPI DBGP PROBE | -> | EARLY_RPINTK START |
   +-----------------+    +--------------------+
   This is what the patch set has done to enable this new usage model.
   It is known as "ACPI early console launcher mode".
   Early consoles started in this style will lose some debuggabilities in
   the kernel boot up.  If the system does not crash very early,
   developers still can see the bufferred kernel outputs when the
   register_console() is called.
   Note that the user configuration can not be applied to the registered
   early consoles in this way as the acpi_table_init() is still called
   after the parse_early_param().  Instead, the early consoles should
   derive the hardware settings used in the BIOS/bootloaders.
   As a launcher, ACPI DBGP will not actually output kernel messages
   without the real early console drivers, that's why the
   CONFIG_EARLY_PRINTK_INTEL_MID_SPI is still need to be enabled along
   along with the CONFIG_EARLY_PRINTK_ACPI.
   In order to disable this facility by default and enable it at runtime,
   an kernel parameter "earlyprintk=acpi" is introduced.  This makes the
   actual sequence looks like:
   +-------------------+    +--------------------+
   | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-------------------+    +....................+    +-----------------+
                            | ACPI DBGP LAUNCH   | -> | ACPI DBGP PROBE | ->
                            +--------------------+    +-----------------+
      +--------------------+
   -> | EARLY_RPINTK START |
      +--------------------+

Version 3 of this patch set is the first version that will be published
in the Linux community.  Earlier versions are reviewed internally in
Intel.  This patch set keeps the version number to track the history
that is known to Intel internal developers.
Version 4 of this patch set fixed bunch of CodingStyle issues.

Lv Zheng (2):
  ACPI: Add early console framework for DBGP/DBG2.
  ACPI: Add Intel MID SPI early console support.

 Documentation/kernel-parameters.txt        |    2 +
 arch/x86/Kconfig.debug                     |   38 +++++
 arch/x86/include/asm/mrst.h                |    2 +-
 arch/x86/kernel/acpi/boot.c                |    1 +
 arch/x86/kernel/early_printk.c             |   25 +++-
 arch/x86/platform/mrst/early_printk_mrst.c |  186 +----------------------
 drivers/acpi/Makefile                      |    2 +
 drivers/acpi/early_printk.c                |  201 +++++++++++++++++++++++++
 drivers/platform/x86/Makefile              |    2 +
 drivers/platform/x86/early/Makefile        |    5 +
 drivers/platform/x86/early/intel_mid_spi.c |  220 ++++++++++++++++++++++++++++
 include/acpi/actbl2.h                      |    1 +
 include/linux/acpi.h                       |   24 +++
 include/linux/intel_mid_early.h            |   12 ++
 14 files changed, 540 insertions(+), 181 deletions(-)
 create mode 100644 drivers/acpi/early_printk.c
 create mode 100644 drivers/platform/x86/early/Makefile
 create mode 100644 drivers/platform/x86/early/intel_mid_spi.c
 create mode 100644 include/linux/intel_mid_early.h

-- 
1.7.10


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH v4 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2012-09-28  2:39 ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Lv Zheng
@ 2012-09-28  2:40   ` Lv Zheng
  2012-09-28  2:40   ` [PATCH v4 2/2] ACPI: Add Intel MID SPI early console support Lv Zheng
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 26+ messages in thread
From: Lv Zheng @ 2012-09-28  2:40 UTC (permalink / raw)
  To: Len Brown; +Cc: linux-kernel, linux-acpi, Lv Zheng

Microsoft Debug Port Table (DBGP or DBG2) is required for Windows SoC
platforms.  This patch is introduced to fix the gap between Windows
and Linux.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
 Documentation/kernel-parameters.txt |    1 +
 arch/x86/Kconfig.debug              |   15 +++
 arch/x86/kernel/acpi/boot.c         |    1 +
 arch/x86/kernel/early_printk.c      |   13 +++
 drivers/acpi/Makefile               |    2 +
 drivers/acpi/early_printk.c         |  201 +++++++++++++++++++++++++++++++++++
 include/linux/acpi.h                |   24 +++++
 7 files changed, 257 insertions(+)
 create mode 100644 drivers/acpi/early_printk.c

Index: linux-acpi/Documentation/kernel-parameters.txt
===================================================================
--- linux-acpi.orig/Documentation/kernel-parameters.txt	2012-09-27 22:35:07.000000000 +0800
+++ linux-acpi/Documentation/kernel-parameters.txt	2012-09-27 22:35:44.000000000 +0800
@@ -763,6 +763,7 @@
 			earlyprintk=serial[,ttySn[,baudrate]]
 			earlyprintk=ttySn[,baudrate]
 			earlyprintk=dbgp[debugController#]
+			earlyprintk=acpi[debugController#]
 
 			Append ",keep" to not disable it when the real console
 			takes over.
Index: linux-acpi/arch/x86/Kconfig.debug
===================================================================
--- linux-acpi.orig/arch/x86/Kconfig.debug	2012-09-27 22:35:07.000000000 +0800
+++ linux-acpi/arch/x86/Kconfig.debug	2012-09-27 22:35:44.000000000 +0800
@@ -59,6 +59,21 @@
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash. You need usb debug device.
 
+config EARLY_PRINTK_ACPI
+	bool "Early printk launcher via ACPI debug port tables"
+	depends on EARLY_PRINTK && ACPI
+	---help---
+	  Write kernel log output directly into the debug ports described
+	  in the ACPI tables known as DBGP and DBG2.
+
+	  To enable such debugging facilities, you need to enable this
+	  configuration option and append the "earlyprintk=acpi" kernel
+	  parameter through the boot loaders.  Please refer the
+	  "Documentation/kernel-parameters.txt" for details.  Since this
+	  is an early console launcher, you still need to enable actual
+	  early console drivers that are suitable for your platform.
+	  If in doubt, say "N".
+
 config DEBUG_STACKOVERFLOW
 	bool "Check for stack overflows"
 	depends on DEBUG_KERNEL
Index: linux-acpi/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-acpi.orig/arch/x86/kernel/acpi/boot.c	2012-09-27 22:35:07.000000000 +0800
+++ linux-acpi/arch/x86/kernel/acpi/boot.c	2012-09-27 22:35:13.000000000 +0800
@@ -1518,6 +1518,7 @@
 		return;
 	}
 
+	acpi_early_console_parse();
 	acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
 
 	/*
Index: linux-acpi/arch/x86/kernel/early_printk.c
===================================================================
--- linux-acpi.orig/arch/x86/kernel/early_printk.c	2012-09-27 22:35:07.000000000 +0800
+++ linux-acpi/arch/x86/kernel/early_printk.c	2012-09-27 22:35:44.000000000 +0800
@@ -200,6 +200,15 @@
 	register_console(early_console);
 }
 
+#ifdef CONFIG_EARLY_PRINTK_ACPI
+#include <linux/acpi.h>
+
+int __init acpi_early_console_setup(struct acpi_debug_port *info)
+{
+	return 0;
+}
+#endif
+
 static int __init setup_early_printk(char *buf)
 {
 	int keep;
@@ -236,6 +245,10 @@
 		if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4))
 			early_console_register(&early_dbgp_console, keep);
 #endif
+#ifdef CONFIG_EARLY_PRINTK_ACPI
+		if (!strncmp(buf, "acpi", 4))
+			acpi_early_console_init(buf + 4, keep);
+#endif
 #ifdef CONFIG_HVC_XEN
 		if (!strncmp(buf, "xen", 3))
 			early_console_register(&xenboot_console, keep);
Index: linux-acpi/drivers/acpi/Makefile
===================================================================
--- linux-acpi.orig/drivers/acpi/Makefile	2012-09-27 22:35:07.000000000 +0800
+++ linux-acpi/drivers/acpi/Makefile	2012-09-27 22:35:36.000000000 +0800
@@ -46,6 +46,8 @@
 acpi-y				+= video_detect.o
 endif
 
+obj-$(CONFIG_EARLY_PRINTK_ACPI)	+= early_printk.o
+
 # These are (potentially) separate modules
 obj-$(CONFIG_ACPI_AC) 		+= ac.o
 obj-$(CONFIG_ACPI_BUTTON)	+= button.o
Index: linux-acpi/drivers/acpi/early_printk.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-acpi/drivers/acpi/early_printk.c	2012-09-27 22:35:13.000000000 +0800
@@ -0,0 +1,201 @@
+/*
+ *  acpi/early_printk.c - ACPI Boot-Time Debug Ports
+ *
+ *  Copyright (C) 2012 Lv Zheng <lv.zheng@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/acpi.h>
+#include <linux/bootmem.h>
+
+#define ACPI_EARLY_DISABLED	0x0000
+#define ACPI_EARLY_ENABLED	0x0001
+#define ACPI_EARLY_KEEP		0x0002
+#define ACPI_EARLY_PORT_MSK	0xFF00
+#define ACPI_EARLY_PORT_OFF	8
+
+u16 acpi_early_flags = ACPI_EARLY_DISABLED;
+
+static inline bool acpi_early_enabled(void)
+{
+	return acpi_early_flags & ACPI_EARLY_ENABLED;
+}
+
+static inline u8 acpi_early_port_index(void)
+{
+	return (acpi_early_flags & ACPI_EARLY_PORT_MSK) >> ACPI_EARLY_PORT_OFF;
+}
+
+int __init acpi_early_console_keep(void)
+{
+	return acpi_early_flags & ACPI_EARLY_KEEP ? 1 : 0;
+}
+
+static inline int acpi_table_parse_dbg2(acpi_early_console_handler handler)
+{
+	struct acpi_table_header *table_header = NULL;
+	struct acpi_dbg2_device *entry;
+	unsigned int count = 0;
+	unsigned long table_end;
+	acpi_size tbl_size;
+	unsigned int max_entries;
+	struct acpi_debug_port devinfo;
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	if (!handler)
+		return -EINVAL;
+
+	acpi_get_table(ACPI_SIG_DBG2, 0, &table_header);
+	if (!table_header) {
+		pr_warn("DBG2 not present\n");
+		return -ENODEV;
+	}
+	tbl_size = table_header->length;
+	table_end = (unsigned long)table_header + table_header->length;
+
+	entry = (struct acpi_dbg2_device *)
+	    ((unsigned long)table_header +
+	     ((struct acpi_table_dbg2 *)table_header)->info_offset);
+	max_entries = ((struct acpi_table_dbg2 *)table_header)->info_count;
+
+	while (((unsigned long)entry) + sizeof(struct acpi_dbg2_device) <
+	       table_end) {
+		if (entry->revision != 0) {
+			pr_warn("DBG2 revision %d not supported\n",
+				entry->revision);
+			count = -ENODEV;
+			goto fail;
+		}
+		if (!max_entries || count++ < max_entries) {
+			devinfo.port_index = (u8)count;
+			devinfo.port_type = entry->port_type;
+			devinfo.port_subtype = entry->port_subtype;
+			devinfo.register_count = entry->register_count;
+			devinfo.registers = (struct acpi_generic_address *)
+			    ((unsigned long)entry + entry->base_address_offset);
+			devinfo.namepath_length = entry->namepath_length;
+			devinfo.namepath = (char *)
+			    ((unsigned long)entry + entry->namepath_offset);
+			devinfo.oem_data_length = entry->oem_data_length;
+			devinfo.oem_data = (u8 *)
+			    ((unsigned long)entry + entry->oem_data_offset);
+
+			if (handler(&devinfo, table_end)) {
+				count = -ENODEV;
+				goto fail;
+			}
+		}
+
+		entry = (struct acpi_dbg2_device *)
+		    ((unsigned long)entry + entry->length);
+	}
+
+fail:
+	early_acpi_os_unmap_memory((char *)table_header, tbl_size);
+	return count;
+}
+
+static int __init acpi_parse_early_console(struct acpi_debug_port *info,
+					   const unsigned long end)
+{
+	pr_info("early: DBG2 console %d detected: %04x:%04x.\n",
+		info->port_index, info->port_type, info->port_subtype);
+
+	if (acpi_early_port_index() != 0 &&
+	    acpi_early_port_index() != info->port_index)
+		return 0;
+
+	acpi_early_console_setup(info);
+
+	return 0;
+}
+
+static int __init acpi_parse_dbgp(struct acpi_table_header *table)
+{
+	struct acpi_table_dbgp *dbgp;
+	struct acpi_debug_port devinfo;
+
+	if (acpi_early_port_index() != 0 &&
+	    acpi_early_port_index() != 1)
+		return 0;
+
+	dbgp = (struct acpi_table_dbgp *)table;
+	if (!dbgp) {
+		pr_warn("Unable to map DBGP\n");
+		return -ENODEV;
+	}
+
+	pr_info("early: DBGP console detected: %04x.\n",
+		dbgp->type);
+
+	devinfo.port_index = 1;
+	devinfo.port_type = ACPI_DBG2_SERIAL_PORT;
+	devinfo.port_subtype = dbgp->type;
+	devinfo.register_count = 1;
+	devinfo.registers = (struct acpi_generic_address *)&dbgp->debug_port;
+	devinfo.namepath_length = 0;
+	devinfo.namepath = NULL;
+	devinfo.oem_data_length = 0;
+	devinfo.oem_data = NULL;
+
+	acpi_parse_early_console(&devinfo, 0);
+
+	return 0;
+}
+
+int __init acpi_early_console_parse(void)
+{
+	if (!acpi_early_enabled())
+		return -EINVAL;
+
+	if (acpi_table_parse_dbg2(acpi_parse_early_console) == 0)
+		acpi_table_parse(ACPI_SIG_DBGP, acpi_parse_dbgp);
+
+	return 0;
+}
+
+int __init acpi_early_console_init(char *s, int keep)
+{
+	acpi_early_flags = ACPI_EARLY_ENABLED;
+	if (keep)
+		acpi_early_flags |= ACPI_EARLY_KEEP;
+
+	if (*s) {
+		int ret;
+		unsigned long port;
+
+		ret = kstrtoul(s, 10, &port);
+		if (!ret)
+			acpi_early_flags |= ((u8)port) << ACPI_EARLY_PORT_OFF;
+	}
+
+	pr_info("early: debug port index %d.\n", acpi_early_port_index());
+
+	return 0;
+}
+
Index: linux-acpi/include/linux/acpi.h
===================================================================
--- linux-acpi.orig/include/linux/acpi.h	2012-09-27 22:35:07.000000000 +0800
+++ linux-acpi/include/linux/acpi.h	2012-09-27 22:35:41.000000000 +0800
@@ -430,4 +430,28 @@
 #define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
 #endif
 
+#ifdef CONFIG_EARLY_PRINTK_ACPI
+struct acpi_debug_port {
+	u8 port_index;
+	u16 port_type;
+	u16 port_subtype;
+	u16 register_count;
+	struct acpi_generic_address *registers;
+	u16 namepath_length;
+	char *namepath;
+	u16 oem_data_length;
+	u8 *oem_data;
+};
+
+typedef int (*acpi_early_console_handler)(struct acpi_debug_port *dev,
+					  const unsigned long end);
+
+int __init acpi_early_console_keep(void);
+int __init acpi_early_console_init(char *s, int keep);
+int __init acpi_early_console_parse(void);
+int __init acpi_early_console_setup(struct acpi_debug_port *info);
+#else
+static int acpi_early_console_parse(void) { return 0; }
+#endif
+
 #endif	/*_LINUX_ACPI_H*/

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH v4 2/2] ACPI: Add Intel MID SPI early console support.
  2012-09-28  2:39 ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Lv Zheng
  2012-09-28  2:40   ` [PATCH v4 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
@ 2012-09-28  2:40   ` Lv Zheng
  2012-09-28  5:24   ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Zheng, Lv
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 26+ messages in thread
From: Lv Zheng @ 2012-09-28  2:40 UTC (permalink / raw)
  To: Len Brown; +Cc: linux-kernel, linux-acpi, Lv Zheng

DesignWare SPI UART is used as one of the debug ports on Low Power Intel
Architecture (LPIA) platforms.  This patch is introduced to support this
debugging console reported by ACPI DBGP/DBG2.  The original MID SPI
early console stuff is also refined to co-exist with the new ACPI usage
model.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
 Documentation/kernel-parameters.txt        |    1 +
 arch/x86/Kconfig.debug                     |   23 +++
 arch/x86/include/asm/mrst.h                |    2 +-
 arch/x86/kernel/early_printk.c             |   12 +-
 arch/x86/platform/mrst/early_printk_mrst.c |  186 +----------------------
 drivers/platform/x86/Makefile              |    2 +
 drivers/platform/x86/early/Makefile        |    5 +
 drivers/platform/x86/early/intel_mid_spi.c |  220 ++++++++++++++++++++++++++++
 include/acpi/actbl2.h                      |    1 +
 include/linux/intel_mid_early.h            |   12 ++
 10 files changed, 283 insertions(+), 181 deletions(-)
 create mode 100644 drivers/platform/x86/early/Makefile
 create mode 100644 drivers/platform/x86/early/intel_mid_spi.c
 create mode 100644 include/linux/intel_mid_early.h

Index: linux-acpi/arch/x86/Kconfig.debug
===================================================================
--- linux-acpi.orig/arch/x86/Kconfig.debug	2012-09-27 22:35:13.000000000 +0800
+++ linux-acpi/arch/x86/Kconfig.debug	2012-09-27 22:35:14.000000000 +0800
@@ -43,9 +43,32 @@
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash.
 
+config EARLY_PRINTK_INTEL_MID_SPI
+	bool "Early printk for Intel MID SPI UART port"
+	depends on EARLY_PRINTK
+	---help---
+	  Write kernel log output directly into the MID SPI UART debug port.
+
+	  Intel MID platforms are using DesignWare SPI UART as its debug
+	  console.  This option does not introduce actual early console into
+	  the kernel binary, but is required by a real early console
+	  implementation (EARLY_PRINTK_INTEL_MID or EARLY_PRINTK_ACPI).
+	  You should normally N here unless you need to do kernel booting
+	  development.
+
 config EARLY_PRINTK_INTEL_MID
 	bool "Early printk for Intel MID platform support"
 	depends on EARLY_PRINTK && X86_INTEL_MID
+	select EARLY_PRINTK_INTEL_MID_SPI
+	---help---
+	  Write kernel log output directly into the MID SPI UART debug port.
+
+	  Intel MID platforms are always equipped with SPI debug ports and
+	  USB OTG debug ports. To enable these debugging facilities, you
+	  need to pass "earlyprintk=mrst" parameter to the kernel through
+	  boot loaders.  Please see "Documentation/kernel-parameter.txt" for
+	  details.  You should normally N here unless you need to do kernel
+	  booting development.
 
 config EARLY_PRINTK_DBGP
 	bool "Early printk via EHCI debug port"
Index: linux-acpi/arch/x86/include/asm/mrst.h
===================================================================
--- linux-acpi.orig/arch/x86/include/asm/mrst.h	2012-09-27 22:35:05.000000000 +0800
+++ linux-acpi/arch/x86/include/asm/mrst.h	2012-09-27 22:35:41.000000000 +0800
@@ -12,6 +12,7 @@
 #define _ASM_X86_MRST_H
 
 #include <linux/sfi.h>
+#include <linux/intel_mid_early.h>
 
 extern int pci_mrst_init(void);
 extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
@@ -63,7 +64,6 @@
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX	8
 
-extern struct console early_mrst_console;
 extern void mrst_early_console_init(void);
 
 extern struct console early_hsu_console;
Index: linux-acpi/arch/x86/kernel/early_printk.c
===================================================================
--- linux-acpi.orig/arch/x86/kernel/early_printk.c	2012-09-27 22:35:13.000000000 +0800
+++ linux-acpi/arch/x86/kernel/early_printk.c	2012-09-27 22:35:42.000000000 +0800
@@ -205,6 +205,16 @@
 
 int __init acpi_early_console_setup(struct acpi_debug_port *info)
 {
+#ifdef CONFIG_EARLY_PRINTK_INTEL_MID_SPI
+	if (info->port_type == ACPI_DBG2_SERIAL_PORT
+	    && info->port_subtype == ACPI_DBG2_INTEL_MID_SPI
+	    && info->register_count > 0) {
+		mid_spi_early_console_init((u32)(info->registers[0].address));
+		early_console_register(&mid_spi_early_console,
+				       acpi_early_console_keep());
+	}
+#endif
+
 	return 0;
 }
 #endif
@@ -256,7 +266,7 @@
 #ifdef CONFIG_EARLY_PRINTK_INTEL_MID
 		if (!strncmp(buf, "mrst", 4)) {
 			mrst_early_console_init();
-			early_console_register(&early_mrst_console, keep);
+			early_console_register(&mid_spi_early_console, keep);
 		}
 
 		if (!strncmp(buf, "hsu", 3)) {
Index: linux-acpi/arch/x86/platform/mrst/early_printk_mrst.c
===================================================================
--- linux-acpi.orig/arch/x86/platform/mrst/early_printk_mrst.c	2012-09-27 22:35:05.000000000 +0800
+++ linux-acpi/arch/x86/platform/mrst/early_printk_mrst.c	2012-09-27 22:35:14.000000000 +0800
@@ -29,82 +29,8 @@
 #include <asm/pgtable.h>
 #include <asm/mrst.h>
 
-#define MRST_SPI_TIMEOUT		0x200000
 #define MRST_REGBASE_SPI0		0xff128000
 #define MRST_REGBASE_SPI1		0xff128400
-#define MRST_CLK_SPI0_REG		0xff11d86c
-
-/* Bit fields in CTRLR0 */
-#define SPI_DFS_OFFSET			0
-
-#define SPI_FRF_OFFSET			4
-#define SPI_FRF_SPI			0x0
-#define SPI_FRF_SSP			0x1
-#define SPI_FRF_MICROWIRE		0x2
-#define SPI_FRF_RESV			0x3
-
-#define SPI_MODE_OFFSET			6
-#define SPI_SCPH_OFFSET			6
-#define SPI_SCOL_OFFSET			7
-#define SPI_TMOD_OFFSET			8
-#define	SPI_TMOD_TR			0x0		/* xmit & recv */
-#define SPI_TMOD_TO			0x1		/* xmit only */
-#define SPI_TMOD_RO			0x2		/* recv only */
-#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
-
-#define SPI_SLVOE_OFFSET		10
-#define SPI_SRL_OFFSET			11
-#define SPI_CFS_OFFSET			12
-
-/* Bit fields in SR, 7 bits */
-#define SR_MASK				0x7f		/* cover 7 bits */
-#define SR_BUSY				(1 << 0)
-#define SR_TF_NOT_FULL			(1 << 1)
-#define SR_TF_EMPT			(1 << 2)
-#define SR_RF_NOT_EMPT			(1 << 3)
-#define SR_RF_FULL			(1 << 4)
-#define SR_TX_ERR			(1 << 5)
-#define SR_DCOL				(1 << 6)
-
-struct dw_spi_reg {
-	u32	ctrl0;
-	u32	ctrl1;
-	u32	ssienr;
-	u32	mwcr;
-	u32	ser;
-	u32	baudr;
-	u32	txfltr;
-	u32	rxfltr;
-	u32	txflr;
-	u32	rxflr;
-	u32	sr;
-	u32	imr;
-	u32	isr;
-	u32	risr;
-	u32	txoicr;
-	u32	rxoicr;
-	u32	rxuicr;
-	u32	msticr;
-	u32	icr;
-	u32	dmacr;
-	u32	dmatdlr;
-	u32	dmardlr;
-	u32	idr;
-	u32	version;
-
-	/* Currently operates as 32 bits, though only the low 16 bits matter */
-	u32	dr;
-} __packed;
-
-#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
-#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
-
-/* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */
-static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0;
-
-static u32 *pclk_spi0;
-/* Always contains an accessible address, start with 0 */
-static struct dw_spi_reg *pspi;
 
 static struct kmsg_dumper dw_dumper;
 static int dumper_registered;
@@ -116,77 +42,21 @@
 	size_t len;
 
 	/* When run to this, we'd better re-init the HW */
-	mrst_early_console_init();
+	mid_spi_early_console_reset();
 
 	while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len))
-		early_mrst_console.write(&early_mrst_console, line, len);
-}
-
-/* Set the ratio rate to 115200, 8n1, IRQ disabled */
-static void max3110_write_config(void)
-{
-	u16 config;
-
-	config = 0xc001;
-	dw_writel(pspi, dr, config);
-}
-
-/* Translate char to a eligible word and send to max3110 */
-static void max3110_write_data(char c)
-{
-	u16 data;
-
-	data = 0x8000 | c;
-	dw_writel(pspi, dr, data);
+		mid_spi_early_console.write(&mid_spi_early_console, line, len);
 }
 
 void mrst_early_console_init(void)
 {
-	u32 ctrlr0 = 0;
-	u32 spi0_cdiv;
-	u32 freq; /* Freqency info only need be searched once */
-
-	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
-	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
-							MRST_CLK_SPI0_REG);
-	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
-	freq = 100000000 / (spi0_cdiv + 1);
+	/* Default use SPI0 register for mrst */
+	unsigned long spi_paddr = MRST_REGBASE_SPI0;
 
+	/* Detect Penwell and use SPI1 */
 	if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL)
-		mrst_spi_paddr = MRST_REGBASE_SPI1;
-
-	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
-						mrst_spi_paddr);
-
-	/* Disable SPI controller */
-	dw_writel(pspi, ssienr, 0);
-
-	/* Set control param, 8 bits, transmit only mode */
-	ctrlr0 = dw_readl(pspi, ctrl0);
-
-	ctrlr0 &= 0xfcc0;
-	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
-		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
-	dw_writel(pspi, ctrl0, ctrlr0);
-
-	/*
-	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
-	 * calculate the clk dividor to make the clock a little slower
-	 * than real baud rate.
-	 */
-	dw_writel(pspi, baudr, freq/100000);
-
-	/* Disable all INT for early phase */
-	dw_writel(pspi, imr, 0x0);
-
-	/* Set the cs to spi-uart */
-	dw_writel(pspi, ser, 0x2);
-
-	/* Enable the HW, the last step for HW init */
-	dw_writel(pspi, ssienr, 0x1);
-
-	/* Set the default configuration */
-	max3110_write_config();
+		spi_paddr = MRST_REGBASE_SPI1;
+	mid_spi_early_console_init(spi_paddr);
 
 	/* Register the kmsg dumper */
 	if (!dumper_registered) {
@@ -196,48 +66,6 @@
 	}
 }
 
-/* Slave select should be called in the read/write function */
-static void early_mrst_spi_putc(char c)
-{
-	unsigned int timeout;
-	u32 sr;
-
-	timeout = MRST_SPI_TIMEOUT;
-	/* Early putc needs to make sure the TX FIFO is not full */
-	while (--timeout) {
-		sr = dw_readl(pspi, sr);
-		if (!(sr & SR_TF_NOT_FULL))
-			cpu_relax();
-		else
-			break;
-	}
-
-	if (!timeout)
-		pr_warning("MRST earlycon: timed out\n");
-	else
-		max3110_write_data(c);
-}
-
-/* Early SPI only uses polling mode */
-static void early_mrst_spi_write(struct console *con, const char *str, unsigned n)
-{
-	int i;
-
-	for (i = 0; i < n && *str; i++) {
-		if (*str == '\n')
-			early_mrst_spi_putc('\r');
-		early_mrst_spi_putc(*str);
-		str++;
-	}
-}
-
-struct console early_mrst_console = {
-	.name =		"earlymrst",
-	.write =	early_mrst_spi_write,
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
-};
-
 /*
  * Following is the early console based on Medfield HSU (High
  * Speed UART) device.
Index: linux-acpi/drivers/platform/x86/Makefile
===================================================================
--- linux-acpi.orig/drivers/platform/x86/Makefile	2012-09-27 22:35:05.000000000 +0800
+++ linux-acpi/drivers/platform/x86/Makefile	2012-09-27 22:35:14.000000000 +0800
@@ -50,3 +50,5 @@
 obj-$(CONFIG_INTEL_OAKTRAIL)	+= intel_oaktrail.o
 obj-$(CONFIG_SAMSUNG_Q10)	+= samsung-q10.o
 obj-$(CONFIG_APPLE_GMUX)	+= apple-gmux.o
+
+obj-$(CONFIG_EARLY_PRINTK)	+= early/
Index: linux-acpi/drivers/platform/x86/early/Makefile
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-acpi/drivers/platform/x86/early/Makefile	2012-09-27 22:35:14.000000000 +0800
@@ -0,0 +1,5 @@
+#
+# Makefile for linux/drivers/platform/x86/early
+# x86 Platform-Specific Early Printk Support
+#
+obj-$(CONFIG_EARLY_PRINTK_INTEL_MID_SPI)	+= intel_mid_spi.o
Index: linux-acpi/drivers/platform/x86/early/intel_mid_spi.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-acpi/drivers/platform/x86/early/intel_mid_spi.c	2012-09-27 22:35:14.000000000 +0800
@@ -0,0 +1,220 @@
+/*
+ * intel_mid_spi.c - SPI UART early consoles for Intel MID platforms
+ *
+ * Copyright (c) 2008-2012, 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 the Free Software Foundation; version 2
+ * of the License.
+ */
+
+/*
+ * This file implements early console named intel_pmic.
+ * intel_pmic is based on Maxim3110 spi-uart device, it exists in
+ * Low Power Intel Architecture (LPIA) platforms.
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/serial_mfd.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/intel_mid_early.h>
+#include <asm/fixmap.h>
+
+#define DW_SPI_TIMEOUT			0x200000
+#define DW_SPI0_CLK_REG			0xff11d86c
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET			0
+
+#define SPI_FRF_OFFSET			4
+#define SPI_FRF_SPI			0x0
+#define SPI_FRF_SSP			0x1
+#define SPI_FRF_MICROWIRE		0x2
+#define SPI_FRF_RESV			0x3
+
+#define SPI_MODE_OFFSET			6
+#define SPI_SCPH_OFFSET			6
+#define SPI_SCOL_OFFSET			7
+#define SPI_TMOD_OFFSET			8
+#define	SPI_TMOD_TR			0x0		/* xmit & recv */
+#define SPI_TMOD_TO			0x1		/* xmit only */
+#define SPI_TMOD_RO			0x2		/* recv only */
+#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET		10
+#define SPI_SRL_OFFSET			11
+#define SPI_CFS_OFFSET			12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK				0x7f		/* cover 7 bits */
+#define SR_BUSY				(1 << 0)
+#define SR_TF_NOT_FULL			(1 << 1)
+#define SR_TF_EMPT			(1 << 2)
+#define SR_RF_NOT_EMPT			(1 << 3)
+#define SR_RF_FULL			(1 << 4)
+#define SR_TX_ERR			(1 << 5)
+#define SR_DCOL				(1 << 6)
+
+struct dw_spi_reg {
+	u32	ctrl0;
+	u32	ctrl1;
+	u32	ssienr;
+	u32	mwcr;
+	u32	ser;
+	u32	baudr;
+	u32	txfltr;
+	u32	rxfltr;
+	u32	txflr;
+	u32	rxflr;
+	u32	sr;
+	u32	imr;
+	u32	isr;
+	u32	risr;
+	u32	txoicr;
+	u32	rxoicr;
+	u32	rxuicr;
+	u32	msticr;
+	u32	icr;
+	u32	dmacr;
+	u32	dmatdlr;
+	u32	dmardlr;
+	u32	idr;
+	u32	version;
+
+	/* Currently operates as 32 bits, though only the low 16 bits matter */
+	u32	dr;
+} __packed;
+
+#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
+#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
+
+static u32 *pclk_spi0;
+/* Always contains an accessible address, start with 0 */
+static struct dw_spi_reg *pspi;
+static int dw_spi_initialized;
+static u32 dw_spi_regbase;
+
+/* Translate char to a eligible word and send to max3110 */
+static void max3110_write_data(char c)
+{
+	u16 data;
+
+	data = 0x8000 | c;
+	dw_writel(pspi, dr, data);
+}
+
+/* Set the ratio rate to 115200, 8n1, IRQ disabled */
+static void max3110_write_config(void)
+{
+	u16 config;
+
+	config = 0xc001;
+	dw_writel(pspi, dr, config);
+}
+
+int mid_spi_early_console_reset(void)
+{
+	u32 ctrlr0 = 0;
+	u32 spi0_cdiv;
+	u32 freq; /* Freqency info only need be searched once */
+
+	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
+	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+						      DW_SPI0_CLK_REG);
+	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
+	freq = 100000000 / (spi0_cdiv + 1);
+
+	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+						 dw_spi_regbase);
+
+	/* Disable SPI controller */
+	dw_writel(pspi, ssienr, 0);
+
+	/* Set control param, 8 bits, transmit only mode */
+	ctrlr0 = dw_readl(pspi, ctrl0);
+
+	ctrlr0 &= 0xfcc0;
+	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
+		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
+	dw_writel(pspi, ctrl0, ctrlr0);
+
+	/*
+	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
+	 * calculate the clk dividor to make the clock a little slower
+	 * than real baud rate.
+	 */
+	dw_writel(pspi, baudr, freq/100000);
+
+	/* Disable all INT for early phase */
+	dw_writel(pspi, imr, 0x0);
+
+	/* Set the cs to spi-uart */
+	dw_writel(pspi, ser, 0x2);
+
+	/* Enable the HW, the last step for HW init */
+	dw_writel(pspi, ssienr, 0x1);
+
+	/* Set the default configuration */
+	max3110_write_config();
+
+	return 0;
+}
+EXPORT_SYMBOL(mid_spi_early_console_reset);
+
+/* Slave select should be called in the read/write function */
+static void dw_early_spi_putc(char c)
+{
+	unsigned int timeout;
+	u32 sr;
+
+	timeout = DW_SPI_TIMEOUT;
+	/* Early putc needs to make sure the TX FIFO is not full */
+	while (--timeout) {
+		sr = dw_readl(pspi, sr);
+		if (!(sr & SR_TF_NOT_FULL))
+			cpu_relax();
+		else
+			break;
+	}
+
+	if (!timeout)
+		pr_warn("mid-spi-early: timed out\n");
+	else
+		max3110_write_data(c);
+}
+
+/* Early SPI only uses polling mode */
+static void dw_early_spi_write(struct console *con,
+			       const char *str, unsigned n)
+{
+	int i;
+
+	for (i = 0; i < n && *str; i++) {
+		if (*str == '\n')
+			dw_early_spi_putc('\r');
+		dw_early_spi_putc(*str);
+		str++;
+	}
+}
+
+struct console mid_spi_early_console = {
+	.name =		"earlymidspi",
+	.write =	dw_early_spi_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
+void __init mid_spi_early_console_init(u32 spi_paddr)
+{
+	if (dw_spi_initialized)
+		return;
+	dw_spi_regbase = spi_paddr;
+	mid_spi_early_console_reset();
+	dw_spi_initialized = 1;
+}
+
Index: linux-acpi/include/acpi/actbl2.h
===================================================================
--- linux-acpi.orig/include/acpi/actbl2.h	2012-09-27 22:35:05.000000000 +0800
+++ linux-acpi/include/acpi/actbl2.h	2012-09-27 22:35:42.000000000 +0800
@@ -341,6 +341,7 @@
 
 #define ACPI_DBG2_16550_COMPATIBLE  0x0000
 #define ACPI_DBG2_16550_SUBSET      0x0001
+#define ACPI_DBG2_INTEL_MID_SPI     0x0002
 
 #define ACPI_DBG2_1394_STANDARD     0x0000
 
Index: linux-acpi/include/linux/intel_mid_early.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-acpi/include/linux/intel_mid_early.h	2012-09-27 22:35:14.000000000 +0800
@@ -0,0 +1,12 @@
+#ifndef LINUX_INTEL_MID_EARLY_H
+#define LINUX_INTEL_MID_EARLY_H
+
+#include <linux/console.h>
+
+extern struct console mid_spi_early_console;
+
+extern void mid_spi_early_console_init(u32 spi_paddr);
+extern int mid_spi_early_console_reset(void);
+
+#endif /* LINUX_INTEL_MID_EARLY_H */
+
Index: linux-acpi/Documentation/kernel-parameters.txt
===================================================================
--- linux-acpi.orig/Documentation/kernel-parameters.txt	2012-09-27 22:35:13.000000000 +0800
+++ linux-acpi/Documentation/kernel-parameters.txt	2012-09-27 22:35:14.000000000 +0800
@@ -762,6 +762,7 @@
 			earlyprintk=vga
 			earlyprintk=serial[,ttySn[,baudrate]]
 			earlyprintk=ttySn[,baudrate]
+			earlyprintk=mrst
 			earlyprintk=dbgp[debugController#]
 			earlyprintk=acpi[debugController#]
 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA.
  2012-09-28  2:39 ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Lv Zheng
  2012-09-28  2:40   ` [PATCH v4 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
  2012-09-28  2:40   ` [PATCH v4 2/2] ACPI: Add Intel MID SPI early console support Lv Zheng
@ 2012-09-28  5:24   ` Zheng, Lv
  2012-09-28  6:36   ` [RESEND PATCH " H. Peter Anvin
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 26+ messages in thread
From: Zheng, Lv @ 2012-09-28  5:24 UTC (permalink / raw)
  To: Brown, Len; +Cc: linux-kernel, linux-acpi

Forgot to Cc x86 maintainers, will send again. Sorry for the noise.

> -----Original Message-----
> From: Zheng, Lv
> Sent: Friday, September 28, 2012 10:40 AM
> To: Brown, Len
> Cc: linux-kernel@vger.kernel.org; linux-acpi@vger.kernel.org; Zheng, Lv
> Subject: [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA.
> 
> Microsoft Debug Port Table (DBGP or DBG2) is used by the Windows SoC
> platforms to describe their debugging facilities.
> Recent Low Power Intel Architecture (LPIA) platforms have utilized
> this for the SPI UART debug ports that are resident on their debug
> boards.
> 
> This patch set enables the DBGP/DBG2 debug ports as an Linux early
> console launcher.
> The SPI UART debug ports support is also refined to co-exist with this
> new usage model.
> 
> To use this facility on LPIA platforms, you need to enable the following
> kernel configurations:
>   CONFIG_EARLY_PRINTK_ACPI=y
>   CONFIG_EARLY_PRINTK_INTEL_MID_SPI=y
> Then you need to append the following kernel parameter to the kernel
> command line in your the boot loader configuration file:
>   earlyprintk=acpi
> 
> There is a dilemma in designing this patch set.  There should be three
> steps to enable an early console for an operating system:
> 1. Probe: In this stage, the Linux kernel can detect the early consoles
>           and the base address of their register block can be determined.
>           This can be done by parsing the descriptors in the ACPI
> DBGP/DBG2
>           tables.  Note that acpi_table_init() must be called before
>           parsing.
> 2. Setup: In this stage, the Linux kernel can apply user specified
>           configuration options (ex. baudrate of serial ports) for the
>           early consoles.  This is done by parsing the early parameters
>           passed to the kernel from the boot loaders.  Note that
>           parse_early_params() is called very early to allow parameters to
>           be passed to other kernel subsystems.
> 3. Start: In this stage, the Linux kernel can make the console available
>           to output messages.  Since early consoles are always used for
>           kernel boot up debugging, this must be done as early as possible
>           to arm the kernel with more testability the kernel subsystems.
>           Note that, this stage happens when the register_console() is
>           called.
> The preferred sequence for the above steps is:
>    +-----------------+    +-------------------+    +--------------------+
>    | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK
> START |
>    +-----------------+    +-------------------+    +--------------------+
> But unfortunately, in the current x86 implementation, early parameters and
> early printk initialization are called before acpi_table_init() which
> requires early memory mapping facility.
> There are some choices for me to design this patch set:
> 1. Invoking acpi_table_init() before parse_early_param() to maintain the
>    sequence:
>    +-----------------+    +-------------------+    +--------------------+
>    | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK
> START |
>    +-----------------+    +-------------------+    +--------------------+
>    This requires other subsystem maintainers' review to ensure no
>    regressions will be introduced.  As far as I know, one kind of issue
>    might be found in EFI subsystsm:
>    The EFI boot services and runtime services are mixed up in the x86
>    specific initialization process before the ACPI table initialization.
>    Things are much worse that you even cannot disable the runtime services
>    while still allow the boot services codes to be executed in the kernel
>    compilation stage.  Enabling the early consoles after the ACPI table
>    initialization will make it difficult to debug the runtime BIOS bugs.
>    If any progress is made to the kernel boot sequences, please let me
>    know.  I'll be willing to redesign the ACPI DBGP/DBG2 console probing
>    facility.  You can reach me at <zetalog@gmail.com>.
> 2. Modifying above sequece to make it look like:
>    +-------------------+    +-----------------+    +--------------------+
>    | EARLY_PARAM SETUP | -> | ACPI DBGP PROBE | -> | EARLY_RPINTK
> START |
>    +-------------------+    +-----------------+    +--------------------+
>    Early consoles started in this style will lose some debuggabilities in
>    the kernel boot up.  If the system does not crash very early,
>    developers still can see the bufferred kernel outputs when the
>    register_console() is called.
>    Current early console implementation need to be modified to split their
>    initialization codes into tow part:
>    1. Detecting hardware.  This can be called in the PROBE stage.
>    2. Applying user parameters.  This can be called in the SETUP stage.
>    Individual early console drver maintainers need to be involved to avoid
>    regressions that might occur on this modification as the maintainers
>    might offer the real tests rather than I can do.
> 3. Introducing a barely new debugging facility that does not relate to the
>    current early console implementation to allow automatic detection for
>    the early consoles.
>    +-------------------+    +--------------------+
>    | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
>    +-------------------+    +--------------------+
>    +-----------------+    +--------------------+
>    | ACPI DBGP PROBE | -> | EARLY_RPINTK START |
>    +-----------------+    +--------------------+
>    This is what the patch set has done to enable this new usage model.
>    It is known as "ACPI early console launcher mode".
>    Early consoles started in this style will lose some debuggabilities in
>    the kernel boot up.  If the system does not crash very early,
>    developers still can see the bufferred kernel outputs when the
>    register_console() is called.
>    Note that the user configuration can not be applied to the registered
>    early consoles in this way as the acpi_table_init() is still called
>    after the parse_early_param().  Instead, the early consoles should
>    derive the hardware settings used in the BIOS/bootloaders.
>    As a launcher, ACPI DBGP will not actually output kernel messages
>    without the real early console drivers, that's why the
>    CONFIG_EARLY_PRINTK_INTEL_MID_SPI is still need to be enabled along
>    along with the CONFIG_EARLY_PRINTK_ACPI.
>    In order to disable this facility by default and enable it at runtime,
>    an kernel parameter "earlyprintk=acpi" is introduced.  This makes the
>    actual sequence looks like:
>    +-------------------+    +--------------------+
>    | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
>    +-------------------+    +....................+    +-----------------+
>                             | ACPI DBGP LAUNCH   | -> | ACPI DBGP
> PROBE | ->
>                             +--------------------+    +-----------------+
>       +--------------------+
>    -> | EARLY_RPINTK START |
>       +--------------------+
> 
> Version 3 of this patch set is the first version that will be published
> in the Linux community.  Earlier versions are reviewed internally in
> Intel.  This patch set keeps the version number to track the history
> that is known to Intel internal developers.
> Version 4 of this patch set fixed bunch of CodingStyle issues.
> 
> Lv Zheng (2):
>   ACPI: Add early console framework for DBGP/DBG2.
>   ACPI: Add Intel MID SPI early console support.
> 
>  Documentation/kernel-parameters.txt        |    2 +
>  arch/x86/Kconfig.debug                     |   38 +++++
>  arch/x86/include/asm/mrst.h                |    2 +-
>  arch/x86/kernel/acpi/boot.c                |    1 +
>  arch/x86/kernel/early_printk.c             |   25 +++-
>  arch/x86/platform/mrst/early_printk_mrst.c |  186 +----------------------
>  drivers/acpi/Makefile                      |    2 +
>  drivers/acpi/early_printk.c                |  201
> +++++++++++++++++++++++++
>  drivers/platform/x86/Makefile              |    2 +
>  drivers/platform/x86/early/Makefile        |    5 +
>  drivers/platform/x86/early/intel_mid_spi.c |  220
> ++++++++++++++++++++++++++++
>  include/acpi/actbl2.h                      |    1 +
>  include/linux/acpi.h                       |   24 +++
>  include/linux/intel_mid_early.h            |   12 ++
>  14 files changed, 540 insertions(+), 181 deletions(-)
>  create mode 100644 drivers/acpi/early_printk.c
>  create mode 100644 drivers/platform/x86/early/Makefile
>  create mode 100644 drivers/platform/x86/early/intel_mid_spi.c
>  create mode 100644 include/linux/intel_mid_early.h
> 
> --
> 1.7.10


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [RESEND PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA.
  2012-09-28  2:39 ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Lv Zheng
                     ` (2 preceding siblings ...)
  2012-09-28  5:24   ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Zheng, Lv
@ 2012-09-28  6:36   ` H. Peter Anvin
  2012-10-06 18:42     ` Len Brown
  2012-10-10  3:23   ` [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
  2012-10-10  3:23   ` [PATCH v6 2/2] ACPI: Add Intel MID SPI early console support Lv Zheng
  5 siblings, 1 reply; 26+ messages in thread
From: H. Peter Anvin @ 2012-09-28  6:36 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Len Brown, Thomas Gleixner, Ingo Molnar, Jason Wessel, Feng Tang,
	linux-kernel, linux-acpi, x86, platform-driver-x86

On 09/27/2012 10:36 PM, Lv Zheng wrote:
> Microsoft Debug Port Table (DBGP or DBG2) is used by the Windows SoC
> platforms to describe their debugging facilities.
> Recent Low Power Intel Architecture (LPIA) platforms have utilized
> this for the SPI UART debug ports that are resident on their debug
> boards.
>
> This patch set enables the DBGP/DBG2 debug ports as an Linux early
> console launcher.
> The SPI UART debug ports support is also refined to co-exist with this
> new usage model.

Hi Len,

You want to take this, or should I?

	-hpa

-- 
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [RESEND PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA.
  2012-09-28  6:36   ` [RESEND PATCH " H. Peter Anvin
@ 2012-10-06 18:42     ` Len Brown
  2012-10-07 15:41       ` H. Peter Anvin
  2012-10-08  0:51       ` Zheng, Lv
  0 siblings, 2 replies; 26+ messages in thread
From: Len Brown @ 2012-10-06 18:42 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Lv Zheng, Thomas Gleixner, Ingo Molnar, Jason Wessel, Feng Tang,
	linux-kernel, linux-acpi, x86, platform-driver-x86


> You want to take this, or should I?

go ahead and take the series in tip 3.8, Peter, thanks.

I looked over this series a while back and my feedback was that
it should be disabled by default and enabled by bootparam --
like other earlyprink -- else an issue here would render
a system un-bootable.  I see that LV has addressed that
in the latest version.

LV,
have you addressed the feedback from Konrad?

thanks,
-Len



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [RESEND PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA.
  2012-10-06 18:42     ` Len Brown
@ 2012-10-07 15:41       ` H. Peter Anvin
  2012-10-08  0:51       ` Zheng, Lv
  1 sibling, 0 replies; 26+ messages in thread
From: H. Peter Anvin @ 2012-10-07 15:41 UTC (permalink / raw)
  To: Len Brown
  Cc: Lv Zheng, Thomas Gleixner, Ingo Molnar, Jason Wessel, Feng Tang,
	linux-kernel, linux-acpi, x86, platform-driver-x86

On 10/07/2012 02:42 AM, Len Brown wrote:
> 
>> You want to take this, or should I?
> 
> go ahead and take the series in tip 3.8, Peter, thanks.
> 

I'll pull it in after the merge window closes and I get back home.

	-hpa


^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [RESEND PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA.
  2012-10-06 18:42     ` Len Brown
  2012-10-07 15:41       ` H. Peter Anvin
@ 2012-10-08  0:51       ` Zheng, Lv
  1 sibling, 0 replies; 26+ messages in thread
From: Zheng, Lv @ 2012-10-08  0:51 UTC (permalink / raw)
  To: Len Brown, H. Peter Anvin
  Cc: Thomas Gleixner, Ingo Molnar, Jason Wessel, Tang, Feng,
	linux-kernel, linux-acpi, x86, platform-driver-x86

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 689 bytes --]

> go ahead and take the series in tip 3.8, Peter, thanks.
> 
> I looked over this series a while back and my feedback was that it should be
> disabled by default and enabled by bootparam -- like other earlyprink -- else an
> issue here would render a system un-bootable.  I see that LV has addressed
> that in the latest version.
> LV,
> have you addressed the feedback from Konrad?

I missed the mail from Konrad. Thanks for your reminder.
I'll find it and update my patches according to his suggestion.

Best regards/Lv Zheng

ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH v5 1/2] ACPI: Add early console framework for DBGP/DBG2.
       [not found] <cover.1347453194.git.zetalog@gmail.com>
  2012-09-28  2:39 ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Lv Zheng
@ 2012-10-09  2:36 ` Lv Zheng
  2012-10-09 17:02   ` Konrad Rzeszutek Wilk
  2012-10-09  2:37 ` [PATCH v5 2/2] ACPI: Add Intel MID SPI early console support Lv Zheng
  2 siblings, 1 reply; 26+ messages in thread
From: Lv Zheng @ 2012-10-09  2:36 UTC (permalink / raw)
  To: Len Brown, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Feng Tang
  Cc: linux-kernel, linux-acpi, x86, platform-driver-x86, Lv Zheng

Microsoft Debug Port Table (DBGP or DBG2) is used by the Windows SoC
platforms to describe their debugging facilities.
DBGP: http://msdn.microsoft.com/en-us/windows/hardware/hh134821
DBG2: http://msdn.microsoft.com/en-us/library/windows/hardware/hh673515

This patch enables the DBGP/DBG2 debug ports as Linux early console
launcher.  Individual early console drivers are also needed to get the
early kernel messages dumped on the consoles.  For example, to use the
SPI UART early console for the Low Power Intel Architecture (LPIA)
platforms, you need to enable the following kernel configurations:
  CONFIG_EARLY_PRINTK_ACPI=y
  CONFIG_EARLY_PRINTK_INTEL_MID_SPI=y
Then you need to append the following kernel parameter to the kernel
command line in your the boot loader configuration file:
  earlyprintk=acpi

There is a dilemma in designing this patch set.  Let me describe it in
details.
There should be three steps to enable an early console for an operating
system:
1. Probe: In this stage, the Linux kernel can detect the early consoles
          and the base address of their register block can be determined.
          This can be done by parsing the descriptors in the ACPI DBGP/DBG2
          tables.  Note that acpi_table_init() must be called before
          parsing.
2. Setup: In this stage, the Linux kernel can apply user specified
          configuration options (ex. baudrate of serial ports) for the
          early consoles.  This is done by parsing the early parameters
          passed to the kernel from the boot loaders.  Note that
          parse_early_params() is called very early to allow parameters to
          be passed to other kernel subsystems.
3. Start: In this stage, the Linux kernel can make the consoles ready to
          output logs.  Since the early consoles are always used for the
          kernel boot up debugging, this must be done as early as possible
          to arm the kernel with the highest testability for other kernel
          subsystems.  Note that, this stage happens when the
          register_console() is called.
The preferred sequence for the above steps is:
   +-----------------+    +-------------------+    +--------------------+
   | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-----------------+    +-------------------+    +--------------------+
But unfortunately, in the current x86 implementation, early parameters and
early printk initialization are called before acpi_table_init() which
depends on the early memory mapping facility.
There are some choices for me to design this patch set:
1. Invoking acpi_table_init() before parse_early_param() to maintain the
   sequence:
   +-----------------+    +-------------------+    +--------------------+
   | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-----------------+    +-------------------+    +--------------------+
   This requires other subsystem maintainers' review to ensure no
   regressions will be introduced.  At the first glance, I found there
   might be problems for the EFI subsystsm:
   The EFI boot services and runtime services are mixed up in the x86
   specific initialization process before the ACPI table initialization.
   Things are much worse that you even cannot disable the runtime services
   while still allow the boot services codes to be executed in the kernel
   compilation stage.  Enabling the early consoles after the ACPI table
   initialization will make it difficult to debug the runtime BIOS bugs.
   If any progress is made to the kernel boot sequences, please let me
   know.  I'll be willing to redesign the ACPI DBGP/DBG2 console probing
   facility.  You can reach me at <lv.zheng@intel.com> and
   <zetalog@gmail.com>.
2. Modifying the above sequece to make it look like:
   +-------------------+    +-----------------+    +--------------------+
   | EARLY_PARAM SETUP | -> | ACPI DBGP PROBE | -> | EARLY_RPINTK START |
   +-------------------+    +-----------------+    +--------------------+
   Early consoles started in this style will lose part of the testability
   in the kernel boot up sequence.  If the system does not crash very
   early, developers still can see the bufferred kernel outputs when the
   register_console() is called.
   Current early console implementations need to be modified to be
   compatible with this design.  The original codes need to be split up
   into tow parts:
   1. Detecting hardware.  This part can be called in the PROBE stage.
   2. Applying user parameters.  This part can be called in the SETUP
      stage.
   Individual early console drver maintainers need to be involved to avoid
   regressions that might occur if we do things in this way.  And the
   maintainers can offer better tests than I can do.
3. Introducing a brand new debugging facility that does not relate to the
   current early console implementation to allow the early consoles to be
   automatically detected.
   +-------------------+    +--------------------+
   | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-------------------+    +--------------------+
   +-----------------+    +--------------------+
   | ACPI DBGP PROBE | -> | EARLY_RPINTK START |
   +-----------------+    +--------------------+
   Early consoles started in this style will lose part of the testability
   in the kernel boot up sequence.  If the system does not crash very
   early, developers still can see the bufferred kernel outputs when the
   register_console() is called.
   Comparing to the solution 2, we can notice that the user configuration
   can not be applied to the registered early consoles in this way as the
   acpi_table_init() is still called after the parse_early_param().
   Instead, the early consoles should derive the hardware settings used in
   the BIOS/bootloaders.
   This is what the patch set has done to enable this new usage model.
   It is known as "ACPI early console launcher mode".
   As a launcher, ACPI DBGP will not actually output kernel messages
   without the real early console drivers, that's why the
   CONFIG_EARLY_PRINTK_INTEL_MID_SPI still need to be enabled along with
   the CONFIG_EARLY_PRINTK_ACPI.
   In order to disable this facility by default and enable it at runtime,
   an kernel parameter "earlyprintk=acpi" is introduced.  This makes the
   actual sequence look like:
   +-------------------+    +--------------------+
   | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-------------------+    +....................+
                            | ACPI DBGP LAUNCH   | ->
                            +--------------------+
      +-----------------+    +--------------------+
   -> | ACPI DBGP PROBE | -> | EARLY_PRINTK START |
      +-----------------+    +--------------------+

Version 1:
 1. Enables single DBG2 debug port support.
Version 2:
 1. Applies Rui's comments.
Version 3:
 1. Applies Len's comments (earlycon should be disabled by default).
 2. Enables single DBG2 debug ports support.
Version 4:
 1. Fixes the CodingStyle issues reported by checkpatch.pl.
 2. Enables single DBGP debug port support.
Version 5:
 1. Enables multiple DBG2 debug ports support.
 2. Applies Konrad's comments (pr_debug should be used in earlycon).
 3. Changes kstrtoul back to simple_strtoul.

Known Issues:
1. The simple_strtoul function cannot be replaced by the kstrtoul in
   the x86 specific booting codes.  The kstrtoul will return error on
   strings like "acpi0,keep".  This will leave one CodingStyle issue
   reported by the checkpatch.pl.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Reviewed-by: Len Brown <len.brown@intel.com>
Reviewed-by: Rui Zhang <rui.zhang@intel.com>
Reviewed-by: Ying Huang <ying.huang@intel.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad@kernel.org>
---
 Documentation/kernel-parameters.txt |    1 +
 arch/x86/Kconfig.debug              |   15 +++
 arch/x86/kernel/acpi/boot.c         |    1 +
 arch/x86/kernel/early_printk.c      |   13 +++
 drivers/acpi/Makefile               |    2 +
 drivers/acpi/early_printk.c         |  173 +++++++++++++++++++++++++++++++++++
 include/linux/acpi.h                |   22 +++++
 7 files changed, 227 insertions(+)
 create mode 100644 drivers/acpi/early_printk.c

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index ad7e2e5..f656765 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -763,6 +763,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			earlyprintk=serial[,ttySn[,baudrate]]
 			earlyprintk=ttySn[,baudrate]
 			earlyprintk=dbgp[debugController#]
+			earlyprintk=acpi[debugController#]
 
 			Append ",keep" to not disable it when the real console
 			takes over.
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index b322f12..5778082 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -59,6 +59,21 @@ config EARLY_PRINTK_DBGP
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash. You need usb debug device.
 
+config EARLY_PRINTK_ACPI
+	bool "Early printk launcher via ACPI debug port tables"
+	depends on EARLY_PRINTK && ACPI
+	---help---
+	  Write kernel log output directly into the debug ports described
+	  in the ACPI tables known as DBGP and DBG2.
+
+	  To enable such debugging facilities, you need to enable this
+	  configuration option and append the "earlyprintk=acpi" kernel
+	  parameter through the boot loaders.  Please refer the
+	  "Documentation/kernel-parameters.txt" for details.  Since this
+	  is an early console launcher, you still need to enable actual
+	  early console drivers that are suitable for your platform.
+	  If in doubt, say "N".
+
 config DEBUG_STACKOVERFLOW
 	bool "Check for stack overflows"
 	depends on DEBUG_KERNEL
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index b2297e5..cc10ea5 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1518,6 +1518,7 @@ void __init acpi_boot_table_init(void)
 		return;
 	}
 
+	acpi_early_console_probe();
 	acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
 
 	/*
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 9b9f18b..bf5b596 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -200,6 +200,15 @@ static inline void early_console_register(struct console *con, int keep_early)
 	register_console(early_console);
 }
 
+#ifdef CONFIG_EARLY_PRINTK_ACPI
+#include <linux/acpi.h>
+
+int __init __acpi_early_console_start(struct acpi_debug_port *info)
+{
+	return 0;
+}
+#endif
+
 static int __init setup_early_printk(char *buf)
 {
 	int keep;
@@ -236,6 +245,10 @@ static int __init setup_early_printk(char *buf)
 		if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4))
 			early_console_register(&early_dbgp_console, keep);
 #endif
+#ifdef CONFIG_EARLY_PRINTK_ACPI
+		if (!strncmp(buf, "acpi", 4))
+			acpi_early_console_launch(buf + 4, keep);
+#endif
 #ifdef CONFIG_HVC_XEN
 		if (!strncmp(buf, "xen", 3))
 			early_console_register(&xenboot_console, keep);
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 47199e2..99dbd64 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -46,6 +46,8 @@ ifdef CONFIG_ACPI_VIDEO
 acpi-y				+= video_detect.o
 endif
 
+obj-$(CONFIG_EARLY_PRINTK_ACPI)	+= early_printk.o
+
 # These are (potentially) separate modules
 obj-$(CONFIG_ACPI_AC) 		+= ac.o
 obj-$(CONFIG_ACPI_BUTTON)	+= button.o
diff --git a/drivers/acpi/early_printk.c b/drivers/acpi/early_printk.c
new file mode 100644
index 0000000..3e5c1f3
--- /dev/null
+++ b/drivers/acpi/early_printk.c
@@ -0,0 +1,173 @@
+/*
+ * acpi/early_printk.c - ACPI Boot-Time Debug Ports
+ *
+ * Copyright (c) 2012, Intel Corporation
+ * Author: Lv Zheng <lv.zheng@intel.com>
+ *
+ * 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 the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#define DEBUG
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/acpi.h>
+#include <linux/bitmap.h>
+#include <linux/bootmem.h>
+
+#define MAX_ACPI_DBG_PORTS	16
+
+DECLARE_BITMAP(acpi_early_flags, MAX_ACPI_DBG_PORTS);
+int acpi_early_enabled;
+
+static int acpi_early_console_enable(u8 port, int keep)
+{
+	if (port >= MAX_ACPI_DBG_PORTS)
+		return -ENODEV;
+
+	set_bit(port, acpi_early_flags);
+	if (keep)
+		set_bit(port+MAX_ACPI_DBG_PORTS, acpi_early_flags);
+	acpi_early_enabled = 1;
+
+	pr_debug("early: DBGx LAUNCH - console %d.\n", port);
+
+	return 0;
+}
+
+static inline bool acpi_early_console_enabled(u8 port)
+{
+	BUG_ON(port >= MAX_ACPI_DBG_PORTS);
+	return test_bit(port, acpi_early_flags);
+}
+
+int __init acpi_early_console_keep(struct acpi_debug_port *info)
+{
+	BUG_ON(!info || info->port_index >= MAX_ACPI_DBG_PORTS);
+	return test_bit(info->port_index+MAX_ACPI_DBG_PORTS, acpi_early_flags);
+}
+
+static int __init acpi_early_console_start(struct acpi_debug_port *info)
+{
+	if (!acpi_early_console_enabled(info->port_index))
+		return 0;
+
+	pr_debug("early: DBGx START - console %d(%04x:%04x).\n",
+		 info->port_index, info->port_type, info->port_subtype);
+	__acpi_early_console_start(info);
+
+	return 0;
+}
+
+static int __init acpi_parse_dbg2(struct acpi_table_header *table)
+{
+	struct acpi_table_dbg2 *dbg2;
+	struct acpi_dbg2_device *entry;
+	unsigned int count = 0;
+	unsigned long tbl_end;
+	unsigned int max_entries;
+	struct acpi_debug_port devinfo;
+
+	dbg2 = (struct acpi_table_dbg2 *)table;
+	if (!dbg2) {
+		pr_debug("early: DBG2 not present.\n");
+		return -ENODEV;
+	}
+
+	tbl_end = (unsigned long)table + table->length;
+
+	entry = (struct acpi_dbg2_device *)
+		((unsigned long)dbg2 + dbg2->info_offset);
+	max_entries = min_t(u32, MAX_ACPI_DBG_PORTS, dbg2->info_count);
+
+	while (((unsigned long)entry) + sizeof(struct acpi_dbg2_device) <
+	       tbl_end) {
+		if (entry->revision != 0) {
+			pr_debug("early: DBG2 revision %d not supported.\n",
+				 entry->revision);
+			return -ENODEV;
+		}
+		if (!max_entries || count++ < max_entries) {
+			pr_debug("early: DBG2 PROBE - console %d(%04x:%04x).\n",
+				 count-1,
+				 entry->port_type, entry->port_subtype);
+
+			devinfo.port_index = (u8)count-1;
+			devinfo.port_type = entry->port_type;
+			devinfo.port_subtype = entry->port_subtype;
+			devinfo.register_count = entry->register_count;
+			devinfo.registers = (struct acpi_generic_address *)
+			    ((unsigned long)entry + entry->base_address_offset);
+			devinfo.namepath_length = entry->namepath_length;
+			devinfo.namepath = (char *)
+			    ((unsigned long)entry + entry->namepath_offset);
+			devinfo.oem_data_length = entry->oem_data_length;
+			devinfo.oem_data = (u8 *)
+			    ((unsigned long)entry + entry->oem_data_offset);
+
+			acpi_early_console_start(&devinfo);
+		}
+
+		entry = (struct acpi_dbg2_device *)
+		    ((unsigned long)entry + entry->length);
+	}
+
+	return 0;
+}
+
+static int __init acpi_parse_dbgp(struct acpi_table_header *table)
+{
+	struct acpi_table_dbgp *dbgp;
+	struct acpi_debug_port devinfo;
+
+	dbgp = (struct acpi_table_dbgp *)table;
+	if (!dbgp) {
+		pr_debug("early: DBGP not present.\n");
+		return -ENODEV;
+	}
+
+	pr_debug("early: DBGP PROBE - console (%04x).\n", dbgp->type);
+
+	devinfo.port_index = 0;
+	devinfo.port_type = ACPI_DBG2_SERIAL_PORT;
+	devinfo.port_subtype = dbgp->type;
+	devinfo.register_count = 1;
+	devinfo.registers = (struct acpi_generic_address *)&dbgp->debug_port;
+	devinfo.namepath_length = 0;
+	devinfo.namepath = NULL;
+	devinfo.oem_data_length = 0;
+	devinfo.oem_data = NULL;
+
+	acpi_early_console_start(&devinfo);
+
+	return 0;
+}
+
+int __init acpi_early_console_probe(void)
+{
+	if (!acpi_early_enabled)
+		return -EINVAL;
+
+	if (acpi_table_parse(ACPI_SIG_DBG2, acpi_parse_dbg2) != 0)
+		acpi_table_parse(ACPI_SIG_DBGP, acpi_parse_dbgp);
+
+	return 0;
+}
+
+int __init acpi_early_console_launch(char *s, int keep)
+{
+	char *e;
+	unsigned long port = 0;
+
+	if (*s)
+		port = simple_strtoul(s, &e, 10);
+
+	return acpi_early_console_enable(port, keep);
+}
+
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 4f2a762..641366c 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -430,4 +430,26 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state,
 #define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
 #endif
 
+#ifdef CONFIG_EARLY_PRINTK_ACPI
+struct acpi_debug_port {
+	u8 port_index;
+	u16 port_type;
+	u16 port_subtype;
+	u16 register_count;
+	struct acpi_generic_address *registers;
+	u16 namepath_length;
+	char *namepath;
+	u16 oem_data_length;
+	u8 *oem_data;
+};
+
+int __init acpi_early_console_keep(struct acpi_debug_port *info);
+int __init acpi_early_console_launch(char *s, int keep);
+int __init acpi_early_console_probe(void);
+/* This interface is arch specific. */
+int __init __acpi_early_console_start(struct acpi_debug_port *info);
+#else
+static int acpi_early_console_probe(void) { return 0; }
+#endif
+
 #endif	/*_LINUX_ACPI_H*/
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v5 2/2] ACPI: Add Intel MID SPI early console support.
       [not found] <cover.1347453194.git.zetalog@gmail.com>
  2012-09-28  2:39 ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Lv Zheng
  2012-10-09  2:36 ` [PATCH v5 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
@ 2012-10-09  2:37 ` Lv Zheng
  2012-10-09 17:06   ` Konrad Rzeszutek Wilk
  2 siblings, 1 reply; 26+ messages in thread
From: Lv Zheng @ 2012-10-09  2:37 UTC (permalink / raw)
  To: Len Brown, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Feng Tang
  Cc: linux-kernel, linux-acpi, x86, platform-driver-x86, Lv Zheng

DesignWare SPI UART is used as one of the debug ports on Low Power Intel
Architecture (LPIA) platforms.  This patch is introduced to support this
debugging console reported by ACPI DBGP/DBG2.  The original MID SPI
early console stuff is also refined to co-exist with the new ACPI usage
model.

To use this facility on LPIA platforms, you need to enable the following
kernel configurations:
  CONFIG_EARLY_PRINTK_ACPI=y
  CONFIG_EARLY_PRINTK_INTEL_MID_SPI=y
Then you need to append the following kernel parameter to the kernel
command line in the boot loader configuration file:
  earlyprintk=acpi

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Reviewed-by: Feng Tang <feng.tang@intel.com>
---
 Documentation/kernel-parameters.txt        |    1 +
 arch/x86/Kconfig.debug                     |   23 +++
 arch/x86/include/asm/mrst.h                |    2 +-
 arch/x86/kernel/early_printk.c             |   12 +-
 arch/x86/platform/mrst/early_printk_mrst.c |  186 +----------------------
 drivers/platform/x86/Makefile              |    2 +
 drivers/platform/x86/early/Makefile        |    5 +
 drivers/platform/x86/early/intel_mid_spi.c |  220 ++++++++++++++++++++++++++++
 include/acpi/actbl2.h                      |    1 +
 include/linux/intel_mid_early.h            |   12 ++
 10 files changed, 283 insertions(+), 181 deletions(-)
 create mode 100644 drivers/platform/x86/early/Makefile
 create mode 100644 drivers/platform/x86/early/intel_mid_spi.c
 create mode 100644 include/linux/intel_mid_early.h

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f656765..003ffd9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -762,6 +762,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			earlyprintk=vga
 			earlyprintk=serial[,ttySn[,baudrate]]
 			earlyprintk=ttySn[,baudrate]
+			earlyprintk=mrst
 			earlyprintk=dbgp[debugController#]
 			earlyprintk=acpi[debugController#]
 
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 5778082..4a26e2d 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -43,9 +43,32 @@ config EARLY_PRINTK
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash.
 
+config EARLY_PRINTK_INTEL_MID_SPI
+	bool "Early printk for Intel MID SPI UART port"
+	depends on EARLY_PRINTK
+	---help---
+	  Write kernel log output directly into the MID SPI UART debug port.
+
+	  Intel MID platforms are using DesignWare SPI UART as its debug
+	  console.  This option does not introduce actual early console into
+	  the kernel binary, but is required by a real early console
+	  implementation (EARLY_PRINTK_INTEL_MID or EARLY_PRINTK_ACPI).
+	  You should normally N here unless you need to do kernel booting
+	  development.
+
 config EARLY_PRINTK_INTEL_MID
 	bool "Early printk for Intel MID platform support"
 	depends on EARLY_PRINTK && X86_INTEL_MID
+	select EARLY_PRINTK_INTEL_MID_SPI
+	---help---
+	  Write kernel log output directly into the MID SPI UART debug port.
+
+	  Intel MID platforms are always equipped with SPI debug ports and
+	  USB OTG debug ports. To enable these debugging facilities, you
+	  need to pass "earlyprintk=mrst" parameter to the kernel through
+	  boot loaders.  Please see "Documentation/kernel-parameter.txt" for
+	  details.  You should normally N here unless you need to do kernel
+	  booting development.
 
 config EARLY_PRINTK_DBGP
 	bool "Early printk via EHCI debug port"
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
index fc18bf3..8ab0655 100644
--- a/arch/x86/include/asm/mrst.h
+++ b/arch/x86/include/asm/mrst.h
@@ -12,6 +12,7 @@
 #define _ASM_X86_MRST_H
 
 #include <linux/sfi.h>
+#include <linux/intel_mid_early.h>
 
 extern int pci_mrst_init(void);
 extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
@@ -63,7 +64,6 @@ extern enum mrst_timer_options mrst_timer_options;
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX	8
 
-extern struct console early_mrst_console;
 extern void mrst_early_console_init(void);
 
 extern struct console early_hsu_console;
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index bf5b596..9b5ee96 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -205,6 +205,16 @@ static inline void early_console_register(struct console *con, int keep_early)
 
 int __init __acpi_early_console_start(struct acpi_debug_port *info)
 {
+#ifdef CONFIG_EARLY_PRINTK_INTEL_MID_SPI
+	if (info->port_type == ACPI_DBG2_SERIAL_PORT
+	    && info->port_subtype == ACPI_DBG2_INTEL_MID_SPI
+	    && info->register_count > 0) {
+		mid_spi_early_console_init((u32)(info->registers[0].address));
+		early_console_register(&mid_spi_early_console,
+				       acpi_early_console_keep(info));
+	}
+#endif
+
 	return 0;
 }
 #endif
@@ -256,7 +266,7 @@ static int __init setup_early_printk(char *buf)
 #ifdef CONFIG_EARLY_PRINTK_INTEL_MID
 		if (!strncmp(buf, "mrst", 4)) {
 			mrst_early_console_init();
-			early_console_register(&early_mrst_console, keep);
+			early_console_register(&mid_spi_early_console, keep);
 		}
 
 		if (!strncmp(buf, "hsu", 3)) {
diff --git a/arch/x86/platform/mrst/early_printk_mrst.c b/arch/x86/platform/mrst/early_printk_mrst.c
index 028454f..7afbf18 100644
--- a/arch/x86/platform/mrst/early_printk_mrst.c
+++ b/arch/x86/platform/mrst/early_printk_mrst.c
@@ -29,82 +29,8 @@
 #include <asm/pgtable.h>
 #include <asm/mrst.h>
 
-#define MRST_SPI_TIMEOUT		0x200000
 #define MRST_REGBASE_SPI0		0xff128000
 #define MRST_REGBASE_SPI1		0xff128400
-#define MRST_CLK_SPI0_REG		0xff11d86c
-
-/* Bit fields in CTRLR0 */
-#define SPI_DFS_OFFSET			0
-
-#define SPI_FRF_OFFSET			4
-#define SPI_FRF_SPI			0x0
-#define SPI_FRF_SSP			0x1
-#define SPI_FRF_MICROWIRE		0x2
-#define SPI_FRF_RESV			0x3
-
-#define SPI_MODE_OFFSET			6
-#define SPI_SCPH_OFFSET			6
-#define SPI_SCOL_OFFSET			7
-#define SPI_TMOD_OFFSET			8
-#define	SPI_TMOD_TR			0x0		/* xmit & recv */
-#define SPI_TMOD_TO			0x1		/* xmit only */
-#define SPI_TMOD_RO			0x2		/* recv only */
-#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
-
-#define SPI_SLVOE_OFFSET		10
-#define SPI_SRL_OFFSET			11
-#define SPI_CFS_OFFSET			12
-
-/* Bit fields in SR, 7 bits */
-#define SR_MASK				0x7f		/* cover 7 bits */
-#define SR_BUSY				(1 << 0)
-#define SR_TF_NOT_FULL			(1 << 1)
-#define SR_TF_EMPT			(1 << 2)
-#define SR_RF_NOT_EMPT			(1 << 3)
-#define SR_RF_FULL			(1 << 4)
-#define SR_TX_ERR			(1 << 5)
-#define SR_DCOL				(1 << 6)
-
-struct dw_spi_reg {
-	u32	ctrl0;
-	u32	ctrl1;
-	u32	ssienr;
-	u32	mwcr;
-	u32	ser;
-	u32	baudr;
-	u32	txfltr;
-	u32	rxfltr;
-	u32	txflr;
-	u32	rxflr;
-	u32	sr;
-	u32	imr;
-	u32	isr;
-	u32	risr;
-	u32	txoicr;
-	u32	rxoicr;
-	u32	rxuicr;
-	u32	msticr;
-	u32	icr;
-	u32	dmacr;
-	u32	dmatdlr;
-	u32	dmardlr;
-	u32	idr;
-	u32	version;
-
-	/* Currently operates as 32 bits, though only the low 16 bits matter */
-	u32	dr;
-} __packed;
-
-#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
-#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
-
-/* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */
-static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0;
-
-static u32 *pclk_spi0;
-/* Always contains an accessible address, start with 0 */
-static struct dw_spi_reg *pspi;
 
 static struct kmsg_dumper dw_dumper;
 static int dumper_registered;
@@ -116,77 +42,21 @@ static void dw_kmsg_dump(struct kmsg_dumper *dumper,
 	size_t len;
 
 	/* When run to this, we'd better re-init the HW */
-	mrst_early_console_init();
+	mid_spi_early_console_reset();
 
 	while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len))
-		early_mrst_console.write(&early_mrst_console, line, len);
-}
-
-/* Set the ratio rate to 115200, 8n1, IRQ disabled */
-static void max3110_write_config(void)
-{
-	u16 config;
-
-	config = 0xc001;
-	dw_writel(pspi, dr, config);
-}
-
-/* Translate char to a eligible word and send to max3110 */
-static void max3110_write_data(char c)
-{
-	u16 data;
-
-	data = 0x8000 | c;
-	dw_writel(pspi, dr, data);
+		mid_spi_early_console.write(&mid_spi_early_console, line, len);
 }
 
 void mrst_early_console_init(void)
 {
-	u32 ctrlr0 = 0;
-	u32 spi0_cdiv;
-	u32 freq; /* Freqency info only need be searched once */
-
-	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
-	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
-							MRST_CLK_SPI0_REG);
-	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
-	freq = 100000000 / (spi0_cdiv + 1);
+	/* Default use SPI0 register for mrst */
+	unsigned long spi_paddr = MRST_REGBASE_SPI0;
 
+	/* Detect Penwell and use SPI1 */
 	if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL)
-		mrst_spi_paddr = MRST_REGBASE_SPI1;
-
-	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
-						mrst_spi_paddr);
-
-	/* Disable SPI controller */
-	dw_writel(pspi, ssienr, 0);
-
-	/* Set control param, 8 bits, transmit only mode */
-	ctrlr0 = dw_readl(pspi, ctrl0);
-
-	ctrlr0 &= 0xfcc0;
-	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
-		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
-	dw_writel(pspi, ctrl0, ctrlr0);
-
-	/*
-	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
-	 * calculate the clk dividor to make the clock a little slower
-	 * than real baud rate.
-	 */
-	dw_writel(pspi, baudr, freq/100000);
-
-	/* Disable all INT for early phase */
-	dw_writel(pspi, imr, 0x0);
-
-	/* Set the cs to spi-uart */
-	dw_writel(pspi, ser, 0x2);
-
-	/* Enable the HW, the last step for HW init */
-	dw_writel(pspi, ssienr, 0x1);
-
-	/* Set the default configuration */
-	max3110_write_config();
+		spi_paddr = MRST_REGBASE_SPI1;
+	mid_spi_early_console_init(spi_paddr);
 
 	/* Register the kmsg dumper */
 	if (!dumper_registered) {
@@ -196,48 +66,6 @@ void mrst_early_console_init(void)
 	}
 }
 
-/* Slave select should be called in the read/write function */
-static void early_mrst_spi_putc(char c)
-{
-	unsigned int timeout;
-	u32 sr;
-
-	timeout = MRST_SPI_TIMEOUT;
-	/* Early putc needs to make sure the TX FIFO is not full */
-	while (--timeout) {
-		sr = dw_readl(pspi, sr);
-		if (!(sr & SR_TF_NOT_FULL))
-			cpu_relax();
-		else
-			break;
-	}
-
-	if (!timeout)
-		pr_warning("MRST earlycon: timed out\n");
-	else
-		max3110_write_data(c);
-}
-
-/* Early SPI only uses polling mode */
-static void early_mrst_spi_write(struct console *con, const char *str, unsigned n)
-{
-	int i;
-
-	for (i = 0; i < n && *str; i++) {
-		if (*str == '\n')
-			early_mrst_spi_putc('\r');
-		early_mrst_spi_putc(*str);
-		str++;
-	}
-}
-
-struct console early_mrst_console = {
-	.name =		"earlymrst",
-	.write =	early_mrst_spi_write,
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
-};
-
 /*
  * Following is the early console based on Medfield HSU (High
  * Speed UART) device.
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index bf7e4f9..6e4ff46 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -50,3 +50,5 @@ obj-$(CONFIG_INTEL_MID_POWER_BUTTON)	+= intel_mid_powerbtn.o
 obj-$(CONFIG_INTEL_OAKTRAIL)	+= intel_oaktrail.o
 obj-$(CONFIG_SAMSUNG_Q10)	+= samsung-q10.o
 obj-$(CONFIG_APPLE_GMUX)	+= apple-gmux.o
+
+obj-$(CONFIG_EARLY_PRINTK)	+= early/
diff --git a/drivers/platform/x86/early/Makefile b/drivers/platform/x86/early/Makefile
new file mode 100644
index 0000000..5d9408c
--- /dev/null
+++ b/drivers/platform/x86/early/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for linux/drivers/platform/x86/early
+# x86 Platform-Specific Early Printk Support
+#
+obj-$(CONFIG_EARLY_PRINTK_INTEL_MID_SPI)	+= intel_mid_spi.o
diff --git a/drivers/platform/x86/early/intel_mid_spi.c b/drivers/platform/x86/early/intel_mid_spi.c
new file mode 100644
index 0000000..fa5a1a2
--- /dev/null
+++ b/drivers/platform/x86/early/intel_mid_spi.c
@@ -0,0 +1,220 @@
+/*
+ * intel_mid_spi.c - SPI UART early consoles for Intel MID platforms
+ *
+ * Copyright (c) 2008-2012, 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 the Free Software Foundation; version 2
+ * of the License.
+ */
+
+/*
+ * This file is originally implemented by Feng Tang <feng.tang@intel.com>.
+ * It is moved here to co-exist with CONFIG_EARLY_PRINTK_ACPI.
+ * Any questions you should contact the original author.
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/serial_mfd.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/intel_mid_early.h>
+#include <asm/fixmap.h>
+
+#define DW_SPI_TIMEOUT			0x200000
+#define DW_SPI0_CLK_REG			0xff11d86c
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET			0
+
+#define SPI_FRF_OFFSET			4
+#define SPI_FRF_SPI			0x0
+#define SPI_FRF_SSP			0x1
+#define SPI_FRF_MICROWIRE		0x2
+#define SPI_FRF_RESV			0x3
+
+#define SPI_MODE_OFFSET			6
+#define SPI_SCPH_OFFSET			6
+#define SPI_SCOL_OFFSET			7
+#define SPI_TMOD_OFFSET			8
+#define	SPI_TMOD_TR			0x0		/* xmit & recv */
+#define SPI_TMOD_TO			0x1		/* xmit only */
+#define SPI_TMOD_RO			0x2		/* recv only */
+#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET		10
+#define SPI_SRL_OFFSET			11
+#define SPI_CFS_OFFSET			12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK				0x7f		/* cover 7 bits */
+#define SR_BUSY				(1 << 0)
+#define SR_TF_NOT_FULL			(1 << 1)
+#define SR_TF_EMPT			(1 << 2)
+#define SR_RF_NOT_EMPT			(1 << 3)
+#define SR_RF_FULL			(1 << 4)
+#define SR_TX_ERR			(1 << 5)
+#define SR_DCOL				(1 << 6)
+
+struct dw_spi_reg {
+	u32	ctrl0;
+	u32	ctrl1;
+	u32	ssienr;
+	u32	mwcr;
+	u32	ser;
+	u32	baudr;
+	u32	txfltr;
+	u32	rxfltr;
+	u32	txflr;
+	u32	rxflr;
+	u32	sr;
+	u32	imr;
+	u32	isr;
+	u32	risr;
+	u32	txoicr;
+	u32	rxoicr;
+	u32	rxuicr;
+	u32	msticr;
+	u32	icr;
+	u32	dmacr;
+	u32	dmatdlr;
+	u32	dmardlr;
+	u32	idr;
+	u32	version;
+
+	/* Currently operates as 32 bits, though only the low 16 bits matter */
+	u32	dr;
+} __packed;
+
+#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
+#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
+
+static u32 *pclk_spi0;
+/* Always contains an accessible address, start with 0 */
+static struct dw_spi_reg *pspi;
+static int dw_spi_initialized;
+static u32 dw_spi_regbase;
+
+/* Translate char to a eligible word and send to max3110 */
+static void max3110_write_data(char c)
+{
+	u16 data;
+
+	data = 0x8000 | c;
+	dw_writel(pspi, dr, data);
+}
+
+/* Set the ratio rate to 115200, 8n1, IRQ disabled */
+static void max3110_write_config(void)
+{
+	u16 config;
+
+	config = 0xc001;
+	dw_writel(pspi, dr, config);
+}
+
+int mid_spi_early_console_reset(void)
+{
+	u32 ctrlr0 = 0;
+	u32 spi0_cdiv;
+	u32 freq; /* Freqency info only need be searched once */
+
+	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
+	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+						      DW_SPI0_CLK_REG);
+	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
+	freq = 100000000 / (spi0_cdiv + 1);
+
+	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+						 dw_spi_regbase);
+
+	/* Disable SPI controller */
+	dw_writel(pspi, ssienr, 0);
+
+	/* Set control param, 8 bits, transmit only mode */
+	ctrlr0 = dw_readl(pspi, ctrl0);
+
+	ctrlr0 &= 0xfcc0;
+	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
+		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
+	dw_writel(pspi, ctrl0, ctrlr0);
+
+	/*
+	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
+	 * calculate the clk dividor to make the clock a little slower
+	 * than real baud rate.
+	 */
+	dw_writel(pspi, baudr, freq/100000);
+
+	/* Disable all INT for early phase */
+	dw_writel(pspi, imr, 0x0);
+
+	/* Set the cs to spi-uart */
+	dw_writel(pspi, ser, 0x2);
+
+	/* Enable the HW, the last step for HW init */
+	dw_writel(pspi, ssienr, 0x1);
+
+	/* Set the default configuration */
+	max3110_write_config();
+
+	return 0;
+}
+EXPORT_SYMBOL(mid_spi_early_console_reset);
+
+/* Slave select should be called in the read/write function */
+static void dw_early_spi_putc(char c)
+{
+	unsigned int timeout;
+	u32 sr;
+
+	timeout = DW_SPI_TIMEOUT;
+	/* Early putc needs to make sure the TX FIFO is not full */
+	while (--timeout) {
+		sr = dw_readl(pspi, sr);
+		if (!(sr & SR_TF_NOT_FULL))
+			cpu_relax();
+		else
+			break;
+	}
+
+	if (!timeout)
+		pr_warn("mid-spi-early: timed out\n");
+	else
+		max3110_write_data(c);
+}
+
+/* Early SPI only uses polling mode */
+static void dw_early_spi_write(struct console *con,
+			       const char *str, unsigned n)
+{
+	int i;
+
+	for (i = 0; i < n && *str; i++) {
+		if (*str == '\n')
+			dw_early_spi_putc('\r');
+		dw_early_spi_putc(*str);
+		str++;
+	}
+}
+
+struct console mid_spi_early_console = {
+	.name =		"earlymidspi",
+	.write =	dw_early_spi_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
+void __init mid_spi_early_console_init(u32 spi_paddr)
+{
+	if (dw_spi_initialized)
+		return;
+	dw_spi_regbase = spi_paddr;
+	mid_spi_early_console_reset();
+	dw_spi_initialized = 1;
+}
+
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index 1b2b356..ffa9d62 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -341,6 +341,7 @@ struct acpi_dbg2_device {
 
 #define ACPI_DBG2_16550_COMPATIBLE  0x0000
 #define ACPI_DBG2_16550_SUBSET      0x0001
+#define ACPI_DBG2_INTEL_MID_SPI     0x0002
 
 #define ACPI_DBG2_1394_STANDARD     0x0000
 
diff --git a/include/linux/intel_mid_early.h b/include/linux/intel_mid_early.h
new file mode 100644
index 0000000..edba232
--- /dev/null
+++ b/include/linux/intel_mid_early.h
@@ -0,0 +1,12 @@
+#ifndef LINUX_INTEL_MID_EARLY_H
+#define LINUX_INTEL_MID_EARLY_H
+
+#include <linux/console.h>
+
+extern struct console mid_spi_early_console;
+
+extern void mid_spi_early_console_init(u32 spi_paddr);
+extern int mid_spi_early_console_reset(void);
+
+#endif /* LINUX_INTEL_MID_EARLY_H */
+
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2012-10-09  2:36 ` [PATCH v5 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
@ 2012-10-09 17:02   ` Konrad Rzeszutek Wilk
  2012-10-10  1:31     ` Zheng, Lv
  2012-10-10  1:40     ` Zheng, Lv
  0 siblings, 2 replies; 26+ messages in thread
From: Konrad Rzeszutek Wilk @ 2012-10-09 17:02 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Len Brown, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Feng Tang, linux-kernel, linux-acpi, x86,
	platform-driver-x86

On Tue, Oct 09, 2012 at 10:36:56AM +0800, Lv Zheng wrote:
> Microsoft Debug Port Table (DBGP or DBG2) is used by the Windows SoC
> platforms to describe their debugging facilities.
> DBGP: http://msdn.microsoft.com/en-us/windows/hardware/hh134821
> DBG2: http://msdn.microsoft.com/en-us/library/windows/hardware/hh673515
> 
> This patch enables the DBGP/DBG2 debug ports as Linux early console
> launcher.  Individual early console drivers are also needed to get the
> early kernel messages dumped on the consoles.  For example, to use the
> SPI UART early console for the Low Power Intel Architecture (LPIA)
> platforms, you need to enable the following kernel configurations:
>   CONFIG_EARLY_PRINTK_ACPI=y
>   CONFIG_EARLY_PRINTK_INTEL_MID_SPI=y
> Then you need to append the following kernel parameter to the kernel
> command line in your the boot loader configuration file:
>   earlyprintk=acpi
> 
> There is a dilemma in designing this patch set.  Let me describe it in
> details.
> There should be three steps to enable an early console for an operating
> system:
> 1. Probe: In this stage, the Linux kernel can detect the early consoles
>           and the base address of their register block can be determined.
>           This can be done by parsing the descriptors in the ACPI DBGP/DBG2
>           tables.  Note that acpi_table_init() must be called before
>           parsing.
> 2. Setup: In this stage, the Linux kernel can apply user specified
>           configuration options (ex. baudrate of serial ports) for the
>           early consoles.  This is done by parsing the early parameters
>           passed to the kernel from the boot loaders.  Note that
>           parse_early_params() is called very early to allow parameters to
>           be passed to other kernel subsystems.
> 3. Start: In this stage, the Linux kernel can make the consoles ready to
>           output logs.  Since the early consoles are always used for the
>           kernel boot up debugging, this must be done as early as possible
>           to arm the kernel with the highest testability for other kernel
>           subsystems.  Note that, this stage happens when the
>           register_console() is called.
> The preferred sequence for the above steps is:
>    +-----------------+    +-------------------+    +--------------------+
>    | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
>    +-----------------+    +-------------------+    +--------------------+
> But unfortunately, in the current x86 implementation, early parameters and
> early printk initialization are called before acpi_table_init() which
> depends on the early memory mapping facility.
> There are some choices for me to design this patch set:
> 1. Invoking acpi_table_init() before parse_early_param() to maintain the
>    sequence:
>    +-----------------+    +-------------------+    +--------------------+
>    | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
>    +-----------------+    +-------------------+    +--------------------+
>    This requires other subsystem maintainers' review to ensure no
>    regressions will be introduced.  At the first glance, I found there
>    might be problems for the EFI subsystsm:
>    The EFI boot services and runtime services are mixed up in the x86
>    specific initialization process before the ACPI table initialization.
>    Things are much worse that you even cannot disable the runtime services
>    while still allow the boot services codes to be executed in the kernel
>    compilation stage.  Enabling the early consoles after the ACPI table
>    initialization will make it difficult to debug the runtime BIOS bugs.
>    If any progress is made to the kernel boot sequences, please let me
>    know.  I'll be willing to redesign the ACPI DBGP/DBG2 console probing
>    facility.  You can reach me at <lv.zheng@intel.com> and
>    <zetalog@gmail.com>.
> 2. Modifying the above sequece to make it look like:
>    +-------------------+    +-----------------+    +--------------------+
>    | EARLY_PARAM SETUP | -> | ACPI DBGP PROBE | -> | EARLY_RPINTK START |
>    +-------------------+    +-----------------+    +--------------------+
>    Early consoles started in this style will lose part of the testability
>    in the kernel boot up sequence.  If the system does not crash very
>    early, developers still can see the bufferred kernel outputs when the
>    register_console() is called.
>    Current early console implementations need to be modified to be
>    compatible with this design.  The original codes need to be split up
>    into tow parts:
>    1. Detecting hardware.  This part can be called in the PROBE stage.
>    2. Applying user parameters.  This part can be called in the SETUP
>       stage.
>    Individual early console drver maintainers need to be involved to avoid
>    regressions that might occur if we do things in this way.  And the
>    maintainers can offer better tests than I can do.
> 3. Introducing a brand new debugging facility that does not relate to the
>    current early console implementation to allow the early consoles to be
>    automatically detected.
>    +-------------------+    +--------------------+
>    | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
>    +-------------------+    +--------------------+
>    +-----------------+    +--------------------+
>    | ACPI DBGP PROBE | -> | EARLY_RPINTK START |
>    +-----------------+    +--------------------+
>    Early consoles started in this style will lose part of the testability
>    in the kernel boot up sequence.  If the system does not crash very
>    early, developers still can see the bufferred kernel outputs when the
>    register_console() is called.
>    Comparing to the solution 2, we can notice that the user configuration
>    can not be applied to the registered early consoles in this way as the
>    acpi_table_init() is still called after the parse_early_param().
>    Instead, the early consoles should derive the hardware settings used in
>    the BIOS/bootloaders.
>    This is what the patch set has done to enable this new usage model.
>    It is known as "ACPI early console launcher mode".
>    As a launcher, ACPI DBGP will not actually output kernel messages
>    without the real early console drivers, that's why the
>    CONFIG_EARLY_PRINTK_INTEL_MID_SPI still need to be enabled along with
>    the CONFIG_EARLY_PRINTK_ACPI.
>    In order to disable this facility by default and enable it at runtime,
>    an kernel parameter "earlyprintk=acpi" is introduced.  This makes the
>    actual sequence look like:
>    +-------------------+    +--------------------+
>    | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
>    +-------------------+    +....................+
>                             | ACPI DBGP LAUNCH   | ->
>                             +--------------------+
>       +-----------------+    +--------------------+
>    -> | ACPI DBGP PROBE | -> | EARLY_PRINTK START |
>       +-----------------+    +--------------------+
> 
> Version 1:
>  1. Enables single DBG2 debug port support.
> Version 2:
>  1. Applies Rui's comments.
> Version 3:
>  1. Applies Len's comments (earlycon should be disabled by default).
>  2. Enables single DBG2 debug ports support.
> Version 4:
>  1. Fixes the CodingStyle issues reported by checkpatch.pl.
>  2. Enables single DBGP debug port support.
> Version 5:
>  1. Enables multiple DBG2 debug ports support.
>  2. Applies Konrad's comments (pr_debug should be used in earlycon).
>  3. Changes kstrtoul back to simple_strtoul.
> 
> Known Issues:
> 1. The simple_strtoul function cannot be replaced by the kstrtoul in
>    the x86 specific booting codes.  The kstrtoul will return error on
>    strings like "acpi0,keep".  This will leave one CodingStyle issue
>    reported by the checkpatch.pl.
> 
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Reviewed-by: Len Brown <len.brown@intel.com>
> Reviewed-by: Rui Zhang <rui.zhang@intel.com>
> Reviewed-by: Ying Huang <ying.huang@intel.com>
> Reviewed-by: Konrad Rzeszutek Wilk <konrad@kernel.org>

Please don't include that unless I (or other folks looking at your code)
say explicitly 'Acked' or 'Reviewed-by'

> ---
>  Documentation/kernel-parameters.txt |    1 +
>  arch/x86/Kconfig.debug              |   15 +++
>  arch/x86/kernel/acpi/boot.c         |    1 +
>  arch/x86/kernel/early_printk.c      |   13 +++
>  drivers/acpi/Makefile               |    2 +
>  drivers/acpi/early_printk.c         |  173 +++++++++++++++++++++++++++++++++++
>  include/linux/acpi.h                |   22 +++++
>  7 files changed, 227 insertions(+)
>  create mode 100644 drivers/acpi/early_printk.c
> 
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index ad7e2e5..f656765 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -763,6 +763,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>  			earlyprintk=serial[,ttySn[,baudrate]]
>  			earlyprintk=ttySn[,baudrate]
>  			earlyprintk=dbgp[debugController#]
> +			earlyprintk=acpi[debugController#]
>  
>  			Append ",keep" to not disable it when the real console
>  			takes over.
> diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
> index b322f12..5778082 100644
> --- a/arch/x86/Kconfig.debug
> +++ b/arch/x86/Kconfig.debug
> @@ -59,6 +59,21 @@ config EARLY_PRINTK_DBGP
>  	  with klogd/syslogd or the X server. You should normally N here,
>  	  unless you want to debug such a crash. You need usb debug device.
>  
> +config EARLY_PRINTK_ACPI
> +	bool "Early printk launcher via ACPI debug port tables"
> +	depends on EARLY_PRINTK && ACPI
> +	---help---
> +	  Write kernel log output directly into the debug ports described
> +	  in the ACPI tables known as DBGP and DBG2.
> +
> +	  To enable such debugging facilities, you need to enable this
> +	  configuration option and append the "earlyprintk=acpi" kernel
> +	  parameter through the boot loaders.  Please refer the
> +	  "Documentation/kernel-parameters.txt" for details.  Since this
> +	  is an early console launcher, you still need to enable actual
> +	  early console drivers that are suitable for your platform.
> +	  If in doubt, say "N".
> +
>  config DEBUG_STACKOVERFLOW
>  	bool "Check for stack overflows"
>  	depends on DEBUG_KERNEL
> diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
> index b2297e5..cc10ea5 100644
> --- a/arch/x86/kernel/acpi/boot.c
> +++ b/arch/x86/kernel/acpi/boot.c
> @@ -1518,6 +1518,7 @@ void __init acpi_boot_table_init(void)
>  		return;
>  	}
>  
> +	acpi_early_console_probe();
>  	acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
>  
>  	/*
> diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
> index 9b9f18b..bf5b596 100644
> --- a/arch/x86/kernel/early_printk.c
> +++ b/arch/x86/kernel/early_printk.c
> @@ -200,6 +200,15 @@ static inline void early_console_register(struct console *con, int keep_early)
>  	register_console(early_console);
>  }
>  
> +#ifdef CONFIG_EARLY_PRINTK_ACPI
> +#include <linux/acpi.h>
> +
> +int __init __acpi_early_console_start(struct acpi_debug_port *info)
> +{
> +	return 0;
> +}
> +#endif
> +
>  static int __init setup_early_printk(char *buf)
>  {
>  	int keep;
> @@ -236,6 +245,10 @@ static int __init setup_early_printk(char *buf)
>  		if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4))
>  			early_console_register(&early_dbgp_console, keep);
>  #endif
> +#ifdef CONFIG_EARLY_PRINTK_ACPI
> +		if (!strncmp(buf, "acpi", 4))
> +			acpi_early_console_launch(buf + 4, keep);
> +#endif
>  #ifdef CONFIG_HVC_XEN
>  		if (!strncmp(buf, "xen", 3))
>  			early_console_register(&xenboot_console, keep);
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 47199e2..99dbd64 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -46,6 +46,8 @@ ifdef CONFIG_ACPI_VIDEO
>  acpi-y				+= video_detect.o
>  endif
>  
> +obj-$(CONFIG_EARLY_PRINTK_ACPI)	+= early_printk.o
> +
>  # These are (potentially) separate modules
>  obj-$(CONFIG_ACPI_AC) 		+= ac.o
>  obj-$(CONFIG_ACPI_BUTTON)	+= button.o
> diff --git a/drivers/acpi/early_printk.c b/drivers/acpi/early_printk.c
> new file mode 100644
> index 0000000..3e5c1f3
> --- /dev/null
> +++ b/drivers/acpi/early_printk.c
> @@ -0,0 +1,173 @@
> +/*
> + * acpi/early_printk.c - ACPI Boot-Time Debug Ports
> + *
> + * Copyright (c) 2012, Intel Corporation
> + * Author: Lv Zheng <lv.zheng@intel.com>
> + *
> + * 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 the Free Software Foundation; version 2
> + * of the License.
> + */
> +
> +#define DEBUG

That should not be the default case.

> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +#include <linux/errno.h>
> +#include <linux/acpi.h>
> +#include <linux/bitmap.h>
> +#include <linux/bootmem.h>
> +
> +#define MAX_ACPI_DBG_PORTS	16
> +
> +DECLARE_BITMAP(acpi_early_flags, MAX_ACPI_DBG_PORTS);

static?

> +int acpi_early_enabled;

__read_mostly and you could also make it a bool.


> +
> +static int acpi_early_console_enable(u8 port, int keep)
> +{
> +	if (port >= MAX_ACPI_DBG_PORTS)
> +		return -ENODEV;
> +
> +	set_bit(port, acpi_early_flags);
> +	if (keep)
> +		set_bit(port+MAX_ACPI_DBG_PORTS, acpi_early_flags);


Huh? The bitmap is up to MAX_ACPI_DB_PORTS, but here you offset it
past that? Why?

> +	acpi_early_enabled = 1;
> +
> +	pr_debug("early: DBGx LAUNCH - console %d.\n", port);
> +
> +	return 0;
> +}
> +
> +static inline bool acpi_early_console_enabled(u8 port)
> +{
> +	BUG_ON(port >= MAX_ACPI_DBG_PORTS);
> +	return test_bit(port, acpi_early_flags);
> +}
> +
> +int __init acpi_early_console_keep(struct acpi_debug_port *info)

Why not make it 'bool' like the other (acpi_early_console_enabled)?
> +{
> +	BUG_ON(!info || info->port_index >= MAX_ACPI_DBG_PORTS);
> +	return test_bit(info->port_index+MAX_ACPI_DBG_PORTS, acpi_early_flags);
> +}
> +
> +static int __init acpi_early_console_start(struct acpi_debug_port *info)
> +{
> +	if (!acpi_early_console_enabled(info->port_index))
> +		return 0;

Not -ENODEV?
> +
> +	pr_debug("early: DBGx START - console %d(%04x:%04x).\n",
> +		 info->port_index, info->port_type, info->port_subtype);
> +	__acpi_early_console_start(info);
> +
> +	return 0;
> +}
> +
> +static int __init acpi_parse_dbg2(struct acpi_table_header *table)
> +{
> +	struct acpi_table_dbg2 *dbg2;
> +	struct acpi_dbg2_device *entry;
> +	unsigned int count = 0;
> +	unsigned long tbl_end;
> +	unsigned int max_entries;
> +	struct acpi_debug_port devinfo;
> +
> +	dbg2 = (struct acpi_table_dbg2 *)table;
> +	if (!dbg2) {
> +		pr_debug("early: DBG2 not present.\n");
> +		return -ENODEV;
> +	}
> +
> +	tbl_end = (unsigned long)table + table->length;
> +
> +	entry = (struct acpi_dbg2_device *)
> +		((unsigned long)dbg2 + dbg2->info_offset);
> +	max_entries = min_t(u32, MAX_ACPI_DBG_PORTS, dbg2->info_count);
> +
> +	while (((unsigned long)entry) + sizeof(struct acpi_dbg2_device) <
> +	       tbl_end) {

Just make it one line. Ignore the 80 characters limit here.

> +		if (entry->revision != 0) {
> +			pr_debug("early: DBG2 revision %d not supported.\n",
> +				 entry->revision);
> +			return -ENODEV;
> +		}
> +		if (!max_entries || count++ < max_entries) {

How about you just make this 'count'
> +			pr_debug("early: DBG2 PROBE - console %d(%04x:%04x).\n",
> +				 count-1,
> +				 entry->port_type, entry->port_subtype);
> +
> +			devinfo.port_index = (u8)count-1;

Then you don't this 'count -1'
> +			devinfo.port_type = entry->port_type;
> +			devinfo.port_subtype = entry->port_subtype;
> +			devinfo.register_count = entry->register_count;
> +			devinfo.registers = (struct acpi_generic_address *)
> +			    ((unsigned long)entry + entry->base_address_offset);
> +			devinfo.namepath_length = entry->namepath_length;
> +			devinfo.namepath = (char *)
> +			    ((unsigned long)entry + entry->namepath_offset);
> +			devinfo.oem_data_length = entry->oem_data_length;
> +			devinfo.oem_data = (u8 *)
> +			    ((unsigned long)entry + entry->oem_data_offset);
> +
> +			acpi_early_console_start(&devinfo);

no check of the return value to see whether you should return
immediately?
> +		}
and then do
		count++ here?

> +
> +		entry = (struct acpi_dbg2_device *)
> +		    ((unsigned long)entry + entry->length);
> +	}
> +
> +	return 0;
> +}
> +
> +static int __init acpi_parse_dbgp(struct acpi_table_header *table)
> +{
> +	struct acpi_table_dbgp *dbgp;
> +	struct acpi_debug_port devinfo;
> +
> +	dbgp = (struct acpi_table_dbgp *)table;
> +	if (!dbgp) {
> +		pr_debug("early: DBGP not present.\n");
> +		return -ENODEV;
> +	}
> +
> +	pr_debug("early: DBGP PROBE - console (%04x).\n", dbgp->type);
> +
> +	devinfo.port_index = 0;
> +	devinfo.port_type = ACPI_DBG2_SERIAL_PORT;
> +	devinfo.port_subtype = dbgp->type;
> +	devinfo.register_count = 1;
> +	devinfo.registers = (struct acpi_generic_address *)&dbgp->debug_port;
> +	devinfo.namepath_length = 0;
> +	devinfo.namepath = NULL;
> +	devinfo.oem_data_length = 0;
> +	devinfo.oem_data = NULL;
> +
> +	acpi_early_console_start(&devinfo);

how about 'return acpi_early_console_start(..)'
> +
> +	return 0;
> +}
> +
> +int __init acpi_early_console_probe(void)
> +{
> +	if (!acpi_early_enabled)
> +		return -EINVAL;
> +
> +	if (acpi_table_parse(ACPI_SIG_DBG2, acpi_parse_dbg2) != 0)
> +		acpi_table_parse(ACPI_SIG_DBGP, acpi_parse_dbgp);
> +
> +	return 0;
> +}
> +
> +int __init acpi_early_console_launch(char *s, int keep)
> +{
> +	char *e;
> +	unsigned long port = 0;
> +
> +	if (*s)
> +		port = simple_strtoul(s, &e, 10);
> +
> +	return acpi_early_console_enable(port, keep);
> +}
> +
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 4f2a762..641366c 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -430,4 +430,26 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state,
>  #define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
>  #endif
>  
> +#ifdef CONFIG_EARLY_PRINTK_ACPI
> +struct acpi_debug_port {
> +	u8 port_index;
> +	u16 port_type;
> +	u16 port_subtype;
> +	u16 register_count;
> +	struct acpi_generic_address *registers;
> +	u16 namepath_length;
> +	char *namepath;
> +	u16 oem_data_length;
> +	u8 *oem_data;
> +};
> +
> +int __init acpi_early_console_keep(struct acpi_debug_port *info);
> +int __init acpi_early_console_launch(char *s, int keep);
> +int __init acpi_early_console_probe(void);
> +/* This interface is arch specific. */
> +int __init __acpi_early_console_start(struct acpi_debug_port *info);
> +#else
> +static int acpi_early_console_probe(void) { return 0; }
> +#endif
> +
>  #endif	/*_LINUX_ACPI_H*/
> -- 
> 1.7.10
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 2/2] ACPI: Add Intel MID SPI early console support.
  2012-10-09  2:37 ` [PATCH v5 2/2] ACPI: Add Intel MID SPI early console support Lv Zheng
@ 2012-10-09 17:06   ` Konrad Rzeszutek Wilk
  2012-10-10  1:33     ` Zheng, Lv
  2012-10-10  3:10     ` Zheng, Lv
  0 siblings, 2 replies; 26+ messages in thread
From: Konrad Rzeszutek Wilk @ 2012-10-09 17:06 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Len Brown, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Feng Tang, linux-kernel, linux-acpi, x86,
	platform-driver-x86

On Tue, Oct 09, 2012 at 10:37:32AM +0800, Lv Zheng wrote:
> DesignWare SPI UART is used as one of the debug ports on Low Power Intel
> Architecture (LPIA) platforms.  This patch is introduced to support this
> debugging console reported by ACPI DBGP/DBG2.  The original MID SPI
> early console stuff is also refined to co-exist with the new ACPI usage
> model.
> 
> To use this facility on LPIA platforms, you need to enable the following
> kernel configurations:
>   CONFIG_EARLY_PRINTK_ACPI=y
>   CONFIG_EARLY_PRINTK_INTEL_MID_SPI=y
> Then you need to append the following kernel parameter to the kernel
> command line in the boot loader configuration file:
>   earlyprintk=acpi


.. or earlyprintk=mrst
?
> 
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> Reviewed-by: Feng Tang <feng.tang@intel.com>
> ---
>  Documentation/kernel-parameters.txt        |    1 +
>  arch/x86/Kconfig.debug                     |   23 +++
>  arch/x86/include/asm/mrst.h                |    2 +-
>  arch/x86/kernel/early_printk.c             |   12 +-
>  arch/x86/platform/mrst/early_printk_mrst.c |  186 +----------------------
>  drivers/platform/x86/Makefile              |    2 +
>  drivers/platform/x86/early/Makefile        |    5 +
>  drivers/platform/x86/early/intel_mid_spi.c |  220 ++++++++++++++++++++++++++++
>  include/acpi/actbl2.h                      |    1 +
>  include/linux/intel_mid_early.h            |   12 ++
>  10 files changed, 283 insertions(+), 181 deletions(-)
>  create mode 100644 drivers/platform/x86/early/Makefile
>  create mode 100644 drivers/platform/x86/early/intel_mid_spi.c
>  create mode 100644 include/linux/intel_mid_early.h
> 
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index f656765..003ffd9 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -762,6 +762,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>  			earlyprintk=vga
>  			earlyprintk=serial[,ttySn[,baudrate]]
>  			earlyprintk=ttySn[,baudrate]
> +			earlyprintk=mrst
>  			earlyprintk=dbgp[debugController#]
>  			earlyprintk=acpi[debugController#]
>  
> diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
> index 5778082..4a26e2d 100644
> --- a/arch/x86/Kconfig.debug
> +++ b/arch/x86/Kconfig.debug
> @@ -43,9 +43,32 @@ config EARLY_PRINTK
>  	  with klogd/syslogd or the X server. You should normally N here,
>  	  unless you want to debug such a crash.
>  
> +config EARLY_PRINTK_INTEL_MID_SPI
> +	bool "Early printk for Intel MID SPI UART port"
> +	depends on EARLY_PRINTK
> +	---help---
> +	  Write kernel log output directly into the MID SPI UART debug port.
> +
> +	  Intel MID platforms are using DesignWare SPI UART as its debug
> +	  console.  This option does not introduce actual early console into
> +	  the kernel binary, but is required by a real early console
> +	  implementation (EARLY_PRINTK_INTEL_MID or EARLY_PRINTK_ACPI).
> +	  You should normally N here unless you need to do kernel booting
> +	  development.
> +
>  config EARLY_PRINTK_INTEL_MID
>  	bool "Early printk for Intel MID platform support"
>  	depends on EARLY_PRINTK && X86_INTEL_MID
> +	select EARLY_PRINTK_INTEL_MID_SPI
> +	---help---
> +	  Write kernel log output directly into the MID SPI UART debug port.
> +
> +	  Intel MID platforms are always equipped with SPI debug ports and
> +	  USB OTG debug ports. To enable these debugging facilities, you
> +	  need to pass "earlyprintk=mrst" parameter to the kernel through
> +	  boot loaders.  Please see "Documentation/kernel-parameter.txt" for
> +	  details.  You should normally N here unless you need to do kernel
> +	  booting development.
>  
>  config EARLY_PRINTK_DBGP
>  	bool "Early printk via EHCI debug port"
> diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
> index fc18bf3..8ab0655 100644
> --- a/arch/x86/include/asm/mrst.h
> +++ b/arch/x86/include/asm/mrst.h
> @@ -12,6 +12,7 @@
>  #define _ASM_X86_MRST_H
>  
>  #include <linux/sfi.h>
> +#include <linux/intel_mid_early.h>
>  
>  extern int pci_mrst_init(void);
>  extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
> @@ -63,7 +64,6 @@ extern enum mrst_timer_options mrst_timer_options;
>  #define SFI_MTMR_MAX_NUM 8
>  #define SFI_MRTC_MAX	8
>  
> -extern struct console early_mrst_console;
>  extern void mrst_early_console_init(void);
>  
>  extern struct console early_hsu_console;
> diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
> index bf5b596..9b5ee96 100644
> --- a/arch/x86/kernel/early_printk.c
> +++ b/arch/x86/kernel/early_printk.c
> @@ -205,6 +205,16 @@ static inline void early_console_register(struct console *con, int keep_early)
>  
>  int __init __acpi_early_console_start(struct acpi_debug_port *info)
>  {
> +#ifdef CONFIG_EARLY_PRINTK_INTEL_MID_SPI
> +	if (info->port_type == ACPI_DBG2_SERIAL_PORT
> +	    && info->port_subtype == ACPI_DBG2_INTEL_MID_SPI
> +	    && info->register_count > 0) {

Is it ever going to be zero?

> +		mid_spi_early_console_init((u32)(info->registers[0].address));
> +		early_console_register(&mid_spi_early_console,
> +				       acpi_early_console_keep(info));
> +	}
> +#endif
> +
>  	return 0;
>  }
>  #endif
> @@ -256,7 +266,7 @@ static int __init setup_early_printk(char *buf)
>  #ifdef CONFIG_EARLY_PRINTK_INTEL_MID
>  		if (!strncmp(buf, "mrst", 4)) {
>  			mrst_early_console_init();
> -			early_console_register(&early_mrst_console, keep);
> +			early_console_register(&mid_spi_early_console, keep);
>  		}
>  
>  		if (!strncmp(buf, "hsu", 3)) {
> diff --git a/arch/x86/platform/mrst/early_printk_mrst.c b/arch/x86/platform/mrst/early_printk_mrst.c
> index 028454f..7afbf18 100644
> --- a/arch/x86/platform/mrst/early_printk_mrst.c
> +++ b/arch/x86/platform/mrst/early_printk_mrst.c
> @@ -29,82 +29,8 @@
>  #include <asm/pgtable.h>
>  #include <asm/mrst.h>
>  
> -#define MRST_SPI_TIMEOUT		0x200000
>  #define MRST_REGBASE_SPI0		0xff128000
>  #define MRST_REGBASE_SPI1		0xff128400
> -#define MRST_CLK_SPI0_REG		0xff11d86c
> -
> -/* Bit fields in CTRLR0 */
> -#define SPI_DFS_OFFSET			0
> -
> -#define SPI_FRF_OFFSET			4
> -#define SPI_FRF_SPI			0x0
> -#define SPI_FRF_SSP			0x1
> -#define SPI_FRF_MICROWIRE		0x2
> -#define SPI_FRF_RESV			0x3
> -
> -#define SPI_MODE_OFFSET			6
> -#define SPI_SCPH_OFFSET			6
> -#define SPI_SCOL_OFFSET			7
> -#define SPI_TMOD_OFFSET			8
> -#define	SPI_TMOD_TR			0x0		/* xmit & recv */
> -#define SPI_TMOD_TO			0x1		/* xmit only */
> -#define SPI_TMOD_RO			0x2		/* recv only */
> -#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
> -
> -#define SPI_SLVOE_OFFSET		10
> -#define SPI_SRL_OFFSET			11
> -#define SPI_CFS_OFFSET			12
> -
> -/* Bit fields in SR, 7 bits */
> -#define SR_MASK				0x7f		/* cover 7 bits */
> -#define SR_BUSY				(1 << 0)
> -#define SR_TF_NOT_FULL			(1 << 1)
> -#define SR_TF_EMPT			(1 << 2)
> -#define SR_RF_NOT_EMPT			(1 << 3)
> -#define SR_RF_FULL			(1 << 4)
> -#define SR_TX_ERR			(1 << 5)
> -#define SR_DCOL				(1 << 6)
> -
> -struct dw_spi_reg {
> -	u32	ctrl0;
> -	u32	ctrl1;
> -	u32	ssienr;
> -	u32	mwcr;
> -	u32	ser;
> -	u32	baudr;
> -	u32	txfltr;
> -	u32	rxfltr;
> -	u32	txflr;
> -	u32	rxflr;
> -	u32	sr;
> -	u32	imr;
> -	u32	isr;
> -	u32	risr;
> -	u32	txoicr;
> -	u32	rxoicr;
> -	u32	rxuicr;
> -	u32	msticr;
> -	u32	icr;
> -	u32	dmacr;
> -	u32	dmatdlr;
> -	u32	dmardlr;
> -	u32	idr;
> -	u32	version;
> -
> -	/* Currently operates as 32 bits, though only the low 16 bits matter */
> -	u32	dr;
> -} __packed;
> -
> -#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
> -#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
> -
> -/* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */
> -static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0;
> -
> -static u32 *pclk_spi0;
> -/* Always contains an accessible address, start with 0 */
> -static struct dw_spi_reg *pspi;
>  
>  static struct kmsg_dumper dw_dumper;
>  static int dumper_registered;
> @@ -116,77 +42,21 @@ static void dw_kmsg_dump(struct kmsg_dumper *dumper,
>  	size_t len;
>  
>  	/* When run to this, we'd better re-init the HW */
> -	mrst_early_console_init();
> +	mid_spi_early_console_reset();
>  
>  	while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len))
> -		early_mrst_console.write(&early_mrst_console, line, len);
> -}
> -
> -/* Set the ratio rate to 115200, 8n1, IRQ disabled */
> -static void max3110_write_config(void)
> -{
> -	u16 config;
> -
> -	config = 0xc001;
> -	dw_writel(pspi, dr, config);
> -}
> -
> -/* Translate char to a eligible word and send to max3110 */
> -static void max3110_write_data(char c)
> -{
> -	u16 data;
> -
> -	data = 0x8000 | c;
> -	dw_writel(pspi, dr, data);
> +		mid_spi_early_console.write(&mid_spi_early_console, line, len);
>  }
>  
>  void mrst_early_console_init(void)
>  {
> -	u32 ctrlr0 = 0;
> -	u32 spi0_cdiv;
> -	u32 freq; /* Freqency info only need be searched once */
> -
> -	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
> -	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
> -							MRST_CLK_SPI0_REG);
> -	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
> -	freq = 100000000 / (spi0_cdiv + 1);
> +	/* Default use SPI0 register for mrst */
> +	unsigned long spi_paddr = MRST_REGBASE_SPI0;
>  
> +	/* Detect Penwell and use SPI1 */
>  	if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL)
> -		mrst_spi_paddr = MRST_REGBASE_SPI1;
> -
> -	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
> -						mrst_spi_paddr);
> -
> -	/* Disable SPI controller */
> -	dw_writel(pspi, ssienr, 0);
> -
> -	/* Set control param, 8 bits, transmit only mode */
> -	ctrlr0 = dw_readl(pspi, ctrl0);
> -
> -	ctrlr0 &= 0xfcc0;
> -	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
> -		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
> -	dw_writel(pspi, ctrl0, ctrlr0);
> -
> -	/*
> -	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
> -	 * calculate the clk dividor to make the clock a little slower
> -	 * than real baud rate.
> -	 */
> -	dw_writel(pspi, baudr, freq/100000);
> -
> -	/* Disable all INT for early phase */
> -	dw_writel(pspi, imr, 0x0);
> -
> -	/* Set the cs to spi-uart */
> -	dw_writel(pspi, ser, 0x2);
> -
> -	/* Enable the HW, the last step for HW init */
> -	dw_writel(pspi, ssienr, 0x1);
> -
> -	/* Set the default configuration */
> -	max3110_write_config();
> +		spi_paddr = MRST_REGBASE_SPI1;
> +	mid_spi_early_console_init(spi_paddr);
>  
>  	/* Register the kmsg dumper */
>  	if (!dumper_registered) {
> @@ -196,48 +66,6 @@ void mrst_early_console_init(void)
>  	}
>  }
>  
> -/* Slave select should be called in the read/write function */
> -static void early_mrst_spi_putc(char c)
> -{
> -	unsigned int timeout;
> -	u32 sr;
> -
> -	timeout = MRST_SPI_TIMEOUT;
> -	/* Early putc needs to make sure the TX FIFO is not full */
> -	while (--timeout) {
> -		sr = dw_readl(pspi, sr);
> -		if (!(sr & SR_TF_NOT_FULL))
> -			cpu_relax();
> -		else
> -			break;
> -	}
> -
> -	if (!timeout)
> -		pr_warning("MRST earlycon: timed out\n");
> -	else
> -		max3110_write_data(c);
> -}
> -
> -/* Early SPI only uses polling mode */
> -static void early_mrst_spi_write(struct console *con, const char *str, unsigned n)
> -{
> -	int i;
> -
> -	for (i = 0; i < n && *str; i++) {
> -		if (*str == '\n')
> -			early_mrst_spi_putc('\r');
> -		early_mrst_spi_putc(*str);
> -		str++;
> -	}
> -}
> -
> -struct console early_mrst_console = {
> -	.name =		"earlymrst",
> -	.write =	early_mrst_spi_write,
> -	.flags =	CON_PRINTBUFFER,
> -	.index =	-1,
> -};
> -
>  /*
>   * Following is the early console based on Medfield HSU (High
>   * Speed UART) device.
> diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
> index bf7e4f9..6e4ff46 100644
> --- a/drivers/platform/x86/Makefile
> +++ b/drivers/platform/x86/Makefile
> @@ -50,3 +50,5 @@ obj-$(CONFIG_INTEL_MID_POWER_BUTTON)	+= intel_mid_powerbtn.o
>  obj-$(CONFIG_INTEL_OAKTRAIL)	+= intel_oaktrail.o
>  obj-$(CONFIG_SAMSUNG_Q10)	+= samsung-q10.o
>  obj-$(CONFIG_APPLE_GMUX)	+= apple-gmux.o
> +
> +obj-$(CONFIG_EARLY_PRINTK)	+= early/
> diff --git a/drivers/platform/x86/early/Makefile b/drivers/platform/x86/early/Makefile
> new file mode 100644
> index 0000000..5d9408c
> --- /dev/null
> +++ b/drivers/platform/x86/early/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Makefile for linux/drivers/platform/x86/early
> +# x86 Platform-Specific Early Printk Support
> +#
> +obj-$(CONFIG_EARLY_PRINTK_INTEL_MID_SPI)	+= intel_mid_spi.o
> diff --git a/drivers/platform/x86/early/intel_mid_spi.c b/drivers/platform/x86/early/intel_mid_spi.c
> new file mode 100644
> index 0000000..fa5a1a2
> --- /dev/null
> +++ b/drivers/platform/x86/early/intel_mid_spi.c
> @@ -0,0 +1,220 @@
> +/*
> + * intel_mid_spi.c - SPI UART early consoles for Intel MID platforms
> + *
> + * Copyright (c) 2008-2012, 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 the Free Software Foundation; version 2
> + * of the License.
> + */
> +
> +/*
> + * This file is originally implemented by Feng Tang <feng.tang@intel.com>.
> + * It is moved here to co-exist with CONFIG_EARLY_PRINTK_ACPI.
> + * Any questions you should contact the original author.
> + */
> +
> +#include <linux/serial_reg.h>
> +#include <linux/serial_mfd.h>
> +#include <linux/kernel.h>
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/export.h>
> +#include <linux/io.h>
> +#include <linux/intel_mid_early.h>
> +#include <asm/fixmap.h>
> +
> +#define DW_SPI_TIMEOUT			0x200000
> +#define DW_SPI0_CLK_REG			0xff11d86c
> +
> +/* Bit fields in CTRLR0 */
> +#define SPI_DFS_OFFSET			0
> +
> +#define SPI_FRF_OFFSET			4
> +#define SPI_FRF_SPI			0x0
> +#define SPI_FRF_SSP			0x1
> +#define SPI_FRF_MICROWIRE		0x2
> +#define SPI_FRF_RESV			0x3
> +
> +#define SPI_MODE_OFFSET			6
> +#define SPI_SCPH_OFFSET			6
> +#define SPI_SCOL_OFFSET			7
> +#define SPI_TMOD_OFFSET			8
> +#define	SPI_TMOD_TR			0x0		/* xmit & recv */
> +#define SPI_TMOD_TO			0x1		/* xmit only */
> +#define SPI_TMOD_RO			0x2		/* recv only */
> +#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
> +
> +#define SPI_SLVOE_OFFSET		10
> +#define SPI_SRL_OFFSET			11
> +#define SPI_CFS_OFFSET			12
> +
> +/* Bit fields in SR, 7 bits */
> +#define SR_MASK				0x7f		/* cover 7 bits */
> +#define SR_BUSY				(1 << 0)
> +#define SR_TF_NOT_FULL			(1 << 1)
> +#define SR_TF_EMPT			(1 << 2)
> +#define SR_RF_NOT_EMPT			(1 << 3)
> +#define SR_RF_FULL			(1 << 4)
> +#define SR_TX_ERR			(1 << 5)
> +#define SR_DCOL				(1 << 6)
> +
> +struct dw_spi_reg {
> +	u32	ctrl0;
> +	u32	ctrl1;
> +	u32	ssienr;
> +	u32	mwcr;
> +	u32	ser;
> +	u32	baudr;
> +	u32	txfltr;
> +	u32	rxfltr;
> +	u32	txflr;
> +	u32	rxflr;
> +	u32	sr;
> +	u32	imr;
> +	u32	isr;
> +	u32	risr;
> +	u32	txoicr;
> +	u32	rxoicr;
> +	u32	rxuicr;
> +	u32	msticr;
> +	u32	icr;
> +	u32	dmacr;
> +	u32	dmatdlr;
> +	u32	dmardlr;
> +	u32	idr;
> +	u32	version;
> +
> +	/* Currently operates as 32 bits, though only the low 16 bits matter */
> +	u32	dr;
> +} __packed;
> +
> +#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
> +#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
> +
> +static u32 *pclk_spi0;
> +/* Always contains an accessible address, start with 0 */
> +static struct dw_spi_reg *pspi;
> +static int dw_spi_initialized;
> +static u32 dw_spi_regbase;
> +
> +/* Translate char to a eligible word and send to max3110 */
> +static void max3110_write_data(char c)
> +{
> +	u16 data;
> +
> +	data = 0x8000 | c;
> +	dw_writel(pspi, dr, data);
> +}
> +
> +/* Set the ratio rate to 115200, 8n1, IRQ disabled */
> +static void max3110_write_config(void)
> +{
> +	u16 config;
> +
> +	config = 0xc001;
> +	dw_writel(pspi, dr, config);
> +}
> +
> +int mid_spi_early_console_reset(void)
> +{
> +	u32 ctrlr0 = 0;
> +	u32 spi0_cdiv;
> +	u32 freq; /* Freqency info only need be searched once */
> +
> +	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
> +	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
> +						      DW_SPI0_CLK_REG);
> +	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
> +	freq = 100000000 / (spi0_cdiv + 1);
> +
> +	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
> +						 dw_spi_regbase);
> +
> +	/* Disable SPI controller */
> +	dw_writel(pspi, ssienr, 0);
> +
> +	/* Set control param, 8 bits, transmit only mode */
> +	ctrlr0 = dw_readl(pspi, ctrl0);
> +
> +	ctrlr0 &= 0xfcc0;
> +	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
> +		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
> +	dw_writel(pspi, ctrl0, ctrlr0);
> +
> +	/*
> +	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
> +	 * calculate the clk dividor to make the clock a little slower
> +	 * than real baud rate.
> +	 */
> +	dw_writel(pspi, baudr, freq/100000);
> +
> +	/* Disable all INT for early phase */
> +	dw_writel(pspi, imr, 0x0);
> +
> +	/* Set the cs to spi-uart */
> +	dw_writel(pspi, ser, 0x2);
> +
> +	/* Enable the HW, the last step for HW init */
> +	dw_writel(pspi, ssienr, 0x1);
> +
> +	/* Set the default configuration */
> +	max3110_write_config();
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(mid_spi_early_console_reset);
> +
> +/* Slave select should be called in the read/write function */
> +static void dw_early_spi_putc(char c)
> +{
> +	unsigned int timeout;
> +	u32 sr;
> +
> +	timeout = DW_SPI_TIMEOUT;
> +	/* Early putc needs to make sure the TX FIFO is not full */
> +	while (--timeout) {
> +		sr = dw_readl(pspi, sr);
> +		if (!(sr & SR_TF_NOT_FULL))
> +			cpu_relax();
> +		else
> +			break;
> +	}
> +
> +	if (!timeout)
> +		pr_warn("mid-spi-early: timed out\n");
> +	else
> +		max3110_write_data(c);
> +}
> +
> +/* Early SPI only uses polling mode */
> +static void dw_early_spi_write(struct console *con,
> +			       const char *str, unsigned n)
> +{
> +	int i;
> +
> +	for (i = 0; i < n && *str; i++) {
> +		if (*str == '\n')
> +			dw_early_spi_putc('\r');
> +		dw_early_spi_putc(*str);
> +		str++;
> +	}
> +}
> +
> +struct console mid_spi_early_console = {
> +	.name =		"earlymidspi",
> +	.write =	dw_early_spi_write,
> +	.flags =	CON_PRINTBUFFER,
> +	.index =	-1,
> +};
> +
> +void __init mid_spi_early_console_init(u32 spi_paddr)
> +{
> +	if (dw_spi_initialized)
> +		return;
> +	dw_spi_regbase = spi_paddr;
> +	mid_spi_early_console_reset();
> +	dw_spi_initialized = 1;
> +}
> +
> diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
> index 1b2b356..ffa9d62 100644
> --- a/include/acpi/actbl2.h
> +++ b/include/acpi/actbl2.h
> @@ -341,6 +341,7 @@ struct acpi_dbg2_device {
>  
>  #define ACPI_DBG2_16550_COMPATIBLE  0x0000
>  #define ACPI_DBG2_16550_SUBSET      0x0001
> +#define ACPI_DBG2_INTEL_MID_SPI     0x0002
>  
>  #define ACPI_DBG2_1394_STANDARD     0x0000
>  
> diff --git a/include/linux/intel_mid_early.h b/include/linux/intel_mid_early.h
> new file mode 100644
> index 0000000..edba232
> --- /dev/null
> +++ b/include/linux/intel_mid_early.h
> @@ -0,0 +1,12 @@
> +#ifndef LINUX_INTEL_MID_EARLY_H
> +#define LINUX_INTEL_MID_EARLY_H
> +
> +#include <linux/console.h>
> +
> +extern struct console mid_spi_early_console;
> +
> +extern void mid_spi_early_console_init(u32 spi_paddr);
> +extern int mid_spi_early_console_reset(void);
> +
> +#endif /* LINUX_INTEL_MID_EARLY_H */
> +
> -- 
> 1.7.10
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH v5 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2012-10-09 17:02   ` Konrad Rzeszutek Wilk
@ 2012-10-10  1:31     ` Zheng, Lv
  2012-10-10 14:06       ` Konrad Rzeszutek Wilk
  2012-10-10  1:40     ` Zheng, Lv
  1 sibling, 1 reply; 26+ messages in thread
From: Zheng, Lv @ 2012-10-10  1:31 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Brown, Len, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Tang, Feng, linux-kernel, linux-acpi, x86,
	platform-driver-x86

> > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > Reviewed-by: Len Brown <len.brown@intel.com>
> > Reviewed-by: Rui Zhang <rui.zhang@intel.com>
> > Reviewed-by: Ying Huang <ying.huang@intel.com>
> > Reviewed-by: Konrad Rzeszutek Wilk <konrad@kernel.org>
> Please don't include that unless I (or other folks looking at your code) say
> explicitly 'Acked' or 'Reviewed-by'

ACK.
I'll remove these names and resend.  Thanks.

> > +#define DEBUG
> That should not be the default case.

RFC.
If we do not add ignore_loglevel to the command line, the acpi earlycon will be mute just as what you want.
Do you really want this to be:
#undef DEBUG
If we do this, all pr_debug invocations in this file will be empty in compilation stage and are there any other means for us to view the output of ACPI earlycon without recompiling?

> > +DECLARE_BITMAP(acpi_early_flags, MAX_ACPI_DBG_PORTS);
> static?

ACK.
I'll do the modification.

> > +int acpi_early_enabled;
> __read_mostly and you could also make it a bool.

NAK.
I think this variable will be read only once and written up to 16 times so __read_mostly is not required.
I'll check and add __init and __initdata for this patch.

> > +	set_bit(port, acpi_early_flags);
> > +	if (keep)
> > +		set_bit(port+MAX_ACPI_DBG_PORTS, acpi_early_flags);
> Huh? The bitmap is up to MAX_ACPI_DB_PORTS, but here you offset it past
> that? Why?

ACK.
It's my mistake.  The size of the bitmap should be "MAX_ACPI_DBG_PORTS<<1 or MAX_ACPI_DBG_PORTS*2".
The reason is:
I think MAX_ACPI_DBG_PORTS=4 is enough in this case.
Since the systems running Linux are 32/64 bit architectures, using 2 bitmaps will be waste.
As the systems are at least 32 bit, the MAX_ACPI_DB_PORTS is defined as 16 to make full use of the bitmap.

> > +	if (!acpi_early_console_enabled(info->port_index))
> > +		return 0;
> Not -ENODEV?

NAK.
This is to support "MULTIPLE DBG2 debug ports".

** MULTIPLE DBGP table versions and MULTIPLE DBG2 debug ports support **
The whole patch takes ENODEV as the semantics of "table not exist or table version not supported" in PROBE/START stage so that we can obtain the ability of probing Microsoft's future tables in the order from DBGn, ..., DBG2, DBGP.
We should not return here as users may pass the following command line:
earlyprintk=acpi2,keep
to let the first 2 debug ports mute, but take the 3rd as a Linux earlycon.

> > +	while (((unsigned long)entry) + sizeof(struct acpi_dbg2_device) <
> > +	       tbl_end) {
> Just make it one line. Ignore the 80 characters limit here.

ACK.
I'll try to implement this within 80 characters.

> > +		if (!max_entries || count++ < max_entries) {
> How about you just make this 'count'
> > +			pr_debug("early: DBG2 PROBE - console %d(%04x:%04x).\n",
> > +				 count-1,
> > +				 entry->port_type, entry->port_subtype);
> > +			devinfo.port_index = (u8)count-1;
> Then you don't this 'count -1'
> and then do
> 		count++ here?

ACK.
It's my mistake, the previous version uses port_index=1 as the first debug port, but this version takes 0 as the first port.

> > +			acpi_early_console_start(&devinfo);
> no check of the return value to see whether you should return immediately?

NAK.
See " MULTIPLE DBGP tables and MULTIPLE DBG2 debug ports support" above.

> > +	acpi_early_console_start(&devinfo);
> how about 'return acpi_early_console_start(..)'

NAK.
See " MULTIPLE DBGP tables and MULTIPLE DBG2 debug ports support" above.

> > +	if (acpi_table_parse(ACPI_SIG_DBG2, acpi_parse_dbg2) != 0)
> > +		acpi_table_parse(ACPI_SIG_DBGP, acpi_parse_dbgp);

RFC.
This is to support "MULTIPLE DBGP table versions".


^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH v5 2/2] ACPI: Add Intel MID SPI early console support.
  2012-10-09 17:06   ` Konrad Rzeszutek Wilk
@ 2012-10-10  1:33     ` Zheng, Lv
  2012-10-10  3:10     ` Zheng, Lv
  1 sibling, 0 replies; 26+ messages in thread
From: Zheng, Lv @ 2012-10-10  1:33 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Brown, Len, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Tang, Feng, linux-kernel, linux-acpi, x86,
	platform-driver-x86

> >   earlyprintk=acpi
> .. or earlyprintk=mrst
> ?

ACK.
The two launchers are all workable for MID_SPI.  I'll add more comments and resend this patch.  Thanks


^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH v5 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2012-10-09 17:02   ` Konrad Rzeszutek Wilk
  2012-10-10  1:31     ` Zheng, Lv
@ 2012-10-10  1:40     ` Zheng, Lv
  1 sibling, 0 replies; 26+ messages in thread
From: Zheng, Lv @ 2012-10-10  1:40 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Brown, Len, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Tang, Feng, linux-kernel, linux-acpi, x86,
	platform-driver-x86

> > +int __init acpi_early_console_keep(struct acpi_debug_port *info)
> 
> Why not make it 'bool' like the other (acpi_early_console_enabled)?

NAK.
"keep" is "int" in "setup_early_printk".

Best regards/Lv Zheng

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH v5 2/2] ACPI: Add Intel MID SPI early console support.
  2012-10-09 17:06   ` Konrad Rzeszutek Wilk
  2012-10-10  1:33     ` Zheng, Lv
@ 2012-10-10  3:10     ` Zheng, Lv
  1 sibling, 0 replies; 26+ messages in thread
From: Zheng, Lv @ 2012-10-10  3:10 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Brown, Len, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Tang, Feng, linux-kernel, linux-acpi, x86,
	platform-driver-x86

> > +#ifdef CONFIG_EARLY_PRINTK_INTEL_MID_SPI
> > +	if (info->port_type == ACPI_DBG2_SERIAL_PORT
> > +	    && info->port_subtype == ACPI_DBG2_INTEL_MID_SPI
> > +	    && info->register_count > 0) {
> Is it ever going to be zero?

NAK.
No register base definition (buggy BIOS?) is meaningless for ACPI launched MID_SPI earlycon.

Thanks and best regards/Lv Zheng

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2012-09-28  2:39 ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Lv Zheng
                     ` (3 preceding siblings ...)
  2012-09-28  6:36   ` [RESEND PATCH " H. Peter Anvin
@ 2012-10-10  3:23   ` Lv Zheng
  2012-10-10 14:10     ` Konrad Rzeszutek Wilk
  2012-10-10 17:44     ` Matthew Garrett
  2012-10-10  3:23   ` [PATCH v6 2/2] ACPI: Add Intel MID SPI early console support Lv Zheng
  5 siblings, 2 replies; 26+ messages in thread
From: Lv Zheng @ 2012-10-10  3:23 UTC (permalink / raw)
  To: Len Brown, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Feng Tang
  Cc: linux-kernel, linux-acpi, x86, platform-driver-x86, Lv Zheng

Microsoft Debug Port Table (DBGP or DBG2) is used by the Windows SoC
platforms to describe their debugging facilities.
DBGP: http://msdn.microsoft.com/en-us/windows/hardware/hh134821
DBG2: http://msdn.microsoft.com/en-us/library/windows/hardware/hh673515

This patch enables the DBGP/DBG2 debug ports as Linux early console
launcher.  Individual early console drivers are also needed to get the
early kernel messages dumped on the consoles.  For example, to use the
SPI UART early console for the Low Power Intel Architecture (LPIA)
platforms, you need to enable the following kernel configurations:
  CONFIG_EARLY_PRINTK_ACPI=y
  CONFIG_EARLY_PRINTK_INTEL_MID_SPI=y
Then you need to append the following kernel parameter to the kernel
command line in your the boot loader configuration file:
  earlyprintk=acpi

There is a dilemma in designing this patch set.  Let me describe it in
details.
There should be three steps to enable an early console for an operating
system:
1. Probe: In this stage, the Linux kernel can detect the early consoles
          and the base address of their register block can be determined.
          This can be done by parsing the descriptors in the ACPI DBGP/DBG2
          tables.  Note that acpi_table_init() must be called before
          parsing.
2. Setup: In this stage, the Linux kernel can apply user specified
          configuration options (ex. baudrate of serial ports) for the
          early consoles.  This is done by parsing the early parameters
          passed to the kernel from the boot loaders.  Note that
          parse_early_params() is called very early to allow parameters to
          be passed to other kernel subsystems.
3. Start: In this stage, the Linux kernel can make the consoles ready to
          output logs.  Since the early consoles are always used for the
          kernel boot up debugging, this must be done as early as possible
          to arm the kernel with the highest testability for other kernel
          subsystems.  Note that, this stage happens when the
          register_console() is called.
The preferred sequence for the above steps is:
   +-----------------+    +-------------------+    +--------------------+
   | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-----------------+    +-------------------+    +--------------------+
But unfortunately, in the current x86 implementation, early parameters and
early printk initialization are called before acpi_table_init() which
depends on the early memory mapping facility.
There are some choices for me to design this patch set:
1. Invoking acpi_table_init() before parse_early_param() to maintain the
   sequence:
   +-----------------+    +-------------------+    +--------------------+
   | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-----------------+    +-------------------+    +--------------------+
   This requires other subsystem maintainers' review to ensure no
   regressions will be introduced.  At the first glance, I found there
   might be problems for the EFI subsystsm:
   The EFI boot services and runtime services are mixed up in the x86
   specific initialization process before the ACPI table initialization.
   Things are much worse that you even cannot disable the runtime services
   while still allow the boot services codes to be executed in the kernel
   compilation stage.  Enabling the early consoles after the ACPI table
   initialization will make it difficult to debug the runtime BIOS bugs.
   If any progress is made to the kernel boot sequences, please let me
   know.  I'll be willing to redesign the ACPI DBGP/DBG2 console probing
   facility.  You can reach me at <lv.zheng@intel.com> and
   <zetalog@gmail.com>.
2. Modifying the above sequece to make it look like:
   +-------------------+    +-----------------+    +--------------------+
   | EARLY_PARAM SETUP | -> | ACPI DBGP PROBE | -> | EARLY_RPINTK START |
   +-------------------+    +-----------------+    +--------------------+
   Early consoles started in this style will lose part of the testability
   in the kernel boot up sequence.  If the system does not crash very
   early, developers still can see the bufferred kernel outputs when the
   register_console() is called.
   Current early console implementations need to be modified to be
   compatible with this design.  The original codes need to be split up
   into tow parts:
   1. Detecting hardware.  This part can be called in the PROBE stage.
   2. Applying user parameters.  This part can be called in the SETUP
      stage.
   Individual early console drver maintainers need to be involved to avoid
   regressions that might occur if we do things in this way.  And the
   maintainers can offer better tests than I can do.
3. Introducing a brand new debugging facility that does not relate to the
   current early console implementation to allow the early consoles to be
   automatically detected.
   +-------------------+    +--------------------+
   | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-------------------+    +--------------------+
   +-----------------+    +--------------------+
   | ACPI DBGP PROBE | -> | EARLY_RPINTK START |
   +-----------------+    +--------------------+
   Early consoles started in this style will lose part of the testability
   in the kernel boot up sequence.  If the system does not crash very
   early, developers still can see the bufferred kernel outputs when the
   register_console() is called.
   Comparing to the solution 2, we can notice that the user configuration
   can not be applied to the registered early consoles in this way as the
   acpi_table_init() is still called after the parse_early_param().
   Instead, the early consoles should derive the hardware settings used in
   the BIOS/bootloaders.
   This is what the patch set has done to enable this new usage model.
   It is known as "ACPI early console launcher mode".
   As a launcher, ACPI DBGP will not actually output kernel messages
   without the real early console drivers, that's why the
   CONFIG_EARLY_PRINTK_INTEL_MID_SPI still need to be enabled along with
   the CONFIG_EARLY_PRINTK_ACPI.
   In order to disable this facility by default and enable it at runtime,
   an kernel parameter "earlyprintk=acpi" is introduced.  This makes the
   actual sequence look like:
   +-------------------+    +--------------------+
   | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
   +-------------------+    +....................+
                            | ACPI DBGP LAUNCH   | ->
                            +--------------------+
      +-----------------+    +--------------------+
   -> | ACPI DBGP PROBE | -> | EARLY_PRINTK START |
      +-----------------+    +--------------------+

Version 1:
 1. Enables single DBG2 debug port support.
Version 2:
 1. Applies Rui's comments.
Version 3:
 1. Applies Len's comments (earlycon should be disabled by default).
 2. Enables single DBG2 debug ports support.
Version 4:
 1. Fixes the CodingStyle issues reported by checkpatch.pl.
 2. Enables single DBGP debug port support.
Version 5:
 1. Enables multiple DBG2 debug ports support.
 2. Applies Konrad's comments (pr_debug should be used in earlycon).
 3. Changes kstrtoul back to simple_strtoul.
Version 6:
 1. Applies Konrad's comments (MAX_ACPI_DBG_PORTS bug and count improvement)
 2. Adds "__init" and "__initdata" to the symbols introduced in this patch.

Known Issues:
1. The simple_strtoul function cannot be replaced by the kstrtoul in
   the x86 specific booting codes.  The kstrtoul will return error on
   strings like "acpi0,keep".  This will leave one CodingStyle issue
   reported by the checkpatch.pl.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
 Documentation/kernel-parameters.txt |    1 +
 arch/x86/Kconfig.debug              |   15 +++
 arch/x86/kernel/acpi/boot.c         |    1 +
 arch/x86/kernel/early_printk.c      |   13 +++
 drivers/acpi/Makefile               |    2 +
 drivers/acpi/early_printk.c         |  172 +++++++++++++++++++++++++++++++++++
 include/linux/acpi.h                |   22 +++++
 7 files changed, 226 insertions(+)
 create mode 100644 drivers/acpi/early_printk.c

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index ad7e2e5..f656765 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -763,6 +763,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			earlyprintk=serial[,ttySn[,baudrate]]
 			earlyprintk=ttySn[,baudrate]
 			earlyprintk=dbgp[debugController#]
+			earlyprintk=acpi[debugController#]
 
 			Append ",keep" to not disable it when the real console
 			takes over.
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index b322f12..5778082 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -59,6 +59,21 @@ config EARLY_PRINTK_DBGP
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash. You need usb debug device.
 
+config EARLY_PRINTK_ACPI
+	bool "Early printk launcher via ACPI debug port tables"
+	depends on EARLY_PRINTK && ACPI
+	---help---
+	  Write kernel log output directly into the debug ports described
+	  in the ACPI tables known as DBGP and DBG2.
+
+	  To enable such debugging facilities, you need to enable this
+	  configuration option and append the "earlyprintk=acpi" kernel
+	  parameter through the boot loaders.  Please refer the
+	  "Documentation/kernel-parameters.txt" for details.  Since this
+	  is an early console launcher, you still need to enable actual
+	  early console drivers that are suitable for your platform.
+	  If in doubt, say "N".
+
 config DEBUG_STACKOVERFLOW
 	bool "Check for stack overflows"
 	depends on DEBUG_KERNEL
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index b2297e5..cc10ea5 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1518,6 +1518,7 @@ void __init acpi_boot_table_init(void)
 		return;
 	}
 
+	acpi_early_console_probe();
 	acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
 
 	/*
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 9b9f18b..bf5b596 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -200,6 +200,15 @@ static inline void early_console_register(struct console *con, int keep_early)
 	register_console(early_console);
 }
 
+#ifdef CONFIG_EARLY_PRINTK_ACPI
+#include <linux/acpi.h>
+
+int __init __acpi_early_console_start(struct acpi_debug_port *info)
+{
+	return 0;
+}
+#endif
+
 static int __init setup_early_printk(char *buf)
 {
 	int keep;
@@ -236,6 +245,10 @@ static int __init setup_early_printk(char *buf)
 		if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4))
 			early_console_register(&early_dbgp_console, keep);
 #endif
+#ifdef CONFIG_EARLY_PRINTK_ACPI
+		if (!strncmp(buf, "acpi", 4))
+			acpi_early_console_launch(buf + 4, keep);
+#endif
 #ifdef CONFIG_HVC_XEN
 		if (!strncmp(buf, "xen", 3))
 			early_console_register(&xenboot_console, keep);
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 47199e2..99dbd64 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -46,6 +46,8 @@ ifdef CONFIG_ACPI_VIDEO
 acpi-y				+= video_detect.o
 endif
 
+obj-$(CONFIG_EARLY_PRINTK_ACPI)	+= early_printk.o
+
 # These are (potentially) separate modules
 obj-$(CONFIG_ACPI_AC) 		+= ac.o
 obj-$(CONFIG_ACPI_BUTTON)	+= button.o
diff --git a/drivers/acpi/early_printk.c b/drivers/acpi/early_printk.c
new file mode 100644
index 0000000..32b3c13
--- /dev/null
+++ b/drivers/acpi/early_printk.c
@@ -0,0 +1,172 @@
+/*
+ * acpi/early_printk.c - ACPI Boot-Time Debug Ports
+ *
+ * Copyright (c) 2012, Intel Corporation
+ * Author: Lv Zheng <lv.zheng@intel.com>
+ *
+ * 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 the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#define DEBUG
+#define pr_fmt(fmt)	"ACPI: " KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/acpi.h>
+#include <linux/bitmap.h>
+#include <linux/bootmem.h>
+
+#define MAX_ACPI_DBG_PORTS	16
+
+static __initdata DECLARE_BITMAP(acpi_early_flags, MAX_ACPI_DBG_PORTS*2);
+static __initdata bool acpi_early_enabled;
+
+static int __init acpi_early_console_enable(u8 port, int keep)
+{
+	if (port >= MAX_ACPI_DBG_PORTS)
+		return -ENODEV;
+
+	set_bit(port, acpi_early_flags);
+	if (keep)
+		set_bit(port+MAX_ACPI_DBG_PORTS, acpi_early_flags);
+	acpi_early_enabled = true;
+
+	pr_debug("DBGx LAUNCH - console %d.\n", port);
+
+	return 0;
+}
+
+static bool __init acpi_early_console_enabled(u8 port)
+{
+	BUG_ON(port >= MAX_ACPI_DBG_PORTS);
+	return test_bit(port, acpi_early_flags);
+}
+
+int __init acpi_early_console_keep(struct acpi_debug_port *info)
+{
+	BUG_ON(!info || info->port_index >= MAX_ACPI_DBG_PORTS);
+	return test_bit(info->port_index+MAX_ACPI_DBG_PORTS, acpi_early_flags);
+}
+
+static int __init acpi_early_console_start(struct acpi_debug_port *info)
+{
+	if (!acpi_early_console_enabled(info->port_index))
+		return 0;
+
+	pr_debug("DBGx START - console %d(%04x:%04x).\n",
+		 info->port_index, info->port_type, info->port_subtype);
+	__acpi_early_console_start(info);
+
+	return 0;
+}
+
+static int __init acpi_parse_dbg2(struct acpi_table_header *table)
+{
+	struct acpi_table_dbg2 *dbg2;
+	struct acpi_dbg2_device *entry;
+	void *tbl_end;
+	u32 count = 0;
+	u32 max_entries;
+	struct acpi_debug_port devinfo;
+
+	dbg2 = (struct acpi_table_dbg2 *)table;
+	if (!dbg2) {
+		pr_debug("DBG2 not present.\n");
+		return -ENODEV;
+	}
+
+	tbl_end = (void *)table + table->length;
+
+	entry = (struct acpi_dbg2_device *)((void *)dbg2 + dbg2->info_offset);
+	max_entries = min_t(u32, MAX_ACPI_DBG_PORTS, dbg2->info_count);
+
+	while (((void *)entry) + sizeof(struct acpi_dbg2_device) < tbl_end) {
+		if (entry->revision != 0) {
+			pr_debug("DBG2 revision %d not supported.\n",
+				 entry->revision);
+			return -ENODEV;
+		}
+		if (count < max_entries) {
+			pr_debug("DBG2 PROBE - console %d(%04x:%04x).\n",
+				 count, entry->port_type, entry->port_subtype);
+
+			devinfo.port_index = (u8)count;
+			devinfo.port_type = entry->port_type;
+			devinfo.port_subtype = entry->port_subtype;
+			devinfo.register_count = entry->register_count;
+			devinfo.registers = (struct acpi_generic_address *)
+			    ((void *)entry + entry->base_address_offset);
+			devinfo.namepath_length = entry->namepath_length;
+			devinfo.namepath = (char *)
+			    ((void *)entry + entry->namepath_offset);
+			devinfo.oem_data_length = entry->oem_data_length;
+			devinfo.oem_data = (u8 *)
+			    ((void *)entry + entry->oem_data_offset);
+
+			acpi_early_console_start(&devinfo);
+			count++;
+		}
+
+		entry = (struct acpi_dbg2_device *)
+			((void *)entry + entry->length);
+	}
+
+	return 0;
+}
+
+static int __init acpi_parse_dbgp(struct acpi_table_header *table)
+{
+	struct acpi_table_dbgp *dbgp;
+	struct acpi_debug_port devinfo;
+
+	dbgp = (struct acpi_table_dbgp *)table;
+	if (!dbgp) {
+		pr_debug("DBGP not present.\n");
+		return -ENODEV;
+	}
+
+	pr_debug("DBGP PROBE - console (%04x).\n", dbgp->type);
+
+	devinfo.port_index = 0;
+	devinfo.port_type = ACPI_DBG2_SERIAL_PORT;
+	devinfo.port_subtype = dbgp->type;
+	devinfo.register_count = 1;
+	devinfo.registers = (struct acpi_generic_address *)&dbgp->debug_port;
+	devinfo.namepath_length = 0;
+	devinfo.namepath = NULL;
+	devinfo.oem_data_length = 0;
+	devinfo.oem_data = NULL;
+
+	acpi_early_console_start(&devinfo);
+
+	return 0;
+}
+
+int __init acpi_early_console_probe(void)
+{
+	if (!acpi_early_enabled)
+		return -EINVAL;
+
+	if (acpi_table_parse(ACPI_SIG_DBG2, acpi_parse_dbg2) != 0)
+		acpi_table_parse(ACPI_SIG_DBGP, acpi_parse_dbgp);
+
+	return 0;
+}
+
+int __init acpi_early_console_launch(char *s, int keep)
+{
+	char *e;
+	unsigned long port = 0;
+
+	if (*s)
+		port = simple_strtoul(s, &e, 10);
+
+	return acpi_early_console_enable(port, keep);
+}
+
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 4f2a762..641366c 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -430,4 +430,26 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state,
 #define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
 #endif
 
+#ifdef CONFIG_EARLY_PRINTK_ACPI
+struct acpi_debug_port {
+	u8 port_index;
+	u16 port_type;
+	u16 port_subtype;
+	u16 register_count;
+	struct acpi_generic_address *registers;
+	u16 namepath_length;
+	char *namepath;
+	u16 oem_data_length;
+	u8 *oem_data;
+};
+
+int __init acpi_early_console_keep(struct acpi_debug_port *info);
+int __init acpi_early_console_launch(char *s, int keep);
+int __init acpi_early_console_probe(void);
+/* This interface is arch specific. */
+int __init __acpi_early_console_start(struct acpi_debug_port *info);
+#else
+static int acpi_early_console_probe(void) { return 0; }
+#endif
+
 #endif	/*_LINUX_ACPI_H*/
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v6 2/2] ACPI: Add Intel MID SPI early console support.
  2012-09-28  2:39 ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Lv Zheng
                     ` (4 preceding siblings ...)
  2012-10-10  3:23   ` [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
@ 2012-10-10  3:23   ` Lv Zheng
  5 siblings, 0 replies; 26+ messages in thread
From: Lv Zheng @ 2012-10-10  3:23 UTC (permalink / raw)
  To: Len Brown, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Feng Tang
  Cc: linux-kernel, linux-acpi, x86, platform-driver-x86, Lv Zheng

DesignWare SPI UART is used as one of the debug ports on Low Power Intel
Architecture (LPIA) platforms.  This patch is introduced to support this
debugging console reported by ACPI DBGP/DBG2.  The original MID SPI
early console stuff is also refined to co-exist with the new ACPI usage
model.

There are two alternatives to use this facility on LPIA platforms:
1. Launch by normal earlycon (on MEDFIELD platforms):
   Enable the following kernel configurations:
     CONFIG_EARLY_PRINTK_INTEL_MID=y
   Pass the following kernel parameter to the kernel:
     earlyprintk=mrst
2. Launch by ACPI DBG2 earlycon (on CLOVERVIEW platforms):
   Enable the following kernel configurations:
     CONFIG_EARLY_PRINTK_ACPI=y
     CONFIG_EARLY_PRINTK_INTEL_MID_SPI=y
   Pass the following kernel parameter to the kernel:
     earlyprintk=acpi

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
---
 Documentation/kernel-parameters.txt        |    1 +
 arch/x86/Kconfig.debug                     |   23 +++
 arch/x86/include/asm/mrst.h                |    2 +-
 arch/x86/kernel/early_printk.c             |   12 +-
 arch/x86/platform/mrst/early_printk_mrst.c |  186 +----------------------
 drivers/platform/x86/Makefile              |    2 +
 drivers/platform/x86/early/Makefile        |    5 +
 drivers/platform/x86/early/intel_mid_spi.c |  220 ++++++++++++++++++++++++++++
 include/acpi/actbl2.h                      |    1 +
 include/linux/intel_mid_early.h            |   12 ++
 10 files changed, 283 insertions(+), 181 deletions(-)
 create mode 100644 drivers/platform/x86/early/Makefile
 create mode 100644 drivers/platform/x86/early/intel_mid_spi.c
 create mode 100644 include/linux/intel_mid_early.h

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f656765..003ffd9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -762,6 +762,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			earlyprintk=vga
 			earlyprintk=serial[,ttySn[,baudrate]]
 			earlyprintk=ttySn[,baudrate]
+			earlyprintk=mrst
 			earlyprintk=dbgp[debugController#]
 			earlyprintk=acpi[debugController#]
 
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 5778082..4a26e2d 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -43,9 +43,32 @@ config EARLY_PRINTK
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash.
 
+config EARLY_PRINTK_INTEL_MID_SPI
+	bool "Early printk for Intel MID SPI UART port"
+	depends on EARLY_PRINTK
+	---help---
+	  Write kernel log output directly into the MID SPI UART debug port.
+
+	  Intel MID platforms are using DesignWare SPI UART as its debug
+	  console.  This option does not introduce actual early console into
+	  the kernel binary, but is required by a real early console
+	  implementation (EARLY_PRINTK_INTEL_MID or EARLY_PRINTK_ACPI).
+	  You should normally N here unless you need to do kernel booting
+	  development.
+
 config EARLY_PRINTK_INTEL_MID
 	bool "Early printk for Intel MID platform support"
 	depends on EARLY_PRINTK && X86_INTEL_MID
+	select EARLY_PRINTK_INTEL_MID_SPI
+	---help---
+	  Write kernel log output directly into the MID SPI UART debug port.
+
+	  Intel MID platforms are always equipped with SPI debug ports and
+	  USB OTG debug ports. To enable these debugging facilities, you
+	  need to pass "earlyprintk=mrst" parameter to the kernel through
+	  boot loaders.  Please see "Documentation/kernel-parameter.txt" for
+	  details.  You should normally N here unless you need to do kernel
+	  booting development.
 
 config EARLY_PRINTK_DBGP
 	bool "Early printk via EHCI debug port"
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
index fc18bf3..8ab0655 100644
--- a/arch/x86/include/asm/mrst.h
+++ b/arch/x86/include/asm/mrst.h
@@ -12,6 +12,7 @@
 #define _ASM_X86_MRST_H
 
 #include <linux/sfi.h>
+#include <linux/intel_mid_early.h>
 
 extern int pci_mrst_init(void);
 extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
@@ -63,7 +64,6 @@ extern enum mrst_timer_options mrst_timer_options;
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX	8
 
-extern struct console early_mrst_console;
 extern void mrst_early_console_init(void);
 
 extern struct console early_hsu_console;
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index bf5b596..9b5ee96 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -205,6 +205,16 @@ static inline void early_console_register(struct console *con, int keep_early)
 
 int __init __acpi_early_console_start(struct acpi_debug_port *info)
 {
+#ifdef CONFIG_EARLY_PRINTK_INTEL_MID_SPI
+	if (info->port_type == ACPI_DBG2_SERIAL_PORT
+	    && info->port_subtype == ACPI_DBG2_INTEL_MID_SPI
+	    && info->register_count > 0) {
+		mid_spi_early_console_init((u32)(info->registers[0].address));
+		early_console_register(&mid_spi_early_console,
+				       acpi_early_console_keep(info));
+	}
+#endif
+
 	return 0;
 }
 #endif
@@ -256,7 +266,7 @@ static int __init setup_early_printk(char *buf)
 #ifdef CONFIG_EARLY_PRINTK_INTEL_MID
 		if (!strncmp(buf, "mrst", 4)) {
 			mrst_early_console_init();
-			early_console_register(&early_mrst_console, keep);
+			early_console_register(&mid_spi_early_console, keep);
 		}
 
 		if (!strncmp(buf, "hsu", 3)) {
diff --git a/arch/x86/platform/mrst/early_printk_mrst.c b/arch/x86/platform/mrst/early_printk_mrst.c
index 028454f..7afbf18 100644
--- a/arch/x86/platform/mrst/early_printk_mrst.c
+++ b/arch/x86/platform/mrst/early_printk_mrst.c
@@ -29,82 +29,8 @@
 #include <asm/pgtable.h>
 #include <asm/mrst.h>
 
-#define MRST_SPI_TIMEOUT		0x200000
 #define MRST_REGBASE_SPI0		0xff128000
 #define MRST_REGBASE_SPI1		0xff128400
-#define MRST_CLK_SPI0_REG		0xff11d86c
-
-/* Bit fields in CTRLR0 */
-#define SPI_DFS_OFFSET			0
-
-#define SPI_FRF_OFFSET			4
-#define SPI_FRF_SPI			0x0
-#define SPI_FRF_SSP			0x1
-#define SPI_FRF_MICROWIRE		0x2
-#define SPI_FRF_RESV			0x3
-
-#define SPI_MODE_OFFSET			6
-#define SPI_SCPH_OFFSET			6
-#define SPI_SCOL_OFFSET			7
-#define SPI_TMOD_OFFSET			8
-#define	SPI_TMOD_TR			0x0		/* xmit & recv */
-#define SPI_TMOD_TO			0x1		/* xmit only */
-#define SPI_TMOD_RO			0x2		/* recv only */
-#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
-
-#define SPI_SLVOE_OFFSET		10
-#define SPI_SRL_OFFSET			11
-#define SPI_CFS_OFFSET			12
-
-/* Bit fields in SR, 7 bits */
-#define SR_MASK				0x7f		/* cover 7 bits */
-#define SR_BUSY				(1 << 0)
-#define SR_TF_NOT_FULL			(1 << 1)
-#define SR_TF_EMPT			(1 << 2)
-#define SR_RF_NOT_EMPT			(1 << 3)
-#define SR_RF_FULL			(1 << 4)
-#define SR_TX_ERR			(1 << 5)
-#define SR_DCOL				(1 << 6)
-
-struct dw_spi_reg {
-	u32	ctrl0;
-	u32	ctrl1;
-	u32	ssienr;
-	u32	mwcr;
-	u32	ser;
-	u32	baudr;
-	u32	txfltr;
-	u32	rxfltr;
-	u32	txflr;
-	u32	rxflr;
-	u32	sr;
-	u32	imr;
-	u32	isr;
-	u32	risr;
-	u32	txoicr;
-	u32	rxoicr;
-	u32	rxuicr;
-	u32	msticr;
-	u32	icr;
-	u32	dmacr;
-	u32	dmatdlr;
-	u32	dmardlr;
-	u32	idr;
-	u32	version;
-
-	/* Currently operates as 32 bits, though only the low 16 bits matter */
-	u32	dr;
-} __packed;
-
-#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
-#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
-
-/* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */
-static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0;
-
-static u32 *pclk_spi0;
-/* Always contains an accessible address, start with 0 */
-static struct dw_spi_reg *pspi;
 
 static struct kmsg_dumper dw_dumper;
 static int dumper_registered;
@@ -116,77 +42,21 @@ static void dw_kmsg_dump(struct kmsg_dumper *dumper,
 	size_t len;
 
 	/* When run to this, we'd better re-init the HW */
-	mrst_early_console_init();
+	mid_spi_early_console_reset();
 
 	while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len))
-		early_mrst_console.write(&early_mrst_console, line, len);
-}
-
-/* Set the ratio rate to 115200, 8n1, IRQ disabled */
-static void max3110_write_config(void)
-{
-	u16 config;
-
-	config = 0xc001;
-	dw_writel(pspi, dr, config);
-}
-
-/* Translate char to a eligible word and send to max3110 */
-static void max3110_write_data(char c)
-{
-	u16 data;
-
-	data = 0x8000 | c;
-	dw_writel(pspi, dr, data);
+		mid_spi_early_console.write(&mid_spi_early_console, line, len);
 }
 
 void mrst_early_console_init(void)
 {
-	u32 ctrlr0 = 0;
-	u32 spi0_cdiv;
-	u32 freq; /* Freqency info only need be searched once */
-
-	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
-	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
-							MRST_CLK_SPI0_REG);
-	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
-	freq = 100000000 / (spi0_cdiv + 1);
+	/* Default use SPI0 register for mrst */
+	unsigned long spi_paddr = MRST_REGBASE_SPI0;
 
+	/* Detect Penwell and use SPI1 */
 	if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL)
-		mrst_spi_paddr = MRST_REGBASE_SPI1;
-
-	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
-						mrst_spi_paddr);
-
-	/* Disable SPI controller */
-	dw_writel(pspi, ssienr, 0);
-
-	/* Set control param, 8 bits, transmit only mode */
-	ctrlr0 = dw_readl(pspi, ctrl0);
-
-	ctrlr0 &= 0xfcc0;
-	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
-		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
-	dw_writel(pspi, ctrl0, ctrlr0);
-
-	/*
-	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
-	 * calculate the clk dividor to make the clock a little slower
-	 * than real baud rate.
-	 */
-	dw_writel(pspi, baudr, freq/100000);
-
-	/* Disable all INT for early phase */
-	dw_writel(pspi, imr, 0x0);
-
-	/* Set the cs to spi-uart */
-	dw_writel(pspi, ser, 0x2);
-
-	/* Enable the HW, the last step for HW init */
-	dw_writel(pspi, ssienr, 0x1);
-
-	/* Set the default configuration */
-	max3110_write_config();
+		spi_paddr = MRST_REGBASE_SPI1;
+	mid_spi_early_console_init(spi_paddr);
 
 	/* Register the kmsg dumper */
 	if (!dumper_registered) {
@@ -196,48 +66,6 @@ void mrst_early_console_init(void)
 	}
 }
 
-/* Slave select should be called in the read/write function */
-static void early_mrst_spi_putc(char c)
-{
-	unsigned int timeout;
-	u32 sr;
-
-	timeout = MRST_SPI_TIMEOUT;
-	/* Early putc needs to make sure the TX FIFO is not full */
-	while (--timeout) {
-		sr = dw_readl(pspi, sr);
-		if (!(sr & SR_TF_NOT_FULL))
-			cpu_relax();
-		else
-			break;
-	}
-
-	if (!timeout)
-		pr_warning("MRST earlycon: timed out\n");
-	else
-		max3110_write_data(c);
-}
-
-/* Early SPI only uses polling mode */
-static void early_mrst_spi_write(struct console *con, const char *str, unsigned n)
-{
-	int i;
-
-	for (i = 0; i < n && *str; i++) {
-		if (*str == '\n')
-			early_mrst_spi_putc('\r');
-		early_mrst_spi_putc(*str);
-		str++;
-	}
-}
-
-struct console early_mrst_console = {
-	.name =		"earlymrst",
-	.write =	early_mrst_spi_write,
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
-};
-
 /*
  * Following is the early console based on Medfield HSU (High
  * Speed UART) device.
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index bf7e4f9..6e4ff46 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -50,3 +50,5 @@ obj-$(CONFIG_INTEL_MID_POWER_BUTTON)	+= intel_mid_powerbtn.o
 obj-$(CONFIG_INTEL_OAKTRAIL)	+= intel_oaktrail.o
 obj-$(CONFIG_SAMSUNG_Q10)	+= samsung-q10.o
 obj-$(CONFIG_APPLE_GMUX)	+= apple-gmux.o
+
+obj-$(CONFIG_EARLY_PRINTK)	+= early/
diff --git a/drivers/platform/x86/early/Makefile b/drivers/platform/x86/early/Makefile
new file mode 100644
index 0000000..5d9408c
--- /dev/null
+++ b/drivers/platform/x86/early/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for linux/drivers/platform/x86/early
+# x86 Platform-Specific Early Printk Support
+#
+obj-$(CONFIG_EARLY_PRINTK_INTEL_MID_SPI)	+= intel_mid_spi.o
diff --git a/drivers/platform/x86/early/intel_mid_spi.c b/drivers/platform/x86/early/intel_mid_spi.c
new file mode 100644
index 0000000..fa5a1a2
--- /dev/null
+++ b/drivers/platform/x86/early/intel_mid_spi.c
@@ -0,0 +1,220 @@
+/*
+ * intel_mid_spi.c - SPI UART early consoles for Intel MID platforms
+ *
+ * Copyright (c) 2008-2012, 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 the Free Software Foundation; version 2
+ * of the License.
+ */
+
+/*
+ * This file is originally implemented by Feng Tang <feng.tang@intel.com>.
+ * It is moved here to co-exist with CONFIG_EARLY_PRINTK_ACPI.
+ * Any questions you should contact the original author.
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/serial_mfd.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/intel_mid_early.h>
+#include <asm/fixmap.h>
+
+#define DW_SPI_TIMEOUT			0x200000
+#define DW_SPI0_CLK_REG			0xff11d86c
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET			0
+
+#define SPI_FRF_OFFSET			4
+#define SPI_FRF_SPI			0x0
+#define SPI_FRF_SSP			0x1
+#define SPI_FRF_MICROWIRE		0x2
+#define SPI_FRF_RESV			0x3
+
+#define SPI_MODE_OFFSET			6
+#define SPI_SCPH_OFFSET			6
+#define SPI_SCOL_OFFSET			7
+#define SPI_TMOD_OFFSET			8
+#define	SPI_TMOD_TR			0x0		/* xmit & recv */
+#define SPI_TMOD_TO			0x1		/* xmit only */
+#define SPI_TMOD_RO			0x2		/* recv only */
+#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET		10
+#define SPI_SRL_OFFSET			11
+#define SPI_CFS_OFFSET			12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK				0x7f		/* cover 7 bits */
+#define SR_BUSY				(1 << 0)
+#define SR_TF_NOT_FULL			(1 << 1)
+#define SR_TF_EMPT			(1 << 2)
+#define SR_RF_NOT_EMPT			(1 << 3)
+#define SR_RF_FULL			(1 << 4)
+#define SR_TX_ERR			(1 << 5)
+#define SR_DCOL				(1 << 6)
+
+struct dw_spi_reg {
+	u32	ctrl0;
+	u32	ctrl1;
+	u32	ssienr;
+	u32	mwcr;
+	u32	ser;
+	u32	baudr;
+	u32	txfltr;
+	u32	rxfltr;
+	u32	txflr;
+	u32	rxflr;
+	u32	sr;
+	u32	imr;
+	u32	isr;
+	u32	risr;
+	u32	txoicr;
+	u32	rxoicr;
+	u32	rxuicr;
+	u32	msticr;
+	u32	icr;
+	u32	dmacr;
+	u32	dmatdlr;
+	u32	dmardlr;
+	u32	idr;
+	u32	version;
+
+	/* Currently operates as 32 bits, though only the low 16 bits matter */
+	u32	dr;
+} __packed;
+
+#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
+#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
+
+static u32 *pclk_spi0;
+/* Always contains an accessible address, start with 0 */
+static struct dw_spi_reg *pspi;
+static int dw_spi_initialized;
+static u32 dw_spi_regbase;
+
+/* Translate char to a eligible word and send to max3110 */
+static void max3110_write_data(char c)
+{
+	u16 data;
+
+	data = 0x8000 | c;
+	dw_writel(pspi, dr, data);
+}
+
+/* Set the ratio rate to 115200, 8n1, IRQ disabled */
+static void max3110_write_config(void)
+{
+	u16 config;
+
+	config = 0xc001;
+	dw_writel(pspi, dr, config);
+}
+
+int mid_spi_early_console_reset(void)
+{
+	u32 ctrlr0 = 0;
+	u32 spi0_cdiv;
+	u32 freq; /* Freqency info only need be searched once */
+
+	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
+	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+						      DW_SPI0_CLK_REG);
+	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
+	freq = 100000000 / (spi0_cdiv + 1);
+
+	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+						 dw_spi_regbase);
+
+	/* Disable SPI controller */
+	dw_writel(pspi, ssienr, 0);
+
+	/* Set control param, 8 bits, transmit only mode */
+	ctrlr0 = dw_readl(pspi, ctrl0);
+
+	ctrlr0 &= 0xfcc0;
+	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
+		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
+	dw_writel(pspi, ctrl0, ctrlr0);
+
+	/*
+	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
+	 * calculate the clk dividor to make the clock a little slower
+	 * than real baud rate.
+	 */
+	dw_writel(pspi, baudr, freq/100000);
+
+	/* Disable all INT for early phase */
+	dw_writel(pspi, imr, 0x0);
+
+	/* Set the cs to spi-uart */
+	dw_writel(pspi, ser, 0x2);
+
+	/* Enable the HW, the last step for HW init */
+	dw_writel(pspi, ssienr, 0x1);
+
+	/* Set the default configuration */
+	max3110_write_config();
+
+	return 0;
+}
+EXPORT_SYMBOL(mid_spi_early_console_reset);
+
+/* Slave select should be called in the read/write function */
+static void dw_early_spi_putc(char c)
+{
+	unsigned int timeout;
+	u32 sr;
+
+	timeout = DW_SPI_TIMEOUT;
+	/* Early putc needs to make sure the TX FIFO is not full */
+	while (--timeout) {
+		sr = dw_readl(pspi, sr);
+		if (!(sr & SR_TF_NOT_FULL))
+			cpu_relax();
+		else
+			break;
+	}
+
+	if (!timeout)
+		pr_warn("mid-spi-early: timed out\n");
+	else
+		max3110_write_data(c);
+}
+
+/* Early SPI only uses polling mode */
+static void dw_early_spi_write(struct console *con,
+			       const char *str, unsigned n)
+{
+	int i;
+
+	for (i = 0; i < n && *str; i++) {
+		if (*str == '\n')
+			dw_early_spi_putc('\r');
+		dw_early_spi_putc(*str);
+		str++;
+	}
+}
+
+struct console mid_spi_early_console = {
+	.name =		"earlymidspi",
+	.write =	dw_early_spi_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
+void __init mid_spi_early_console_init(u32 spi_paddr)
+{
+	if (dw_spi_initialized)
+		return;
+	dw_spi_regbase = spi_paddr;
+	mid_spi_early_console_reset();
+	dw_spi_initialized = 1;
+}
+
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index 1b2b356..ffa9d62 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -341,6 +341,7 @@ struct acpi_dbg2_device {
 
 #define ACPI_DBG2_16550_COMPATIBLE  0x0000
 #define ACPI_DBG2_16550_SUBSET      0x0001
+#define ACPI_DBG2_INTEL_MID_SPI     0x0002
 
 #define ACPI_DBG2_1394_STANDARD     0x0000
 
diff --git a/include/linux/intel_mid_early.h b/include/linux/intel_mid_early.h
new file mode 100644
index 0000000..edba232
--- /dev/null
+++ b/include/linux/intel_mid_early.h
@@ -0,0 +1,12 @@
+#ifndef LINUX_INTEL_MID_EARLY_H
+#define LINUX_INTEL_MID_EARLY_H
+
+#include <linux/console.h>
+
+extern struct console mid_spi_early_console;
+
+extern void mid_spi_early_console_init(u32 spi_paddr);
+extern int mid_spi_early_console_reset(void);
+
+#endif /* LINUX_INTEL_MID_EARLY_H */
+
-- 
1.7.10


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH v5 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2012-10-10  1:31     ` Zheng, Lv
@ 2012-10-10 14:06       ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 26+ messages in thread
From: Konrad Rzeszutek Wilk @ 2012-10-10 14:06 UTC (permalink / raw)
  To: Zheng, Lv
  Cc: Brown, Len, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Tang, Feng, linux-kernel, linux-acpi, x86,
	platform-driver-x86

On Wed, Oct 10, 2012 at 01:31:54AM +0000, Zheng, Lv wrote:
> > > Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> > > Reviewed-by: Len Brown <len.brown@intel.com>
> > > Reviewed-by: Rui Zhang <rui.zhang@intel.com>
> > > Reviewed-by: Ying Huang <ying.huang@intel.com>
> > > Reviewed-by: Konrad Rzeszutek Wilk <konrad@kernel.org>
> > Please don't include that unless I (or other folks looking at your code) say
> > explicitly 'Acked' or 'Reviewed-by'
> 
> ACK.
> I'll remove these names and resend.  Thanks.
> 
> > > +#define DEBUG
> > That should not be the default case.
> 
> RFC.

The title of the patch does not have RFC anymore.. Please put it back
then.

> If we do not add ignore_loglevel to the command line, the acpi earlycon will be mute just as what you want.
> Do you really want this to be:
> #undef DEBUG
> If we do this, all pr_debug invocations in this file will be empty in compilation stage and are there any other means for us to view the output of ACPI earlycon without recompiling?

Correct. By the time you remove the 'RFC' part this should be the
default.
> 
> > > +DECLARE_BITMAP(acpi_early_flags, MAX_ACPI_DBG_PORTS);
> > static?
> 
> ACK.
> I'll do the modification.
> 
> > > +int acpi_early_enabled;
> > __read_mostly and you could also make it a bool.
> 
> NAK.
> I think this variable will be read only once and written up to 16 times so __read_mostly is not required.
> I'll check and add __init and __initdata for this patch.
> 
> > > +	set_bit(port, acpi_early_flags);
> > > +	if (keep)
> > > +		set_bit(port+MAX_ACPI_DBG_PORTS, acpi_early_flags);
> > Huh? The bitmap is up to MAX_ACPI_DB_PORTS, but here you offset it past
> > that? Why?
> 
> ACK.
> It's my mistake.  The size of the bitmap should be "MAX_ACPI_DBG_PORTS<<1 or MAX_ACPI_DBG_PORTS*2".
> The reason is:
> I think MAX_ACPI_DBG_PORTS=4 is enough in this case.
> Since the systems running Linux are 32/64 bit architectures, using 2 bitmaps will be waste.
> As the systems are at least 32 bit, the MAX_ACPI_DB_PORTS is defined as 16 to make full use of the bitmap.

> 
> > > +	if (!acpi_early_console_enabled(info->port_index))
> > > +		return 0;
> > Not -ENODEV?
> 
> NAK.
> This is to support "MULTIPLE DBG2 debug ports".
> 
> ** MULTIPLE DBGP table versions and MULTIPLE DBG2 debug ports support **
> The whole patch takes ENODEV as the semantics of "table not exist or table version not supported" in PROBE/START stage so that we can obtain the ability of probing Microsoft's future tables in the order from DBGn, ..., DBG2, DBGP.
> We should not return here as users may pass the following command line:
> earlyprintk=acpi2,keep
> to let the first 2 debug ports mute, but take the 3rd as a Linux earlycon.

OK? How will this function get called three times then? I thought it
would just get called once?

> 
> > > +	while (((unsigned long)entry) + sizeof(struct acpi_dbg2_device) <
> > > +	       tbl_end) {
> > Just make it one line. Ignore the 80 characters limit here.
> 
> ACK.
> I'll try to implement this within 80 characters.

Well, you don't have to - not for this.
> 
> > > +		if (!max_entries || count++ < max_entries) {
> > How about you just make this 'count'
> > > +			pr_debug("early: DBG2 PROBE - console %d(%04x:%04x).\n",
> > > +				 count-1,
> > > +				 entry->port_type, entry->port_subtype);
> > > +			devinfo.port_index = (u8)count-1;
> > Then you don't this 'count -1'
> > and then do
> > 		count++ here?
> 
> ACK.
> It's my mistake, the previous version uses port_index=1 as the first debug port, but this version takes 0 as the first port.
> 
> > > +			acpi_early_console_start(&devinfo);
> > no check of the return value to see whether you should return immediately?
> 
> NAK.
> See " MULTIPLE DBGP tables and MULTIPLE DBG2 debug ports support" above.
> 
> > > +	acpi_early_console_start(&devinfo);
> > how about 'return acpi_early_console_start(..)'
> 
> NAK.
> See " MULTIPLE DBGP tables and MULTIPLE DBG2 debug ports support" above.
> 
> > > +	if (acpi_table_parse(ACPI_SIG_DBG2, acpi_parse_dbg2) != 0)
> > > +		acpi_table_parse(ACPI_SIG_DBGP, acpi_parse_dbgp);
> 
> RFC.
> This is to support "MULTIPLE DBGP table versions".
> 
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2012-10-10  3:23   ` [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
@ 2012-10-10 14:10     ` Konrad Rzeszutek Wilk
  2012-10-10 23:39       ` Zheng, Lv
  2012-10-10 17:44     ` Matthew Garrett
  1 sibling, 1 reply; 26+ messages in thread
From: Konrad Rzeszutek Wilk @ 2012-10-10 14:10 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Len Brown, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Feng Tang, linux-kernel, linux-acpi, x86,
	platform-driver-x86

On Wed, Oct 10, 2012 at 11:23:01AM +0800, Lv Zheng wrote:
> Microsoft Debug Port Table (DBGP or DBG2) is used by the Windows SoC
> platforms to describe their debugging facilities.
> DBGP: http://msdn.microsoft.com/en-us/windows/hardware/hh134821
> DBG2: http://msdn.microsoft.com/en-us/library/windows/hardware/hh673515
> 
> This patch enables the DBGP/DBG2 debug ports as Linux early console
> launcher.  Individual early console drivers are also needed to get the
> early kernel messages dumped on the consoles.  For example, to use the
> SPI UART early console for the Low Power Intel Architecture (LPIA)
> platforms, you need to enable the following kernel configurations:
>   CONFIG_EARLY_PRINTK_ACPI=y
>   CONFIG_EARLY_PRINTK_INTEL_MID_SPI=y
> Then you need to append the following kernel parameter to the kernel
> command line in your the boot loader configuration file:
>   earlyprintk=acpi
> 
> There is a dilemma in designing this patch set.  Let me describe it in
> details.
> There should be three steps to enable an early console for an operating
> system:
> 1. Probe: In this stage, the Linux kernel can detect the early consoles
>           and the base address of their register block can be determined.
>           This can be done by parsing the descriptors in the ACPI DBGP/DBG2
>           tables.  Note that acpi_table_init() must be called before
>           parsing.
> 2. Setup: In this stage, the Linux kernel can apply user specified
>           configuration options (ex. baudrate of serial ports) for the
>           early consoles.  This is done by parsing the early parameters
>           passed to the kernel from the boot loaders.  Note that
>           parse_early_params() is called very early to allow parameters to
>           be passed to other kernel subsystems.
> 3. Start: In this stage, the Linux kernel can make the consoles ready to
>           output logs.  Since the early consoles are always used for the
>           kernel boot up debugging, this must be done as early as possible
>           to arm the kernel with the highest testability for other kernel
>           subsystems.  Note that, this stage happens when the
>           register_console() is called.
> The preferred sequence for the above steps is:
>    +-----------------+    +-------------------+    +--------------------+
>    | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
>    +-----------------+    +-------------------+    +--------------------+
> But unfortunately, in the current x86 implementation, early parameters and
> early printk initialization are called before acpi_table_init() which
> depends on the early memory mapping facility.
> There are some choices for me to design this patch set:
> 1. Invoking acpi_table_init() before parse_early_param() to maintain the
>    sequence:
>    +-----------------+    +-------------------+    +--------------------+
>    | ACPI DBGP PROBE | -> | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
>    +-----------------+    +-------------------+    +--------------------+
>    This requires other subsystem maintainers' review to ensure no
>    regressions will be introduced.  At the first glance, I found there
>    might be problems for the EFI subsystsm:
>    The EFI boot services and runtime services are mixed up in the x86
>    specific initialization process before the ACPI table initialization.
>    Things are much worse that you even cannot disable the runtime services
>    while still allow the boot services codes to be executed in the kernel
>    compilation stage.  Enabling the early consoles after the ACPI table
>    initialization will make it difficult to debug the runtime BIOS bugs.
>    If any progress is made to the kernel boot sequences, please let me
>    know.  I'll be willing to redesign the ACPI DBGP/DBG2 console probing
>    facility.  You can reach me at <lv.zheng@intel.com> and
>    <zetalog@gmail.com>.
> 2. Modifying the above sequece to make it look like:
>    +-------------------+    +-----------------+    +--------------------+
>    | EARLY_PARAM SETUP | -> | ACPI DBGP PROBE | -> | EARLY_RPINTK START |
>    +-------------------+    +-----------------+    +--------------------+
>    Early consoles started in this style will lose part of the testability
>    in the kernel boot up sequence.  If the system does not crash very
>    early, developers still can see the bufferred kernel outputs when the
>    register_console() is called.
>    Current early console implementations need to be modified to be
>    compatible with this design.  The original codes need to be split up
>    into tow parts:
>    1. Detecting hardware.  This part can be called in the PROBE stage.
>    2. Applying user parameters.  This part can be called in the SETUP
>       stage.
>    Individual early console drver maintainers need to be involved to avoid
>    regressions that might occur if we do things in this way.  And the
>    maintainers can offer better tests than I can do.
> 3. Introducing a brand new debugging facility that does not relate to the
>    current early console implementation to allow the early consoles to be
>    automatically detected.
>    +-------------------+    +--------------------+
>    | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
>    +-------------------+    +--------------------+
>    +-----------------+    +--------------------+
>    | ACPI DBGP PROBE | -> | EARLY_RPINTK START |
>    +-----------------+    +--------------------+
>    Early consoles started in this style will lose part of the testability
>    in the kernel boot up sequence.  If the system does not crash very
>    early, developers still can see the bufferred kernel outputs when the
>    register_console() is called.
>    Comparing to the solution 2, we can notice that the user configuration
>    can not be applied to the registered early consoles in this way as the
>    acpi_table_init() is still called after the parse_early_param().
>    Instead, the early consoles should derive the hardware settings used in
>    the BIOS/bootloaders.
>    This is what the patch set has done to enable this new usage model.
>    It is known as "ACPI early console launcher mode".
>    As a launcher, ACPI DBGP will not actually output kernel messages
>    without the real early console drivers, that's why the
>    CONFIG_EARLY_PRINTK_INTEL_MID_SPI still need to be enabled along with
>    the CONFIG_EARLY_PRINTK_ACPI.
>    In order to disable this facility by default and enable it at runtime,
>    an kernel parameter "earlyprintk=acpi" is introduced.  This makes the
>    actual sequence look like:
>    +-------------------+    +--------------------+
>    | EARLY_PARAM SETUP | -> | EARLY_RPINTK START |
>    +-------------------+    +....................+
>                             | ACPI DBGP LAUNCH   | ->
>                             +--------------------+
>       +-----------------+    +--------------------+
>    -> | ACPI DBGP PROBE | -> | EARLY_PRINTK START |
>       +-----------------+    +--------------------+
> 
> Version 1:
>  1. Enables single DBG2 debug port support.
> Version 2:
>  1. Applies Rui's comments.
> Version 3:
>  1. Applies Len's comments (earlycon should be disabled by default).
>  2. Enables single DBG2 debug ports support.
> Version 4:
>  1. Fixes the CodingStyle issues reported by checkpatch.pl.
>  2. Enables single DBGP debug port support.
> Version 5:
>  1. Enables multiple DBG2 debug ports support.
>  2. Applies Konrad's comments (pr_debug should be used in earlycon).
>  3. Changes kstrtoul back to simple_strtoul.
> Version 6:
>  1. Applies Konrad's comments (MAX_ACPI_DBG_PORTS bug and count improvement)
>  2. Adds "__init" and "__initdata" to the symbols introduced in this patch.
> 
> Known Issues:
> 1. The simple_strtoul function cannot be replaced by the kstrtoul in
>    the x86 specific booting codes.  The kstrtoul will return error on
>    strings like "acpi0,keep".  This will leave one CodingStyle issue
>    reported by the checkpatch.pl.
> 
> Signed-off-by: Lv Zheng <lv.zheng@intel.com>
> ---
>  Documentation/kernel-parameters.txt |    1 +
>  arch/x86/Kconfig.debug              |   15 +++
>  arch/x86/kernel/acpi/boot.c         |    1 +
>  arch/x86/kernel/early_printk.c      |   13 +++
>  drivers/acpi/Makefile               |    2 +
>  drivers/acpi/early_printk.c         |  172 +++++++++++++++++++++++++++++++++++
>  include/linux/acpi.h                |   22 +++++
>  7 files changed, 226 insertions(+)
>  create mode 100644 drivers/acpi/early_printk.c
> 
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index ad7e2e5..f656765 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -763,6 +763,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>  			earlyprintk=serial[,ttySn[,baudrate]]
>  			earlyprintk=ttySn[,baudrate]
>  			earlyprintk=dbgp[debugController#]
> +			earlyprintk=acpi[debugController#]
>  
>  			Append ",keep" to not disable it when the real console
>  			takes over.
> diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
> index b322f12..5778082 100644
> --- a/arch/x86/Kconfig.debug
> +++ b/arch/x86/Kconfig.debug
> @@ -59,6 +59,21 @@ config EARLY_PRINTK_DBGP
>  	  with klogd/syslogd or the X server. You should normally N here,
>  	  unless you want to debug such a crash. You need usb debug device.
>  
> +config EARLY_PRINTK_ACPI
> +	bool "Early printk launcher via ACPI debug port tables"
> +	depends on EARLY_PRINTK && ACPI
> +	---help---
> +	  Write kernel log output directly into the debug ports described
> +	  in the ACPI tables known as DBGP and DBG2.
> +
> +	  To enable such debugging facilities, you need to enable this
> +	  configuration option and append the "earlyprintk=acpi" kernel
> +	  parameter through the boot loaders.  Please refer the
> +	  "Documentation/kernel-parameters.txt" for details.  Since this
> +	  is an early console launcher, you still need to enable actual
> +	  early console drivers that are suitable for your platform.
> +	  If in doubt, say "N".
> +
>  config DEBUG_STACKOVERFLOW
>  	bool "Check for stack overflows"
>  	depends on DEBUG_KERNEL
> diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
> index b2297e5..cc10ea5 100644
> --- a/arch/x86/kernel/acpi/boot.c
> +++ b/arch/x86/kernel/acpi/boot.c
> @@ -1518,6 +1518,7 @@ void __init acpi_boot_table_init(void)
>  		return;
>  	}
>  
> +	acpi_early_console_probe();
>  	acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
>  
>  	/*
> diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
> index 9b9f18b..bf5b596 100644
> --- a/arch/x86/kernel/early_printk.c
> +++ b/arch/x86/kernel/early_printk.c
> @@ -200,6 +200,15 @@ static inline void early_console_register(struct console *con, int keep_early)
>  	register_console(early_console);
>  }
>  
> +#ifdef CONFIG_EARLY_PRINTK_ACPI
> +#include <linux/acpi.h>
> +
> +int __init __acpi_early_console_start(struct acpi_debug_port *info)
> +{
> +	return 0;
> +}
> +#endif
> +
>  static int __init setup_early_printk(char *buf)
>  {
>  	int keep;
> @@ -236,6 +245,10 @@ static int __init setup_early_printk(char *buf)
>  		if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4))
>  			early_console_register(&early_dbgp_console, keep);
>  #endif
> +#ifdef CONFIG_EARLY_PRINTK_ACPI
> +		if (!strncmp(buf, "acpi", 4))
> +			acpi_early_console_launch(buf + 4, keep);
> +#endif
>  #ifdef CONFIG_HVC_XEN
>  		if (!strncmp(buf, "xen", 3))
>  			early_console_register(&xenboot_console, keep);
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 47199e2..99dbd64 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -46,6 +46,8 @@ ifdef CONFIG_ACPI_VIDEO
>  acpi-y				+= video_detect.o
>  endif
>  
> +obj-$(CONFIG_EARLY_PRINTK_ACPI)	+= early_printk.o
> +
>  # These are (potentially) separate modules
>  obj-$(CONFIG_ACPI_AC) 		+= ac.o
>  obj-$(CONFIG_ACPI_BUTTON)	+= button.o
> diff --git a/drivers/acpi/early_printk.c b/drivers/acpi/early_printk.c
> new file mode 100644
> index 0000000..32b3c13
> --- /dev/null
> +++ b/drivers/acpi/early_printk.c
> @@ -0,0 +1,172 @@
> +/*
> + * acpi/early_printk.c - ACPI Boot-Time Debug Ports
> + *
> + * Copyright (c) 2012, Intel Corporation
> + * Author: Lv Zheng <lv.zheng@intel.com>
> + *
> + * 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 the Free Software Foundation; version 2
> + * of the License.
> + */
> +
> +#define DEBUG
> +#define pr_fmt(fmt)	"ACPI: " KBUILD_MODNAME ": " fmt
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +#include <linux/errno.h>
> +#include <linux/acpi.h>
> +#include <linux/bitmap.h>
> +#include <linux/bootmem.h>
> +
> +#define MAX_ACPI_DBG_PORTS	16
> +
> +static __initdata DECLARE_BITMAP(acpi_early_flags, MAX_ACPI_DBG_PORTS*2);

So the __initdata means that this structure is going away when
user-space launches. Is that OK if the user also supplied 'keep'?

> +static __initdata bool acpi_early_enabled;
> +
> +static int __init acpi_early_console_enable(u8 port, int keep)
> +{
> +	if (port >= MAX_ACPI_DBG_PORTS)
> +		return -ENODEV;
> +
> +	set_bit(port, acpi_early_flags);
> +	if (keep)
> +		set_bit(port+MAX_ACPI_DBG_PORTS, acpi_early_flags);

Put a comment explaining why you use half of the bitmap to mark them
as 'keep'. Thought wouldn't be just easier if you had another bitmap:

acpi_keep_ports?

To set those instead of using this bitmap?

> +	acpi_early_enabled = true;
> +
> +	pr_debug("DBGx LAUNCH - console %d.\n", port);
> +
> +	return 0;
> +}
> +
> +static bool __init acpi_early_console_enabled(u8 port)
> +{
> +	BUG_ON(port >= MAX_ACPI_DBG_PORTS);
> +	return test_bit(port, acpi_early_flags);
> +}
> +
> +int __init acpi_early_console_keep(struct acpi_debug_port *info)
> +{
> +	BUG_ON(!info || info->port_index >= MAX_ACPI_DBG_PORTS);
> +	return test_bit(info->port_index+MAX_ACPI_DBG_PORTS, acpi_early_flags);
> +}
> +
> +static int __init acpi_early_console_start(struct acpi_debug_port *info)
> +{
> +	if (!acpi_early_console_enabled(info->port_index))
> +		return 0;
> +
> +	pr_debug("DBGx START - console %d(%04x:%04x).\n",
> +		 info->port_index, info->port_type, info->port_subtype);
> +	__acpi_early_console_start(info);
> +
> +	return 0;
> +}
> +
> +static int __init acpi_parse_dbg2(struct acpi_table_header *table)
> +{
> +	struct acpi_table_dbg2 *dbg2;
> +	struct acpi_dbg2_device *entry;
> +	void *tbl_end;
> +	u32 count = 0;
> +	u32 max_entries;
> +	struct acpi_debug_port devinfo;
> +
> +	dbg2 = (struct acpi_table_dbg2 *)table;
> +	if (!dbg2) {
> +		pr_debug("DBG2 not present.\n");
> +		return -ENODEV;
> +	}
> +
> +	tbl_end = (void *)table + table->length;
> +
> +	entry = (struct acpi_dbg2_device *)((void *)dbg2 + dbg2->info_offset);
> +	max_entries = min_t(u32, MAX_ACPI_DBG_PORTS, dbg2->info_count);
> +
> +	while (((void *)entry) + sizeof(struct acpi_dbg2_device) < tbl_end) {
> +		if (entry->revision != 0) {
> +			pr_debug("DBG2 revision %d not supported.\n",
> +				 entry->revision);
> +			return -ENODEV;
> +		}
> +		if (count < max_entries) {
> +			pr_debug("DBG2 PROBE - console %d(%04x:%04x).\n",
> +				 count, entry->port_type, entry->port_subtype);
> +
> +			devinfo.port_index = (u8)count;
> +			devinfo.port_type = entry->port_type;
> +			devinfo.port_subtype = entry->port_subtype;
> +			devinfo.register_count = entry->register_count;
> +			devinfo.registers = (struct acpi_generic_address *)
> +			    ((void *)entry + entry->base_address_offset);
> +			devinfo.namepath_length = entry->namepath_length;
> +			devinfo.namepath = (char *)
> +			    ((void *)entry + entry->namepath_offset);
> +			devinfo.oem_data_length = entry->oem_data_length;
> +			devinfo.oem_data = (u8 *)
> +			    ((void *)entry + entry->oem_data_offset);
> +
> +			acpi_early_console_start(&devinfo);
> +			count++;
> +		}
> +
> +		entry = (struct acpi_dbg2_device *)
> +			((void *)entry + entry->length);
> +	}
> +
> +	return 0;
> +}
> +
> +static int __init acpi_parse_dbgp(struct acpi_table_header *table)
> +{
> +	struct acpi_table_dbgp *dbgp;
> +	struct acpi_debug_port devinfo;
> +
> +	dbgp = (struct acpi_table_dbgp *)table;
> +	if (!dbgp) {
> +		pr_debug("DBGP not present.\n");
> +		return -ENODEV;
> +	}
> +
> +	pr_debug("DBGP PROBE - console (%04x).\n", dbgp->type);
> +
> +	devinfo.port_index = 0;
> +	devinfo.port_type = ACPI_DBG2_SERIAL_PORT;
> +	devinfo.port_subtype = dbgp->type;
> +	devinfo.register_count = 1;
> +	devinfo.registers = (struct acpi_generic_address *)&dbgp->debug_port;
> +	devinfo.namepath_length = 0;
> +	devinfo.namepath = NULL;
> +	devinfo.oem_data_length = 0;
> +	devinfo.oem_data = NULL;
> +
> +	acpi_early_console_start(&devinfo);
> +
> +	return 0;
> +}
> +
> +int __init acpi_early_console_probe(void)
> +{
> +	if (!acpi_early_enabled)
> +		return -EINVAL;
> +
> +	if (acpi_table_parse(ACPI_SIG_DBG2, acpi_parse_dbg2) != 0)
> +		acpi_table_parse(ACPI_SIG_DBGP, acpi_parse_dbgp);
> +
> +	return 0;
> +}
> +
> +int __init acpi_early_console_launch(char *s, int keep)
> +{
> +	char *e;
> +	unsigned long port = 0;
> +
> +	if (*s)
> +		port = simple_strtoul(s, &e, 10);
> +
> +	return acpi_early_console_enable(port, keep);
> +}
> +
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 4f2a762..641366c 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -430,4 +430,26 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state,
>  #define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
>  #endif
>  
> +#ifdef CONFIG_EARLY_PRINTK_ACPI
> +struct acpi_debug_port {
> +	u8 port_index;
> +	u16 port_type;
> +	u16 port_subtype;
> +	u16 register_count;
> +	struct acpi_generic_address *registers;
> +	u16 namepath_length;
> +	char *namepath;
> +	u16 oem_data_length;
> +	u8 *oem_data;
> +};
> +
> +int __init acpi_early_console_keep(struct acpi_debug_port *info);
> +int __init acpi_early_console_launch(char *s, int keep);
> +int __init acpi_early_console_probe(void);
> +/* This interface is arch specific. */
> +int __init __acpi_early_console_start(struct acpi_debug_port *info);
> +#else
> +static int acpi_early_console_probe(void) { return 0; }
> +#endif
> +
>  #endif	/*_LINUX_ACPI_H*/
> -- 
> 1.7.10
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2012-10-10  3:23   ` [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
  2012-10-10 14:10     ` Konrad Rzeszutek Wilk
@ 2012-10-10 17:44     ` Matthew Garrett
  2012-10-12 19:24       ` Khalid Aziz
  1 sibling, 1 reply; 26+ messages in thread
From: Matthew Garrett @ 2012-10-10 17:44 UTC (permalink / raw)
  To: Lv Zheng
  Cc: Len Brown, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Feng Tang, linux-kernel, linux-acpi, x86,
	platform-driver-x86

On Wed, Oct 10, 2012 at 11:23:01AM +0800, Lv Zheng wrote:
> Microsoft Debug Port Table (DBGP or DBG2) is used by the Windows SoC
> platforms to describe their debugging facilities.
> DBGP: http://msdn.microsoft.com/en-us/windows/hardware/hh134821
> DBG2: http://msdn.microsoft.com/en-us/library/windows/hardware/hh673515

The license for these specifications only covers BIOS implementations, 
not OS implementations. Has this had appropriate legal review?

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2012-10-10 14:10     ` Konrad Rzeszutek Wilk
@ 2012-10-10 23:39       ` Zheng, Lv
  0 siblings, 0 replies; 26+ messages in thread
From: Zheng, Lv @ 2012-10-10 23:39 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Brown, Len, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
	Jason Wessel, Tang, Feng, linux-kernel, linux-acpi, x86,
	platform-driver-x86

> > +static __initdata DECLARE_BITMAP(acpi_early_flags,
> > +MAX_ACPI_DBG_PORTS*2);

It's OK since the keep bit will be derived by the real earlycon drivers in the __acpi_early_console_start() which is an arch specific interface.
You can find this usage in the [PATCH v6 2/2].

> > +	set_bit(port, acpi_early_flags);
> > +	if (keep)
> > +		set_bit(port+MAX_ACPI_DBG_PORTS, acpi_early_flags);
> Put a comment explaining why you use half of the bitmap to mark them as
> 'keep'. Thought wouldn't be just easier if you had another bitmap:
> acpi_keep_ports?
> To set those instead of using this bitmap?

I prefer to put comment here.
I've been a deep embedded engineer for the last 5 years, implementing software containing 4 bus protocol stacks within 128bytes ram and 16kbytes rom, where we used high modularity design patterns.
Thus made my habit being critical to ram/rom consumption...

I'm OOO now, the updated version will be sent next week.

Thanks for your comments and best regards/Lv Zheng

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2012-10-10 17:44     ` Matthew Garrett
@ 2012-10-12 19:24       ` Khalid Aziz
  2013-06-04 10:53         ` Grant Likely
  0 siblings, 1 reply; 26+ messages in thread
From: Khalid Aziz @ 2012-10-12 19:24 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Lv Zheng, Len Brown, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, Jason Wessel, Feng Tang, linux-kernel,
	linux-acpi, x86, platform-driver-x86

On Wed, 2012-10-10 at 18:44 +0100, Matthew Garrett wrote:
> On Wed, Oct 10, 2012 at 11:23:01AM +0800, Lv Zheng wrote:
> > Microsoft Debug Port Table (DBGP or DBG2) is used by the Windows SoC
> > platforms to describe their debugging facilities.
> > DBGP: http://msdn.microsoft.com/en-us/windows/hardware/hh134821
> > DBG2: http://msdn.microsoft.com/en-us/library/windows/hardware/hh673515
> 
> The license for these specifications only covers BIOS implementations, 
> not OS implementations. Has this had appropriate legal review?
> 

I agree with Matthew. There are potential legal issues with using
DBGP/DBGP2 tables in Linux. I had added support for SPCR and DBGP tables
many years ago (in early 2.6 kernel timeframe) before Microsoft added
this new license. I pulled the code out (in 2.6.14, I think) after
Microsoft added the new license to these tables. I agree with Matthew's
interpretation that the license is clear only about BIOS vendors being
allowed to use these tables. PCDP table in DIG64 spec was introduced to
get around the legal issues with using SPCR and DBGP in Linux.

License for DBGP/DBGP2 needs some legal review before this patch can go
into Linux.

--
Khalid


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2012-10-12 19:24       ` Khalid Aziz
@ 2013-06-04 10:53         ` Grant Likely
  2013-06-04 13:23           ` Matthew Garrett
  0 siblings, 1 reply; 26+ messages in thread
From: Grant Likely @ 2013-06-04 10:53 UTC (permalink / raw)
  To: Khalid Aziz
  Cc: Matthew Garrett, Lv Zheng, Len Brown, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Jason Wessel, Feng Tang,
	Linux Kernel Mailing List, ACPI Devel Mailing List, x86,
	platform-driver-x86, Al Stone

On Fri, Oct 12, 2012 at 8:24 PM, Khalid Aziz <khalid@gonehiking.org> wrote:
> On Wed, 2012-10-10 at 18:44 +0100, Matthew Garrett wrote:
>> On Wed, Oct 10, 2012 at 11:23:01AM +0800, Lv Zheng wrote:
>> > Microsoft Debug Port Table (DBGP or DBG2) is used by the Windows SoC
>> > platforms to describe their debugging facilities.
>> > DBGP: http://msdn.microsoft.com/en-us/windows/hardware/hh134821
>> > DBG2: http://msdn.microsoft.com/en-us/library/windows/hardware/hh673515
>>
>> The license for these specifications only covers BIOS implementations,
>> not OS implementations. Has this had appropriate legal review?
>>
>
> I agree with Matthew. There are potential legal issues with using
> DBGP/DBGP2 tables in Linux. I had added support for SPCR and DBGP tables
> many years ago (in early 2.6 kernel timeframe) before Microsoft added
> this new license. I pulled the code out (in 2.6.14, I think) after
> Microsoft added the new license to these tables. I agree with Matthew's
> interpretation that the license is clear only about BIOS vendors being
> allowed to use these tables. PCDP table in DIG64 spec was introduced to
> get around the legal issues with using SPCR and DBGP in Linux.
>
> License for DBGP/DBGP2 needs some legal review before this patch can go
> into Linux.

Matthew, can you point me at the license Microsoft is using for the
DBG2 table? I can download the document from Microsoft's site without
seeing any reference to it being licensed only for BIOS implementers.
All I see is a "this document is provided 'as-is', blah blah blah"
blurb at the beginning of the document. It may be that Microsoft has
changed the license on this document in the last 6 months.

I asked some of my contacts at Microsoft about this and was told that
the DBG2 spec was supposed to be freed up; but I wasn't able to get
anything absolutely confirmed or in writing.

g.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2013-06-04 10:53         ` Grant Likely
@ 2013-06-04 13:23           ` Matthew Garrett
  2013-06-04 13:35             ` Grant Likely
  0 siblings, 1 reply; 26+ messages in thread
From: Matthew Garrett @ 2013-06-04 13:23 UTC (permalink / raw)
  To: Grant Likely
  Cc: Khalid Aziz, Matthew Garrett, Lv Zheng, Len Brown,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Jason Wessel,
	Feng Tang, Linux Kernel Mailing List, ACPI Devel Mailing List,
	x86, platform-driver-x86, Al Stone

On Tue, Jun 04, 2013 at 11:53:56AM +0100, Grant Likely wrote:

> Matthew, can you point me at the license Microsoft is using for the
> DBG2 table? I can download the document from Microsoft's site without
> seeing any reference to it being licensed only for BIOS implementers.
> All I see is a "this document is provided 'as-is', blah blah blah"
> blurb at the beginning of the document. It may be that Microsoft has
> changed the license on this document in the last 6 months.

The DBGP spec still seems to have the restrictive license, but I can't 
find it on DBG2.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2.
  2013-06-04 13:23           ` Matthew Garrett
@ 2013-06-04 13:35             ` Grant Likely
  0 siblings, 0 replies; 26+ messages in thread
From: Grant Likely @ 2013-06-04 13:35 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Khalid Aziz, Matthew Garrett, Lv Zheng, Len Brown,
	Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Jason Wessel,
	Feng Tang, Linux Kernel Mailing List, ACPI Devel Mailing List,
	x86, platform-driver-x86, Al Stone

On Tue, Jun 4, 2013 at 2:23 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> On Tue, Jun 04, 2013 at 11:53:56AM +0100, Grant Likely wrote:
>
>> Matthew, can you point me at the license Microsoft is using for the
>> DBG2 table? I can download the document from Microsoft's site without
>> seeing any reference to it being licensed only for BIOS implementers.
>> All I see is a "this document is provided 'as-is', blah blah blah"
>> blurb at the beginning of the document. It may be that Microsoft has
>> changed the license on this document in the last 6 months.
>
> The DBGP spec still seems to have the restrictive license, but I can't
> find it on DBG2.

Thanks Matthew. I'll follow up with Microsoft on DBGP.

g.

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2013-06-04 13:36 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <cover.1347453194.git.zetalog@gmail.com>
2012-09-28  2:39 ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Lv Zheng
2012-09-28  2:40   ` [PATCH v4 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
2012-09-28  2:40   ` [PATCH v4 2/2] ACPI: Add Intel MID SPI early console support Lv Zheng
2012-09-28  5:24   ` [PATCH v4 0/2] ACPI: DBGP/DBG2 early console support for LPIA Zheng, Lv
2012-09-28  6:36   ` [RESEND PATCH " H. Peter Anvin
2012-10-06 18:42     ` Len Brown
2012-10-07 15:41       ` H. Peter Anvin
2012-10-08  0:51       ` Zheng, Lv
2012-10-10  3:23   ` [PATCH v6 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
2012-10-10 14:10     ` Konrad Rzeszutek Wilk
2012-10-10 23:39       ` Zheng, Lv
2012-10-10 17:44     ` Matthew Garrett
2012-10-12 19:24       ` Khalid Aziz
2013-06-04 10:53         ` Grant Likely
2013-06-04 13:23           ` Matthew Garrett
2013-06-04 13:35             ` Grant Likely
2012-10-10  3:23   ` [PATCH v6 2/2] ACPI: Add Intel MID SPI early console support Lv Zheng
2012-10-09  2:36 ` [PATCH v5 1/2] ACPI: Add early console framework for DBGP/DBG2 Lv Zheng
2012-10-09 17:02   ` Konrad Rzeszutek Wilk
2012-10-10  1:31     ` Zheng, Lv
2012-10-10 14:06       ` Konrad Rzeszutek Wilk
2012-10-10  1:40     ` Zheng, Lv
2012-10-09  2:37 ` [PATCH v5 2/2] ACPI: Add Intel MID SPI early console support Lv Zheng
2012-10-09 17:06   ` Konrad Rzeszutek Wilk
2012-10-10  1:33     ` Zheng, Lv
2012-10-10  3:10     ` Zheng, Lv

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).