import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / mips / mips-boards / generic / printf.c
1 /*
2  * Carsten Langgaard, carstenl@mips.com
3  * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
4  *
5  *  This program is free software; you can distribute it and/or modify it
6  *  under the terms of the GNU General Public License (Version 2) as
7  *  published by the Free Software Foundation.
8  *
9  *  This program is distributed in the hope it will be useful, but WITHOUT
10  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  *  for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17  *
18  * Putting things on the screen/serial line using YAMONs facilities.
19  */
20 #include <linux/config.h>
21 #include <linux/init.h>
22 #include <linux/kernel.h>
23 #include <linux/serial_reg.h>
24 #include <linux/spinlock.h>
25 #include <asm/io.h>
26
27 #ifdef CONFIG_MIPS_ATLAS
28
29 #include <asm/mips-boards/atlas.h>
30
31 /*
32  * Atlas registers are memory mapped on 64-bit aligned boundaries and
33  * only word access are allowed.
34  * When reading the UART 8 bit registers only the LSB are valid.
35  */
36 static inline unsigned int serial_in(int offset)
37 {
38         return (*(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) & 0xff);
39 }
40
41 static inline void serial_out(int offset, int value)
42 {
43         *(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) = value;
44 }
45
46 #elif defined(CONFIG_MIPS_SEAD)
47
48 #include <asm/mips-boards/sead.h>
49
50 /*
51  * SEAD registers are just like Atlas registers.
52  */
53 static inline unsigned int serial_in(int offset)
54 {
55         return (*(volatile unsigned int *)(mips_io_port_base + SEAD_UART0_REGS_BASE + offset*8) & 0xff);
56 }
57
58 static inline void serial_out(int offset, int value)
59 {
60         *(volatile unsigned int *)(mips_io_port_base + SEAD_UART0_REGS_BASE + offset*8) = value;
61 }
62
63 #else
64
65 static inline unsigned int serial_in(int offset)
66 {
67         return inb(0x3f8 + offset);
68 }
69
70 static inline void serial_out(int offset, int value)
71 {
72         outb(value, 0x3f8 + offset);
73 }
74 #endif
75
76 int putPromChar(char c)
77 {
78         while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
79                 ;
80
81         serial_out(UART_TX, c);
82
83         return 1;
84 }
85
86 char getPromChar(void)
87 {
88         while (!(serial_in(UART_LSR) & 1))
89                 ;
90
91         return serial_in(UART_RX);
92 }
93
94 static spinlock_t con_lock = SPIN_LOCK_UNLOCKED;
95
96 static char buf[1024];
97
98 void __init prom_printf(char *fmt, ...)
99 {
100         va_list args;
101         int l;
102         char *p, *buf_end;
103         long flags;
104
105         int putPromChar(char);
106
107         spin_lock_irqsave(con_lock, flags);
108         va_start(args, fmt);
109         l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
110         va_end(args);
111
112         buf_end = buf + l;
113
114         for (p = buf; p < buf_end; p++) {
115                 /* Crude cr/nl handling is better than none */
116                 if (*p == '\n')
117                         putPromChar('\r');
118                 putPromChar(*p);
119         }
120         spin_unlock_irqrestore(con_lock, flags);
121 }