[v2,5/8] ACPI: parse DBG2 table

Message ID 1456333819-13482-6-git-send-email-aleksey.makarov@linaro.org
State New
Headers show

Commit Message

Aleksey Makarov Feb. 24, 2016, 5:10 p.m.
'ARM Server Base Boot Requiremets' [1] mentions DBG2 (Microsoft Debug
Port Table 2) [2] as a mandatory ACPI table that specifies debug ports.

- Implement macros

	ACPI_DBG2_DECLARE(name, type, subtype, setup_fn, data_ptr)

  that defines a handler for the port of given type and subtype.

- For each declared port that is also described in the ACPI DBG2 table
  call the provided callback.

[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0044a/index.html
[2] http://go.microsoft.com/fwlink/p/?LinkId=234837

Signed-off-by: Aleksey Makarov <aleksey.makarov@linaro.org>

---
 drivers/acpi/Kconfig              |  3 ++
 drivers/acpi/Makefile             |  1 +
 drivers/acpi/dbg2.c               | 85 +++++++++++++++++++++++++++++++++++++++
 include/asm-generic/vmlinux.lds.h |  1 +
 include/linux/acpi_dbg2.h         | 48 ++++++++++++++++++++++
 5 files changed, 138 insertions(+)
 create mode 100644 drivers/acpi/dbg2.c
 create mode 100644 include/linux/acpi_dbg2.h

-- 
2.7.1

Patch

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 65fb483..660666e 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -57,6 +57,9 @@  config ACPI_SYSTEM_POWER_STATES_SUPPORT
 config ACPI_CCA_REQUIRED
 	bool
 
+config ACPI_DBG2_TABLE
+	bool
+
 config ACPI_DEBUGGER
 	bool "AML debugger interface"
 	select ACPI_DEBUG
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 7395928..3b5f1ea 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -83,6 +83,7 @@  obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
 obj-$(CONFIG_ACPI_CPPC_LIB)	+= cppc_acpi.o
 obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o
+obj-$(CONFIG_ACPI_DBG2_TABLE)	+= dbg2.o
 
 # processor has its own "processor." module_param namespace
 processor-y			:= processor_driver.o
diff --git a/drivers/acpi/dbg2.c b/drivers/acpi/dbg2.c
new file mode 100644
index 0000000..8a79117
--- /dev/null
+++ b/drivers/acpi/dbg2.c
@@ -0,0 +1,85 @@ 
+/*
+ * Copyright (c) 2012, Intel Corporation
+ * Copyright (c) 2015, 2016 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define pr_fmt(fmt) "ACPI: DBG2: " fmt
+
+#include <linux/acpi_dbg2.h>
+#include <linux/acpi.h>
+#include <linux/kernel.h>
+
+static const char * __init type2string(u16 type)
+{
+	switch (type) {
+	case ACPI_DBG2_SERIAL_PORT:
+		return "SERIAL";
+	case ACPI_DBG2_1394_PORT:
+		return "1394";
+	case ACPI_DBG2_USB_PORT:
+		return "USB";
+	case ACPI_DBG2_NET_PORT:
+		return "NET";
+	default:
+		return "?";
+	}
+}
+
+static const char * __init subtype2string(u16 subtype)
+{
+	switch (subtype) {
+	case ACPI_DBG2_16550_COMPATIBLE:
+		return "16550_COMPATIBLE";
+	case ACPI_DBG2_16550_SUBSET:
+		return "16550_SUBSET";
+	case ACPI_DBG2_ARM_PL011:
+		return "ARM_PL011";
+	case ACPI_DBG2_ARM_SBSA_32BIT:
+		return "ARM_SBSA_32BIT";
+	case ACPI_DBG2_ARM_SBSA_GENERIC:
+		return "ARM_SBSA_GENERIC";
+	case ACPI_DBG2_ARM_DCC:
+		return "ARM_DCC";
+	case ACPI_DBG2_BCM2835:
+		return "BCM2835";
+	default:
+		return "?";
+	}
+}
+
+int __init acpi_dbg2_setup(struct acpi_table_header *table, const void *data)
+{
+	struct acpi_table_dbg2 *dbg2 = (struct acpi_table_dbg2 *)table;
+	struct acpi_dbg2_data *dbg2_data = (struct acpi_dbg2_data *)data;
+	struct acpi_dbg2_device *dbg2_device, *dbg2_end;
+	int i;
+
+	dbg2_device = ACPI_ADD_PTR(struct acpi_dbg2_device, dbg2,
+				   dbg2->info_offset);
+	dbg2_end = ACPI_ADD_PTR(struct acpi_dbg2_device, dbg2, table->length);
+
+	for (i = 0; i < dbg2->info_count; i++) {
+		if (dbg2_device + 1 > dbg2_end) {
+			pr_err("device pointer overflows, bad table\n");
+			return 0;
+		}
+
+		if (dbg2_device->port_type == dbg2_data->port_type &&
+		    dbg2_device->port_subtype == dbg2_data->port_subtype) {
+			pr_info("debug port type: %s subtype: %s\n",
+				type2string(dbg2_device->port_type),
+				subtype2string(dbg2_device->port_subtype));
+			dbg2_data->setup(dbg2_device, dbg2_data->data);
+		}
+
+		dbg2_device = ACPI_ADD_PTR(struct acpi_dbg2_device, dbg2_device,
+					   dbg2_device->length);
+	}
+
+	return 0;
+}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index e9a81a6..ab6a727 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -525,6 +525,7 @@ 
 	IRQCHIP_OF_MATCH_TABLE()					\
 	ACPI_PROBE_TABLE(irqchip)					\
 	ACPI_PROBE_TABLE(clksrc)					\
+	ACPI_PROBE_TABLE(dbg2)						\
 	EARLYCON_TABLE()
 
 #define INIT_TEXT							\
diff --git a/include/linux/acpi_dbg2.h b/include/linux/acpi_dbg2.h
new file mode 100644
index 0000000..125ae7e
--- /dev/null
+++ b/include/linux/acpi_dbg2.h
@@ -0,0 +1,48 @@ 
+#ifndef _ACPI_DBG2_H_
+#define _ACPI_DBG2_H_
+
+#ifdef CONFIG_ACPI_DBG2_TABLE
+
+#include <linux/kernel.h>
+
+struct acpi_dbg2_device;
+struct acpi_table_header;
+
+struct acpi_dbg2_data {
+	u16 port_type;
+	u16 port_subtype;
+	int (*setup)(struct acpi_dbg2_device *, void *);
+	void *data;
+};
+
+int acpi_dbg2_setup(struct acpi_table_header *header, const void *data);
+
+/**
+ * ACPI_DBG2_DECLARE() - Define handler for ACPI DBG2 port
+ * @name:	Identifier to compose name of table data
+ * @type:	Type of the port
+ * @subtype:	Subtype of the port
+ * @setup_fn:	Function to be called to setup the port
+ *		(of type int (*)(struct acpi_dbg2_device *, void *);)
+ * @data_ptr:	Sideband data provided back to the driver
+ */
+#define ACPI_DBG2_DECLARE(name, type, subtype, setup_fn, data_ptr)	\
+	static const struct acpi_dbg2_data				\
+		__acpi_dbg2_data_##name __used = {			\
+			.port_type = type,				\
+			.port_subtype = subtype,			\
+			.setup = setup_fn,				\
+			.data = data_ptr,				\
+		   };							\
+	ACPI_DECLARE_PROBE_ENTRY(dbg2, name, ACPI_SIG_DBG2,		\
+				 acpi_dbg2_setup, &__acpi_dbg2_data_##name)
+
+#else
+
+#define ACPI_DBG2_DECLARE(name, type, subtype, setup_fn, data_ptr)	\
+	static const void *__acpi_dbg_data_##name[]			\
+		__used __initdata = { (void *)setup_fn,	(void *)data_ptr }
+
+#endif
+
+#endif