Skip to contentSkip to conversation

DT early console initialization

PATCH In review Rob Herring 4 participants 12 messages May 8, 2014 – May 28, 2014

Subsystems (8)
lore
Share & tools
lore
#0 lore raw

cover DT early console initialization

From: Rob Herring <[email protected]>

This series adds support for early serial console initialization using DT. This enables determining the serial port type and address using the FDT and allows enabling the console before platform specific initialization runs. I've tested this on arm64. ARM support is dependent on adding fixmap support.

Currently, the earlycon is only enabled if "earlycon" is present on the kernel command line. The FDT needs to have /chosen/stdout-path set to the path of the serial port.

This series is dependent on generic earlycon[1], libfdt support[2], and vmlinux.lds.h clean-ups[3]. The first 2 are in linux-next already. A git branch is available here:

git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git earlycon-dt

Rob

[1] https://lkml.org/lkml/2014/4/18/573
[2] https://lkml.org/lkml/2014/4/22/1202
[3] https://lkml.org/lkml/2014/3/27/285

Rob Herring (6):
of: align RESERVEDMEM_OF_DECLARE function callbacks to other callbacks
of: consolidate linker section OF match table declarations
serial: earlycon: add DT support
of/fdt: add FDT address translation support
of/fdt: add FDT serial scanning for earlycon
tty/serial: pl011: add DT based earlycon support

 drivers/clocksource/clksrc-of.c   |   2 +-
 drivers/irqchip/irqchip.h         |   7 +-
 drivers/of/Makefile               |   2 +
 drivers/of/fdt.c                  |  56 +++++++++
 drivers/of/fdt_address.c          | 241 ++++++++++++++++++++++++++++++++++++++
 drivers/of/of_reserved_mem.c      |   2 +-
 drivers/tty/serial/amba-pl011.c   |   1 +
 drivers/tty/serial/earlycon.c     |  27 +++++
 include/asm-generic/vmlinux.lds.h |   4 +-
 include/linux/clk-provider.h      |   5 +-
 include/linux/clocksource.h       |  16 +--
 include/linux/of.h                |  22 ++++
 include/linux/of_fdt.h            |   1 +
 include/linux/of_reserved_mem.h   |  22 +---
 include/linux/serial_core.h       |   6 +
 15 files changed, 372 insertions(+), 42 deletions(-)
 create mode 100644 drivers/of/fdt_address.c
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/6 of: align RESERVEDMEM_OF_DECLARE function callbacks to other callbacks

From: Rob Herring <[email protected]>

All the parameters for RESERVEDMEM_OF_DECLARE function callbacks are members of struct reserved_mem, so just pass the struct ptr to callback functions so the function callback is more in line with other OF match table callbacks.

Cc Marek Szyprowski <[email protected]>
Cc Grant Likely <[email protected]>
---
 drivers/of/of_reserved_mem.c    | 2 +-
 include/linux/of_reserved_mem.h | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/of/of_reserved_mem.c +1 -1
index e420eb5..632aae8 100644
@@ -188,7 +188,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem)
 		if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
 			continue;
 
-		if (initfn(rmem, rmem->fdt_node, rmem->name) == 0) {
+		if (initfn(rmem) == 0) {
 			pr_info("Reserved memory: initialized node %s, compatible id %s\n",
 				rmem->name, compat);
 			return 0;
include/linux/of_reserved_mem.h +2 -2
index 9b1fbb7..4c81b84 100644
@@ -21,8 +21,8 @@ struct reserved_mem_ops {
 				  struct device *dev);
 };
 
-typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem,
-				      unsigned long node, const char *uname);
+typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem);
+
 
 #ifdef CONFIG_OF_RESERVED_MEM
 void fdt_init_reserved_mem(void);
Signature · 1 line
1.9.1
Acked-by on v1 1/6
#2 lore raw

Re: [PATCH 1/6] of: align RESERVEDMEM_OF_DECLARE function callbacks to other callbacks

Hello,

Quoted 10 lines · Rob Herring

From: Rob Herring <[email protected]>

All the parameters for RESERVEDMEM_OF_DECLARE function callbacks are members of struct reserved_mem, so just pass the struct ptr to callback functions so the function callback is more in line with other OF match table callbacks.

Cc Marek Szyprowski <[email protected]>
Cc Grant Likely <[email protected]>
Quoted 23 lines
---
  drivers/of/of_reserved_mem.c    | 2 +-
  include/linux/of_reserved_mem.h | 4 ++--
  2 files changed, 3 insertions(+), 3 deletions(-)
drivers/of/of_reserved_mem.c +1 -1
index e420eb5..632aae8 100644
@@ -188,7 +188,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem)
  		if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
  			continue;
 
-		if (initfn(rmem, rmem->fdt_node, rmem->name) == 0) {
+		if (initfn(rmem) == 0) {
  			pr_info("Reserved memory: initialized node %s, compatible id %s\n",
  				rmem->name, compat);
  			return 0;
include/linux/of_reserved_mem.h +0 -0
index 9b1fbb7..4c81b84 100644

include/linux/of_reserved_mem.h struct reserved_mem_ops { · line 28

Quoted 10 lines
include/linux/of_reserved_mem.h +2 -2
@@ -21,8 +21,8 @@ struct reserved_mem_ops {
  				  struct device *dev);
  };
 
-typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem,
-				      unsigned long node, const char *uname);
+typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem);
+
 
  #ifdef CONFIG_OF_RESERVED_MEM
  void fdt_init_reserved_mem(void);

Best regards

Signature · 2 lines
Marek Szyprowski, PhD
Samsung R&D Institute Poland
#3 lore raw

PATCH 2/6 of: consolidate linker section OF match table declarations

In reply to Rob Herring

From: Rob Herring <[email protected]>

We now have several OF match tables using linker sections that are nearly the same definition. The only variation is the callback function prototype. Create a common define for creating linker section OF match table entries which each table declaration can use.

---
 drivers/clocksource/clksrc-of.c |  2 +-
 drivers/irqchip/irqchip.h       |  7 +++----
 include/linux/clk-provider.h    |  5 +----
 include/linux/clocksource.h     | 16 +++-------------
 include/linux/of.h              | 22 ++++++++++++++++++++++
 include/linux/of_reserved_mem.h | 18 ++----------------
 6 files changed, 32 insertions(+), 38 deletions(-)
drivers/clocksource/clksrc-of.c +1 -1
index ae2e427..0093a8e 100644
@@ -27,7 +27,7 @@ void __init clocksource_of_init(void)
 {
 	struct device_node *np;
 	const struct of_device_id *match;
-	clocksource_of_init_fn init_func;
+	of_init_fn_1 init_func;
 	unsigned clocksources = 0;
 
 	for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
drivers/irqchip/irqchip.h +3 -4
index e445ba2..0f6486d 100644
@@ -11,6 +11,8 @@
 #ifndef _IRQCHIP_H
 #define _IRQCHIP_H
 
+#include <linux/of.h>
+
 /*
  * This macro must be used by the different irqchip drivers to declare
  * the association between their DT compatible string and their
@@ -21,9 +23,6 @@
  * @compstr: compatible string of the irqchip driver
  * @fn: initialization function
  */
-#define IRQCHIP_DECLARE(name,compstr,fn)				\
-	static const struct of_device_id irqchip_of_match_##name	\
-	__used __section(__irqchip_of_table)				\
-	= { .compatible = compstr, .data = fn }
+#define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)
 
 #endif
include/linux/clk-provider.h +1 -4
index 59e2eb5..3429929 100644
@@ -501,10 +501,7 @@ struct clk_onecell_data {
 
 extern struct of_device_id __clk_of_table;
 
-#define CLK_OF_DECLARE(name, compat, fn)			\
-	static const struct of_device_id __clk_of_table_##name	\
-		__used __section(__clk_of_table)		\
-		= { .compatible = compat, .data = fn };
+#define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn)
 
 #ifdef CONFIG_OF
 int of_clk_add_provider(struct device_node *np,
include/linux/clocksource.h +3 -13
index 67301a4..a16b497 100644
@@ -339,23 +339,13 @@ extern int clocksource_mmio_init(void __iomem *, const char *,
 
 extern int clocksource_i8253_init(void);
 
-struct device_node;
-typedef void(*clocksource_of_init_fn)(struct device_node *);
+#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \
+	OF_DECLARE_1(clksrc, name, compat, fn)
+
 #ifdef CONFIG_CLKSRC_OF
 extern void clocksource_of_init(void);
-
-#define CLOCKSOURCE_OF_DECLARE(name, compat, fn)			\
-	static const struct of_device_id __clksrc_of_table_##name	\
-		__used __section(__clksrc_of_table)			\
-		 = { .compatible = compat,				\
-		     .data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn }
 #else
 static inline void clocksource_of_init(void) {}
-#define CLOCKSOURCE_OF_DECLARE(name, compat, fn)			\
-	static const struct of_device_id __clksrc_of_table_##name	\
-		__attribute__((unused))					\
-		 = { .compatible = compat,				\
-		     .data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn }
 #endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
include/linux/of.h +22 -0
index 3bad8d1..6fb2185 100644
@@ -757,4 +757,26 @@ static inline int of_get_available_child_count(const struct device_node *np)
 	return num;
 }
 
+#ifdef CONFIG_OF
+#define _OF_DECLARE(table, name, compat, fn, fn_type)			\
+	static const struct of_device_id __of_table_##name		\
+		__used __section(__##table##_of_table)			\
+		 = { .compatible = compat,				\
+		     .data = (fn == (fn_type)NULL) ? fn : fn  }
+#else
+#define _OF_DECLARE(name, compat, fn, fn_type)					\
+	static const struct of_device_id __of_table_##name		\
+		__attribute__((unused))					\
+		 = { .compatible = compat,				\
+		     .data = (fn == (fn_type)NULL) ? fn : fn }
+#endif
+
+typedef int (*of_init_fn_2)(struct device_node *, struct device_node *);
+typedef void (*of_init_fn_1)(struct device_node *);
+
+#define OF_DECLARE_1(table, name, compat, fn) \
+		_OF_DECLARE(table, name, compat, fn, of_init_fn_1)
+#define OF_DECLARE_2(table, name, compat, fn) \
+		_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
+
 #endif /* _LINUX_OF_H */
include/linux/of_reserved_mem.h +2 -16
index 4c81b84..4669ddf 100644
@@ -23,31 +23,17 @@ struct reserved_mem_ops {
 
 typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem);
 
+#define RESERVEDMEM_OF_DECLARE(name, compat, init)			\
+	_OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn)
 
 #ifdef CONFIG_OF_RESERVED_MEM
 void fdt_init_reserved_mem(void);
 void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
 			       phys_addr_t base, phys_addr_t size);
-
-#define RESERVEDMEM_OF_DECLARE(name, compat, init)			\
-	static const struct of_device_id __reservedmem_of_table_##name	\
-		__used __section(__reservedmem_of_table)		\
-		 = { .compatible = compat,				\
-		     .data = (init == (reservedmem_of_init_fn)NULL) ?	\
-				init : init }
-
 #else
 static inline void fdt_init_reserved_mem(void) { }
 static inline void fdt_reserved_mem_save_node(unsigned long node,
 		const char *uname, phys_addr_t base, phys_addr_t size) { }
-
-#define RESERVEDMEM_OF_DECLARE(name, compat, init)			\
-	static const struct of_device_id __reservedmem_of_table_##name	\
-		__attribute__((unused))					\
-		 = { .compatible = compat,				\
-		     .data = (init == (reservedmem_of_init_fn)NULL) ?	\
-				init : init }
-
 #endif
 
 #endif /* __OF_RESERVED_MEM_H */
Signature · 1 line
1.9.1
Acked-by on v1 2/6
#4 lore raw

Re: [PATCH 2/6] of: consolidate linker section OF match table declarations

Quoted 9 lines · Rob Herring

From: Rob Herring <[email protected]>

We now have several OF match tables using linker sections that are nearly the same definition. The only variation is the callback function prototype. Create a common define for creating linker section OF match table entries which each table declaration can use.

Nice!

g.

Quoted 165 lines
---
 drivers/clocksource/clksrc-of.c |  2 +-
 drivers/irqchip/irqchip.h       |  7 +++----
 include/linux/clk-provider.h    |  5 +----
 include/linux/clocksource.h     | 16 +++-------------
 include/linux/of.h              | 22 ++++++++++++++++++++++
 include/linux/of_reserved_mem.h | 18 ++----------------
 6 files changed, 32 insertions(+), 38 deletions(-)
drivers/clocksource/clksrc-of.c +1 -1
index ae2e427..0093a8e 100644
@@ -27,7 +27,7 @@ void __init clocksource_of_init(void)
 {
 	struct device_node *np;
 	const struct of_device_id *match;
-	clocksource_of_init_fn init_func;
+	of_init_fn_1 init_func;
 	unsigned clocksources = 0;
 
 	for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
drivers/irqchip/irqchip.h +3 -4
index e445ba2..0f6486d 100644
@@ -11,6 +11,8 @@
 #ifndef _IRQCHIP_H
 #define _IRQCHIP_H
 
+#include <linux/of.h>
+
 /*
  * This macro must be used by the different irqchip drivers to declare
  * the association between their DT compatible string and their
@@ -21,9 +23,6 @@
  * @compstr: compatible string of the irqchip driver
  * @fn: initialization function
  */
-#define IRQCHIP_DECLARE(name,compstr,fn)				\
-	static const struct of_device_id irqchip_of_match_##name	\
-	__used __section(__irqchip_of_table)				\
-	= { .compatible = compstr, .data = fn }
+#define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)
 
 #endif
include/linux/clk-provider.h +1 -4
index 59e2eb5..3429929 100644
@@ -501,10 +501,7 @@ struct clk_onecell_data {
 
 extern struct of_device_id __clk_of_table;
 
-#define CLK_OF_DECLARE(name, compat, fn)			\
-	static const struct of_device_id __clk_of_table_##name	\
-		__used __section(__clk_of_table)		\
-		= { .compatible = compat, .data = fn };
+#define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn)
 
 #ifdef CONFIG_OF
 int of_clk_add_provider(struct device_node *np,
include/linux/clocksource.h +3 -13
index 67301a4..a16b497 100644
@@ -339,23 +339,13 @@ extern int clocksource_mmio_init(void __iomem *, const char *,
 
 extern int clocksource_i8253_init(void);
 
-struct device_node;
-typedef void(*clocksource_of_init_fn)(struct device_node *);
+#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \
+	OF_DECLARE_1(clksrc, name, compat, fn)
+
 #ifdef CONFIG_CLKSRC_OF
 extern void clocksource_of_init(void);
-
-#define CLOCKSOURCE_OF_DECLARE(name, compat, fn)			\
-	static const struct of_device_id __clksrc_of_table_##name	\
-		__used __section(__clksrc_of_table)			\
-		 = { .compatible = compat,				\
-		     .data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn }
 #else
 static inline void clocksource_of_init(void) {}
-#define CLOCKSOURCE_OF_DECLARE(name, compat, fn)			\
-	static const struct of_device_id __clksrc_of_table_##name	\
-		__attribute__((unused))					\
-		 = { .compatible = compat,				\
-		     .data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn }
 #endif
 
 #endif /* _LINUX_CLOCKSOURCE_H */
include/linux/of.h +22 -0
index 3bad8d1..6fb2185 100644
@@ -757,4 +757,26 @@ static inline int of_get_available_child_count(const struct device_node *np)
 	return num;
 }
 
+#ifdef CONFIG_OF
+#define _OF_DECLARE(table, name, compat, fn, fn_type)			\
+	static const struct of_device_id __of_table_##name		\
+		__used __section(__##table##_of_table)			\
+		 = { .compatible = compat,				\
+		     .data = (fn == (fn_type)NULL) ? fn : fn  }
+#else
+#define _OF_DECLARE(name, compat, fn, fn_type)					\
+	static const struct of_device_id __of_table_##name		\
+		__attribute__((unused))					\
+		 = { .compatible = compat,				\
+		     .data = (fn == (fn_type)NULL) ? fn : fn }
+#endif
+
+typedef int (*of_init_fn_2)(struct device_node *, struct device_node *);
+typedef void (*of_init_fn_1)(struct device_node *);
+
+#define OF_DECLARE_1(table, name, compat, fn) \
+		_OF_DECLARE(table, name, compat, fn, of_init_fn_1)
+#define OF_DECLARE_2(table, name, compat, fn) \
+		_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
+
 #endif /* _LINUX_OF_H */
include/linux/of_reserved_mem.h +2 -16
index 4c81b84..4669ddf 100644
@@ -23,31 +23,17 @@ struct reserved_mem_ops {
 
 typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem);
 
+#define RESERVEDMEM_OF_DECLARE(name, compat, init)			\
+	_OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn)
 
 #ifdef CONFIG_OF_RESERVED_MEM
 void fdt_init_reserved_mem(void);
 void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
 			       phys_addr_t base, phys_addr_t size);
-
-#define RESERVEDMEM_OF_DECLARE(name, compat, init)			\
-	static const struct of_device_id __reservedmem_of_table_##name	\
-		__used __section(__reservedmem_of_table)		\
-		 = { .compatible = compat,				\
-		     .data = (init == (reservedmem_of_init_fn)NULL) ?	\
-				init : init }
-
 #else
 static inline void fdt_init_reserved_mem(void) { }
 static inline void fdt_reserved_mem_save_node(unsigned long node,
 		const char *uname, phys_addr_t base, phys_addr_t size) { }
-
-#define RESERVEDMEM_OF_DECLARE(name, compat, init)			\
-	static const struct of_device_id __reservedmem_of_table_##name	\
-		__attribute__((unused))					\
-		 = { .compatible = compat,				\
-		     .data = (init == (reservedmem_of_init_fn)NULL) ?	\
-				init : init }
-
 #endif
 
 #endif /* __OF_RESERVED_MEM_H */
Signature · 1 line
1.9.1
#5 lore raw

PATCH 3/6 serial: earlycon: add DT support

In reply to Rob Herring

From: Rob Herring <[email protected]>

This adds the infrastructure to generic earlycon for earlycon setup using DT. The actual setup is not enabled until a following commit to add the FDT parsing.

Cc Greg Kroah-Hartman <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Arnd Bergmann <[email protected]>
---
 drivers/tty/serial/earlycon.c     | 27 +++++++++++++++++++++++++++
 include/asm-generic/vmlinux.lds.h |  4 +++-
 include/linux/serial_core.h       |  6 ++++++
 3 files changed, 36 insertions(+), 1 deletion(-)
drivers/tty/serial/earlycon.c +27 -0
index c92e830..021fe5f 100644
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/serial_core.h>
+#include <linux/mod_devicetable.h>
 
 #ifdef CONFIG_FIX_EARLYCON_MEM
 #include <asm/fixmap.h>
@@ -32,6 +33,9 @@ static struct earlycon_device early_console_dev = {
 	.con = &early_con,
 };
 
+static const struct of_device_id __earlycon_of_table_sentinel
+	__used __section(__earlycon_of_table_end);
+
 static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
 {
 	void __iomem *base;
@@ -142,3 +146,26 @@ int __init setup_earlycon(char *buf, const char *match,
 	register_console(early_console_dev.con);
 	return 0;
 }
+
+int __init of_setup_earlycon(unsigned long addr,
+			     int (*setup)(struct earlycon_device *, const char *))
+{
+	int err;
+	struct uart_port *port = &early_console_dev.port;
+
+	port->iotype = UPIO_MEM;
+	port->mapbase = addr;
+	port->uartclk = BASE_BAUD * 16;
+	port->membase = earlycon_map(addr, SZ_4K);
+
+	early_console_dev.con->data = &early_console_dev;
+	err = setup(&early_console_dev, NULL);
+	if (err < 0)
+		return err;
+	if (!early_console_dev.con->write)
+		return -ENODEV;
+
+
+	register_console(early_console_dev.con);
+	return 0;
+}
include/asm-generic/vmlinux.lds.h +3 -1
index 120ccb9..f5249c4 100644
@@ -129,6 +129,7 @@
 #define CLK_OF_TABLES()		OF_TABLE(CONFIG_COMMON_CLK, clk)
 #define RESERVEDMEM_OF_TABLES()	OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem)
 #define CPU_METHOD_OF_TABLES()	OF_TABLE(CONFIG_SMP, cpu_method)
+#define EARLYCON_OF_TABLES()	OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
 
 #define KERNEL_DTB()							\
 	STRUCT_ALIGN();							\
@@ -458,7 +459,8 @@
 	CLKSRC_OF_TABLES()						\
 	CPU_METHOD_OF_TABLES()						\
 	KERNEL_DTB()							\
-	IRQCHIP_OF_MATCH_TABLE()
+	IRQCHIP_OF_MATCH_TABLE()					\
+	EARLYCON_OF_TABLES()
 
 #define INIT_TEXT							\
 	*(.init.text)							\
include/linux/serial_core.h +6 -0
index 7a15b5b..5bbb809 100644
@@ -294,6 +294,9 @@ struct earlycon_device {
 int setup_earlycon(char *buf, const char *match,
 		   int (*setup)(struct earlycon_device *, const char *));
 
+extern int of_setup_earlycon(unsigned long addr,
+			     int (*setup)(struct earlycon_device *, const char *));
+
 #define EARLYCON_DECLARE(name, func) \
 static int __init name ## _setup_earlycon(char *buf) \
 { \
@@ -301,6 +304,9 @@ static int __init name ## _setup_earlycon(char *buf) \
 } \
 early_param("earlycon", name ## _setup_earlycon);
 
+#define OF_EARLYCON_DECLARE(name, compat, fn)				\
+	_OF_DECLARE(earlycon, name, compat, fn, void *)
+
 struct uart_port *uart_get_console(struct uart_port *ports, int nr,
 				   struct console *c);
 void uart_parse_options(char *options, int *baud, int *parity, int *bits,
Signature · 1 line
1.9.1
#6 lore raw

PATCH 4/6 of/fdt: add FDT address translation support

In reply to Rob Herring

From: Rob Herring <[email protected]>

Copy u-boot's FDT address translation code from common/fdt_support. This code was originally based on the kernel's unflattened DT address parsing code.

This commit can be reverted once relicensing of this code to GPLv2/BSD is done and it is added to libfdt.

---
 drivers/of/Makefile      |   2 +
 drivers/of/fdt_address.c | 241 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_fdt.h   |   1 +
 3 files changed, 244 insertions(+)
 create mode 100644 drivers/of/fdt_address.c
drivers/of/Makefile +2 -0
index 9891232..099b1fb 100644
@@ -1,5 +1,6 @@
 obj-y = base.o device.o platform.o
 obj-$(CONFIG_OF_FLATTREE) += fdt.o
+obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
 obj-$(CONFIG_OF_PROMTREE) += pdt.o
 obj-$(CONFIG_OF_ADDRESS)  += address.o
 obj-$(CONFIG_OF_IRQ)    += irq.o
@@ -12,3 +13,4 @@ obj-$(CONFIG_OF_MTD)	+= of_mtd.o
 obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
 
 CFLAGS_fdt.o = -I$(src)/../../scripts/dtc/libfdt
+CFLAGS_fdt_address.o = -I$(src)/../../scripts/dtc/libfdt
drivers/of/fdt_address.c new file +241 -0

241 lines not on this page · raw message

include/linux/of_fdt.h +1 -0
index 5c0ab05..0511789 100644
@@ -83,6 +83,7 @@ extern void unflatten_device_tree(void);
 extern void unflatten_and_copy_device_tree(void);
 extern void early_init_devtree(void *);
 extern void early_get_first_memblock_info(void *, phys_addr_t *);
+extern u64 fdt_translate_address(const void *blob, int node_offset);
 #else /* CONFIG_OF_FLATTREE */
 static inline void early_init_fdt_scan_reserved_mem(void) {}
 static inline const char *of_flat_dt_get_machine_name(void) { return NULL; }
Signature · 1 line
1.9.1
#7 lore raw

PATCH 5/6 of/fdt: add FDT serial scanning for earlycon

In reply to Rob Herring

From: Rob Herring <[email protected]>

This adds FDT parsing of {linux,}stdout-path to setup an early serial console. Enabling of the early console is triggered with "earlycon" (with no options) on the kernel command line.

Platforms must either have fixmap permanent mapping support, have a functioning ioremap when early params are parsed, or explicitly call early_init_dt_scan_chosen_serial from architecture code.

---
 drivers/of/fdt.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)
drivers/of/fdt.c +56 -0
index a6f83ea..1fbeab2 100644
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/libfdt.h>
 #include <linux/debugfs.h>
+#include <linux/serial_core.h>
 
 #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
 #include <asm/page.h>
@@ -696,6 +697,61 @@ static inline void early_init_dt_check_for_initrd(unsigned long node)
 }
 #endif /* CONFIG_BLK_DEV_INITRD */
 
+#ifdef CONFIG_SERIAL_EARLYCON
+extern struct of_device_id __earlycon_of_table[];
+
+int __init early_init_dt_scan_chosen_serial(void)
+{
+	int offset;
+	const char *p;
+	int l;
+	const struct of_device_id *match = __earlycon_of_table;
+	const void *fdt = initial_boot_params;
+
+	offset = fdt_path_offset(fdt, "/chosen");
+	if (offset < 0)
+		offset = fdt_path_offset(fdt, "/chosen@0");
+	if (offset < 0)
+		return -ENOENT;
+
+	p = fdt_getprop(fdt, offset, "stdout-path", &l);
+	if (!p)
+		p = fdt_getprop(fdt, offset, "linux,stdout-path", &l);
+	if (!p || !l)
+		return -ENOENT;
+
+	/* Get the node specified by stdout-path */
+	offset = fdt_path_offset(fdt, p);
+	if (offset < 0)
+		return -ENODEV;
+
+	while (match->compatible) {
+		unsigned long addr;
+		if (fdt_node_check_compatible(fdt, offset, match->compatible)) {
+			match++;
+			continue;
+		}
+
+		addr = fdt_translate_address(fdt, offset);
+		if (!addr)
+			return -ENXIO;
+
+		of_setup_earlycon(addr, match->data);
+		return 0;
+	}
+	return -ENODEV;
+}
+
+static int __init setup_of_earlycon(char *buf)
+{
+	if (buf)
+		return 0;
+
+	return early_init_dt_scan_chosen_serial();
+}
+early_param("earlycon", setup_of_earlycon);
+#endif
+
 /**
  * early_init_dt_scan_root - fetch the top level address and size cells
  */
Signature · 1 line
1.9.1
#8 lore raw

PATCH 6/6 tty/serial: pl011: add DT based earlycon support

In reply to Rob Herring

From: Rob Herring <[email protected]>

Enable DT based earlycon initialization for the pl011 uart.

Cc Russell King <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Jiri Slaby <[email protected]>
---
 drivers/tty/serial/amba-pl011.c | 1 +
 1 file changed, 1 insertion(+)
drivers/tty/serial/amba-pl011.c +1 -0
index ee3d803..908a6e3 100644
@@ -2072,6 +2072,7 @@ static int __init pl011_early_console_setup(struct earlycon_device *device,
 	return 0;
 }
 EARLYCON_DECLARE(pl011, pl011_early_console_setup);
+OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup);
 
 #else
 #define AMBA_CONSOLE	NULL
Signature · 1 line
1.9.1
Acked-by on the v1 series
#9 lore raw
In reply to Rob Herring
Quoted 12 lines · Rob Herring

From: Rob Herring <[email protected]>

This series adds support for early serial console initialization using DT. This enables determining the serial port type and address using the FDT and allows enabling the console before platform specific initialization runs. I've tested this on arm64. ARM support is dependent on adding fixmap support.

Currently, the earlycon is only enabled if "earlycon" is present on the kernel command line. The FDT needs to have /chosen/stdout-path set to the path of the serial port.

Quoted 5 lines

This series is dependent on generic earlycon[1], libfdt support[2], and vmlinux.lds.h clean-ups[3]. The first 2 are in linux-next already. A git branch is available here:

git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git earlycon-dt

Nice. For the whole series:

I haven't tested it though.

Quoted 36 lines

Rob

[1] https://lkml.org/lkml/2014/4/18/573
[2] https://lkml.org/lkml/2014/4/22/1202
[3] https://lkml.org/lkml/2014/3/27/285

Rob Herring (6):
of: align RESERVEDMEM_OF_DECLARE function callbacks to other callbacks
of: consolidate linker section OF match table declarations
serial: earlycon: add DT support
of/fdt: add FDT address translation support
of/fdt: add FDT serial scanning for earlycon
tty/serial: pl011: add DT based earlycon support

 drivers/clocksource/clksrc-of.c   |   2 +-
 drivers/irqchip/irqchip.h         |   7 +-
 drivers/of/Makefile               |   2 +
 drivers/of/fdt.c                  |  56 +++++++++
 drivers/of/fdt_address.c          | 241 ++++++++++++++++++++++++++++++++++++++
 drivers/of/of_reserved_mem.c      |   2 +-
 drivers/tty/serial/amba-pl011.c   |   1 +
 drivers/tty/serial/earlycon.c     |  27 +++++
 include/asm-generic/vmlinux.lds.h |   4 +-
 include/linux/clk-provider.h      |   5 +-
 include/linux/clocksource.h       |  16 +--
 include/linux/of.h                |  22 ++++
 include/linux/of_fdt.h            |   1 +
 include/linux/of_reserved_mem.h   |  22 +---
 include/linux/serial_core.h       |   6 +
 15 files changed, 372 insertions(+), 42 deletions(-)
 create mode 100644 drivers/of/fdt_address.c
Signature · 1 line
1.9.1
#10 lore raw
Quoted 17 lines · Grant Likely
Quoted 16 lines · Rob Herring

From: Rob Herring <[email protected]>

This series adds support for early serial console initialization using DT. This enables determining the serial port type and address using the FDT and allows enabling the console before platform specific initialization runs. I've tested this on arm64. ARM support is dependent on adding fixmap support.

Currently, the earlycon is only enabled if "earlycon" is present on the kernel command line. The FDT needs to have /chosen/stdout-path set to the path of the serial port.

This series is dependent on generic earlycon[1], libfdt support[2], and vmlinux.lds.h clean-ups[3]. The first 2 are in linux-next already. A git branch is available here:

Quoted 21 lines
Quoted 1 line

git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git earlycon-dt

Nice. For the whole series:

I haven't tested it though.

Quoted 14 lines

Rob

[1] https://lkml.org/lkml/2014/4/18/573
[2] https://lkml.org/lkml/2014/4/22/1202
[3] https://lkml.org/lkml/2014/3/27/285

Rob Herring (6):
of: align RESERVEDMEM_OF_DECLARE function callbacks to other callbacks
of: consolidate linker section OF match table declarations
serial: earlycon: add DT support
of/fdt: add FDT address translation support
of/fdt: add FDT serial scanning for earlycon
tty/serial: pl011: add DT based earlycon support

Greg, I plan to take this series thru the DT tree for 3.16 unless you have any objections. It has dependencies on both the tty-next and the DT trees.

Rob

#11 lore raw
Quoted 40 lines · Rob Herring
Quoted 17 lines · Grant Likely
Quoted 16 lines · Rob Herring

From: Rob Herring <[email protected]>

This series adds support for early serial console initialization using DT. This enables determining the serial port type and address using the FDT and allows enabling the console before platform specific initialization runs. I've tested this on arm64. ARM support is dependent on adding fixmap support.

Currently, the earlycon is only enabled if "earlycon" is present on the kernel command line. The FDT needs to have /chosen/stdout-path set to the path of the serial port.

This series is dependent on generic earlycon[1], libfdt support[2], and vmlinux.lds.h clean-ups[3]. The first 2 are in linux-next already. A git branch is available here:

Quoted 21 lines
Quoted 1 line

git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git earlycon-dt

Nice. For the whole series:

I haven't tested it though.

Quoted 14 lines

Rob

[1] https://lkml.org/lkml/2014/4/18/573
[2] https://lkml.org/lkml/2014/4/22/1202
[3] https://lkml.org/lkml/2014/3/27/285

Rob Herring (6):
of: align RESERVEDMEM_OF_DECLARE function callbacks to other callbacks
of: consolidate linker section OF match table declarations
serial: earlycon: add DT support
of/fdt: add FDT address translation support
of/fdt: add FDT serial scanning for earlycon
tty/serial: pl011: add DT based earlycon support

Quoted 3 lines

Greg, I plan to take this series thru the DT tree for 3.16 unless you have any objections. It has dependencies on both the tty-next and the DT trees.

No objection from me at all, feel free to do so.

greg k-h