• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * File:         arch/blackfin/kernel/early_printk.c
3  * Based on:     arch/x86_64/kernel/early_printk.c
4  * Author:       Robin Getz <rgetz@blackfin.uclinux.org
5  *
6  * Created:      14Aug2007
7  * Description:  allow a console to be used for early printk
8  *
9  * Modified:
10  *               Copyright 2004-2007 Analog Devices Inc.
11  *
12  * Bugs:         Enter bugs at http://blackfin.uclinux.org/
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  */
24 
25 #include <linux/kernel.h>
26 #include <linux/init.h>
27 #include <linux/serial_core.h>
28 #include <linux/console.h>
29 #include <linux/string.h>
30 #include <asm/blackfin.h>
31 #include <asm/irq_handler.h>
32 #include <asm/early_printk.h>
33 
34 #ifdef CONFIG_SERIAL_BFIN
35 extern struct console *bfin_earlyserial_init(unsigned int port,
36 						unsigned int cflag);
37 #endif
38 #ifdef CONFIG_BFIN_JTAG_COMM
39 extern struct console *bfin_jc_early_init(void);
40 #endif
41 
42 static struct console *early_console;
43 
44 /* Default console */
45 #define DEFAULT_PORT 0
46 #define DEFAULT_CFLAG CS8|B57600
47 
48 /* Default console for early crashes */
49 #define DEFAULT_EARLY_PORT "serial,uart0,57600"
50 
51 #ifdef CONFIG_SERIAL_CORE
52 /* What should get here is "0,57600" */
earlyserial_init(char * buf)53 static struct console * __init earlyserial_init(char *buf)
54 {
55 	int baud, bit;
56 	char parity;
57 	unsigned int serial_port = DEFAULT_PORT;
58 	unsigned int cflag = DEFAULT_CFLAG;
59 
60 	serial_port = simple_strtoul(buf, &buf, 10);
61 	buf++;
62 
63 	cflag = 0;
64 	baud = simple_strtoul(buf, &buf, 10);
65 	switch (baud) {
66 	case 1200:
67 		cflag |= B1200;
68 		break;
69 	case 2400:
70 		cflag |= B2400;
71 		break;
72 	case 4800:
73 		cflag |= B4800;
74 		break;
75 	case 9600:
76 		cflag |= B9600;
77 		break;
78 	case 19200:
79 		cflag |= B19200;
80 		break;
81 	case 38400:
82 		cflag |= B38400;
83 		break;
84 	case 115200:
85 		cflag |= B115200;
86 		break;
87 	default:
88 		cflag |= B57600;
89 	}
90 
91 	parity = buf[0];
92 	buf++;
93 	switch (parity) {
94 	case 'e':
95 		cflag |= PARENB;
96 		break;
97 	case 'o':
98 		cflag |= PARODD;
99 		break;
100 	}
101 
102 	bit = simple_strtoul(buf, &buf, 10);
103 	switch (bit) {
104 	case 5:
105 		cflag |= CS5;
106 		break;
107 	case 6:
108 		cflag |= CS6;
109 		break;
110 	case 7:
111 		cflag |= CS7;
112 		break;
113 	default:
114 		cflag |= CS8;
115 	}
116 
117 #ifdef CONFIG_SERIAL_BFIN
118 	return bfin_earlyserial_init(serial_port, cflag);
119 #else
120 	return NULL;
121 #endif
122 
123 }
124 #endif
125 
setup_early_printk(char * buf)126 int __init setup_early_printk(char *buf)
127 {
128 
129 	/* Crashing in here would be really bad, so check both the var
130 	   and the pointer before we start using it
131 	 */
132 	if (!buf)
133 		return 0;
134 
135 	if (!*buf)
136 		return 0;
137 
138 	if (early_console != NULL)
139 		return 0;
140 
141 #ifdef CONFIG_SERIAL_BFIN
142 	/* Check for Blackfin Serial */
143 	if (!strncmp(buf, "serial,uart", 11)) {
144 		buf += 11;
145 		early_console = earlyserial_init(buf);
146 	}
147 #endif
148 
149 #ifdef CONFIG_BFIN_JTAG_COMM
150 	/* Check for Blackfin JTAG */
151 	if (!strncmp(buf, "jtag", 4)) {
152 		buf += 4;
153 		early_console = bfin_jc_early_init();
154 	}
155 #endif
156 
157 #ifdef CONFIG_FB
158 		/* TODO: add framebuffer console support */
159 #endif
160 
161 	if (likely(early_console)) {
162 		early_console->flags |= CON_BOOT;
163 
164 		register_console(early_console);
165 		printk(KERN_INFO "early printk enabled on %s%d\n",
166 			early_console->name,
167 			early_console->index);
168 	}
169 
170 	return 0;
171 }
172 
173 /*
174  * Set up a temporary Event Vector Table, so if something bad happens before
175  * the kernel is fully started, it doesn't vector off into somewhere we don't
176  * know
177  */
178 
init_early_exception_vectors(void)179 asmlinkage void __init init_early_exception_vectors(void)
180 {
181 	SSYNC();
182 
183 	/* cannot program in software:
184 	 * evt0 - emulation (jtag)
185 	 * evt1 - reset
186 	 */
187 	bfin_write_EVT2(early_trap);
188 	bfin_write_EVT3(early_trap);
189 	bfin_write_EVT5(early_trap);
190 	bfin_write_EVT6(early_trap);
191 	bfin_write_EVT7(early_trap);
192 	bfin_write_EVT8(early_trap);
193 	bfin_write_EVT9(early_trap);
194 	bfin_write_EVT10(early_trap);
195 	bfin_write_EVT11(early_trap);
196 	bfin_write_EVT12(early_trap);
197 	bfin_write_EVT13(early_trap);
198 	bfin_write_EVT14(early_trap);
199 	bfin_write_EVT15(early_trap);
200 	CSYNC();
201 
202 	/* Set all the return from interrupt, exception, NMI to a known place
203 	 * so if we do a RETI, RETX or RETN by mistake - we go somewhere known
204 	 * Note - don't change RETS - we are in a subroutine, or
205 	 * RETE - since it might screw up if emulator is attached
206 	 */
207 	asm("\tRETI = %0; RETX = %0; RETN = %0;\n"
208 		: : "p"(early_trap));
209 
210 }
211 
early_trap_c(struct pt_regs * fp,void * retaddr)212 asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)
213 {
214 	/* This can happen before the uart is initialized, so initialize
215 	 * the UART now
216 	 */
217 	if (likely(early_console == NULL))
218 		setup_early_printk(DEFAULT_EARLY_PORT);
219 
220 	dump_bfin_mem(fp);
221 	show_regs(fp);
222 	dump_bfin_trace_buffer();
223 
224 	panic("Died early");
225 }
226 
227 early_param("earlyprintk", setup_early_printk);
228