summaryrefslogtreecommitdiffstats
path: root/target/linux/lantiq/patches/106-early_printk.patch
blob: 34e0bdf4d22ac66689adceb5bf8efa30177c19b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -33,4 +33,19 @@ endchoice
 source "arch/mips/lantiq/falcon/Kconfig"
 source "arch/mips/lantiq/xway/Kconfig"
 
+if EARLY_PRINTK
+choice
+	prompt "Early printk port"
+	default LANTIQ_PROM_ASC1
+	help
+	  Choose which serial port is used, until the console driver is loaded
+
+config LANTIQ_PROM_ASC0
+	bool "ASC0"
+
+config LANTIQ_PROM_ASC1
+	bool "ASC1"
+endchoice
+endif
+
 endif
--- /dev/null
+++ b/arch/mips/lantiq/early_printk.c
@@ -0,0 +1,68 @@
+/*
+ *  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.
+ *
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/cpu.h>
+
+#include <lantiq.h>
+
+#ifdef CONFIG_SOC_LANTIQ_XWAY
+#include <xway.h>
+#ifdef CONFIG_LANTIQ_PROM_ASC0
+#define LQ_ASC_BASE	KSEG1ADDR(LQ_ASC0_BASE)
+#else
+#define LQ_ASC_BASE	KSEG1ADDR(LQ_ASC1_BASE)
+#endif
+
+#elif CONFIG_SOC_LANTIQ_FALCON
+#include <falcon/gpon_reg_base.h>
+#ifdef CONFIG_LANTIQ_PROM_ASC0
+#define LQ_ASC_BASE	GPON_ASC0_BASE
+#else
+#define LQ_ASC_BASE	GPON_ASC1_BASE
+#endif
+
+#endif
+
+#define ASC_BUF				1024
+#define LQ_ASC_FSTAT		0x0048
+#define LQ_ASC_TBUF			0x0020
+#define TXMASK				0x3F00
+#define TXOFFSET			8
+
+static char buf[ASC_BUF];
+
+void
+prom_putchar(char c)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	while ((lq_r32((u32 *)(LQ_ASC_BASE + LQ_ASC_FSTAT)) & TXMASK) >> TXOFFSET);
+
+	if (c == '\n')
+		lq_w32('\r', (u32 *)(LQ_ASC_BASE + LQ_ASC_TBUF));
+	lq_w32(c, (u32 *)(LQ_ASC_BASE + LQ_ASC_TBUF));
+	local_irq_restore(flags);
+}
+
+void
+early_printf(const char *fmt, ...)
+{
+	va_list args;
+	int l;
+	char *p, *buf_end;
+
+	va_start(args, fmt);
+	l = vsnprintf(buf, ASC_BUF, fmt, args);
+	va_end(args);
+	buf_end = buf + l;
+
+	for (p = buf; p < buf_end; p++)
+		prom_putchar(*p);
+}