Add basic support for mini2440 board to barebox.
[barebox-mini2440.git] / common / console.c
blob7199d9afb85c9e02a6d1883fa1b8d77aac142242
1 /*
2 * (C) Copyright 2000
3 * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
5 * See file CREDITS for list of people who contributed to this
6 * project.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
24 #include <config.h>
25 #include <common.h>
26 #include <stdarg.h>
27 #include <malloc.h>
28 #include <param.h>
29 #include <console.h>
30 #include <driver.h>
31 #include <fs.h>
32 #include <reloc.h>
33 #include <init.h>
34 #include <clock.h>
35 #include <kfifo.h>
36 #include <module.h>
37 #include <linux/list.h>
39 LIST_HEAD(console_list);
40 EXPORT_SYMBOL(console_list);
42 #define CONSOLE_UNINITIALIZED 0
43 #define CONSOLE_INIT_EARLY 1
44 #define CONSOLE_INIT_FULL 2
46 extern char version_string[];
48 static void display_banner (void)
50 printf (RELOC("\n\n%s\n\n"), RELOC_VAR(version_string));
51 printf(RELOC("Board: " CONFIG_BOARDINFO "\n"));
54 static int __initdata initialized = 0;
56 static int console_std_set(struct device_d *dev, struct param_d *param,
57 const char *val)
59 struct console_device *cdev = dev->type_data;
60 char active[4];
61 unsigned int flag = 0, i = 0;
63 if (!val)
64 dev_param_set_generic(dev, param, NULL);
66 if (strchr(val, 'i') && cdev->f_caps & CONSOLE_STDIN) {
67 active[i++] = 'i';
68 flag |= CONSOLE_STDIN;
71 if (strchr(val, 'o') && cdev->f_caps & CONSOLE_STDOUT) {
72 active[i++] = 'o';
73 flag |= CONSOLE_STDOUT;
76 if (strchr(val, 'e') && cdev->f_caps & CONSOLE_STDERR) {
77 active[i++] = 'e';
78 flag |= CONSOLE_STDERR;
81 active[i] = 0;
82 cdev->f_active = flag;
84 dev_param_set_generic(dev, param, active);
86 return 0;
89 static int console_baudrate_set(struct device_d *dev, struct param_d *param,
90 const char *val)
92 struct console_device *cdev = dev->type_data;
93 int baudrate;
94 char baudstr[16];
95 unsigned char c;
97 if (!val)
98 dev_param_set_generic(dev, param, NULL);
100 baudrate = simple_strtoul(val, NULL, 10);
102 if (cdev->f_active) {
103 printf("## Switch baudrate to %d bps and press ENTER ...\n",
104 baudrate);
105 mdelay(50);
106 cdev->setbrg(cdev, baudrate);
107 mdelay(50);
108 do {
109 c = getc();
110 } while (c != '\r' && c != '\n');
111 } else
112 cdev->setbrg(cdev, baudrate);
114 sprintf(baudstr, "%d", baudrate);
115 dev_param_set_generic(dev, param, baudstr);
117 return 0;
120 static struct kfifo *console_input_buffer;
121 static struct kfifo *console_output_buffer;
123 int getc_buffer_flush(void)
125 console_input_buffer = kfifo_alloc(1024);
126 console_output_buffer = kfifo_alloc(1024);
127 return 0;
130 postcore_initcall(getc_buffer_flush);
132 int console_register(struct console_device *newcdev)
134 struct device_d *dev = &newcdev->class_dev;
135 int first = 0;
136 char ch;
138 strcpy(dev->name, "cs");
139 dev->type_data = newcdev;
140 register_device(dev);
142 if (newcdev->setbrg) {
143 dev_add_param(dev, "baudrate", console_baudrate_set, NULL, 0);
144 dev_set_param(dev, "baudrate", "115200");
147 dev_add_param(dev, "active", console_std_set, NULL, 0);
149 initialized = CONSOLE_INIT_FULL;
150 #ifdef CONFIG_CONSOLE_ACTIVATE_ALL
151 dev_set_param(dev, "active", "ioe");
152 #endif
153 #ifdef CONFIG_CONSOLE_ACTIVATE_FIRST
154 if (list_empty(&console_list)) {
155 first = 1;
156 dev_set_param(dev, "active", "ioe");
158 #endif
160 list_add_tail(&newcdev->list, &console_list);
162 if (console_output_buffer) {
163 while (kfifo_getc(console_output_buffer, &ch) == 0)
164 console_putc(CONSOLE_STDOUT, ch);
165 kfifo_free(console_output_buffer);
166 console_output_buffer = NULL;
169 #ifndef CONFIG_HAS_EARLY_INIT
170 if (first)
171 display_banner();
172 #endif
174 return 0;
176 EXPORT_SYMBOL(console_register);
178 static int getc_raw(void)
180 struct console_device *cdev;
181 int active = 0;
183 while (1) {
184 for_each_console(cdev) {
185 if (!(cdev->f_active & CONSOLE_STDIN))
186 continue;
187 active = 1;
188 if (cdev->tstc(cdev))
189 return cdev->getc(cdev);
191 if (!active)
192 /* no active console found. bail out */
193 return -1;
197 int getc(void)
199 unsigned char ch;
200 uint64_t start;
203 * For 100us we read the characters from the serial driver
204 * into a kfifo. This helps us not to lose characters
205 * in small hardware fifos.
207 start = get_time_ns();
208 while (1) {
209 if (tstc()) {
210 kfifo_putc(console_input_buffer, getc_raw());
212 start = get_time_ns();
214 if (is_timeout(start, 100 * USECOND) &&
215 kfifo_len(console_input_buffer))
216 break;
219 kfifo_getc(console_input_buffer, &ch);
220 return ch;
222 EXPORT_SYMBOL(getc);
224 int fgetc(int fd)
226 char c;
228 if (!fd)
229 return getc();
230 return read(fd, &c, 1);
232 EXPORT_SYMBOL(fgetc);
234 int tstc(void)
236 struct console_device *cdev;
238 for_each_console(cdev) {
239 if (!(cdev->f_active & CONSOLE_STDIN))
240 continue;
241 if (cdev->tstc(cdev))
242 return 1;
245 return 0;
247 EXPORT_SYMBOL(tstc);
249 void __initdata *early_console_base;
251 void console_putc(unsigned int ch, char c)
253 struct console_device *cdev;
254 int init = INITDATA(initialized);
256 switch (init) {
257 case CONSOLE_UNINITIALIZED:
258 kfifo_putc(console_output_buffer, c);
259 return;
261 #ifdef CONFIG_HAS_EARLY_INIT
262 case CONSOLE_INIT_EARLY:
263 early_console_putc(INITDATA(early_console_base), c);
264 return;
265 #endif
267 case CONSOLE_INIT_FULL:
268 for_each_console(cdev) {
269 if (cdev->f_active & ch) {
270 if (c == '\n')
271 cdev->putc(cdev, '\r');
272 cdev->putc(cdev, c);
275 return;
276 default:
277 /* If we have problems inititalizing our data
278 * get them early
280 hang();
283 EXPORT_SYMBOL(console_putc);
285 int fputc(int fd, char c)
287 if(list_empty(&console_list)) {
288 if(!fd)
289 console_putc(0, c);
290 return 0;
293 if (fd == 1)
294 putchar(c);
295 else if (fd == 2)
296 eputc(c);
297 else
298 return write(fd, &c, 1);
299 return 0;
301 EXPORT_SYMBOL(fputc);
303 void console_puts(unsigned int ch, const char *str)
305 const char *s = str;
306 while (*s) {
307 if (*s == '\n')
308 console_putc(ch, '\r');
309 console_putc(ch, *s);
310 s++;
313 EXPORT_SYMBOL(console_puts);
315 int fputs(int fd, const char *s)
317 if (fd == 1)
318 puts(s);
319 else if (fd == 2)
320 eputs(s);
321 else
322 return write(fd, s, strlen(s));
323 return 0;
325 EXPORT_SYMBOL(fputs);
327 void console_flush(void)
329 struct console_device *cdev;
331 for_each_console(cdev) {
332 if (cdev->flush)
333 cdev->flush(cdev);
336 EXPORT_SYMBOL(console_flush);
338 void fprintf (int file, const char *fmt, ...)
340 va_list args;
341 uint i;
342 char printbuffer[CFG_PBSIZE];
344 va_start (args, fmt);
346 /* For this to work, printbuffer must be larger than
347 * anything we ever want to print.
349 i = vsprintf (printbuffer, fmt, args);
350 va_end (args);
352 /* Print the string */
353 fputs (file, printbuffer);
355 EXPORT_SYMBOL(fprintf);
357 int printf (const char *fmt, ...)
359 va_list args;
360 uint i;
361 char printbuffer[CFG_PBSIZE];
363 va_start (args, fmt);
365 /* For this to work, printbuffer must be larger than
366 * anything we ever want to print.
368 i = vsprintf (printbuffer, fmt, args);
369 va_end (args);
371 /* Print the string */
372 puts (printbuffer);
374 return i;
376 EXPORT_SYMBOL(printf);
378 int vprintf (const char *fmt, va_list args)
380 uint i;
381 char printbuffer[CFG_PBSIZE];
383 /* For this to work, printbuffer must be larger than
384 * anything we ever want to print.
386 i = vsprintf (printbuffer, fmt, args);
388 /* Print the string */
389 puts (printbuffer);
391 return i;
393 EXPORT_SYMBOL(vprintf);
395 #ifndef ARCH_HAS_CTRLC
396 /* test if ctrl-c was pressed */
397 int ctrlc (void)
399 if (tstc() && getc() == 3)
400 return 1;
401 return 0;
403 EXPORT_SYMBOL(ctrlc);
404 #endif /* ARCH_HAS_CTRC */
406 #ifdef CONFIG_HAS_EARLY_INIT
408 void early_console_start(const char *name, int baudrate)
410 void *base = get_early_console_base(name);
412 if (base) {
413 early_console_init(base, baudrate);
414 INITDATA(initialized) = CONSOLE_INIT_EARLY;
415 INITDATA(early_console_base) = base;
416 display_banner();
420 #endif