]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc5xxx/serial.c
patman: Allow use outside of u-boot tree
[karo-tx-uboot.git] / arch / powerpc / cpu / mpc5xxx / serial.c
1 /*
2  * (C) Copyright 2000 - 2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
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.
12  *
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.
17  *
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
22  *
23  * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
24  * changes based on the file arch/powerpc/mbxboot/m8260_tty.c from the
25  * Linux/PPC sources (m8260_tty.c had no copyright info in it).
26  *
27  * Martin Krause, 8 Jun 2006
28  * Added SERIAL_MULTI support
29  */
30
31 /*
32  * Minimal serial functions needed to use one of the PSC ports
33  * as serial console interface.
34  */
35
36 #include <common.h>
37 #include <linux/compiler.h>
38 #include <mpc5xxx.h>
39 #include <serial.h>
40
41 DECLARE_GLOBAL_DATA_PTR;
42
43 #if defined(CONFIG_PSC_CONSOLE)
44
45 #if CONFIG_PSC_CONSOLE == 1
46 #define PSC_BASE MPC5XXX_PSC1
47 #elif CONFIG_PSC_CONSOLE == 2
48 #define PSC_BASE MPC5XXX_PSC2
49 #elif CONFIG_PSC_CONSOLE == 3
50 #define PSC_BASE MPC5XXX_PSC3
51 #elif CONFIG_PSC_CONSOLE == 4
52 #define PSC_BASE MPC5XXX_PSC4
53 #elif CONFIG_PSC_CONSOLE == 5
54 #define PSC_BASE MPC5XXX_PSC5
55 #elif CONFIG_PSC_CONSOLE == 6
56 #define PSC_BASE MPC5XXX_PSC6
57 #else
58 #error CONFIG_PSC_CONSOLE must be in 1 ... 6
59 #endif
60
61 #if defined(CONFIG_PSC_CONSOLE2)
62
63 #if CONFIG_PSC_CONSOLE2 == 1
64 #define PSC_BASE2 MPC5XXX_PSC1
65 #elif CONFIG_PSC_CONSOLE2 == 2
66 #define PSC_BASE2 MPC5XXX_PSC2
67 #elif CONFIG_PSC_CONSOLE2 == 3
68 #define PSC_BASE2 MPC5XXX_PSC3
69 #elif CONFIG_PSC_CONSOLE2 == 4
70 #define PSC_BASE2 MPC5XXX_PSC4
71 #elif CONFIG_PSC_CONSOLE2 == 5
72 #define PSC_BASE2 MPC5XXX_PSC5
73 #elif CONFIG_PSC_CONSOLE2 == 6
74 #define PSC_BASE2 MPC5XXX_PSC6
75 #else
76 #error CONFIG_PSC_CONSOLE2 must be in 1 ... 6
77 #endif
78
79 #endif
80
81 int serial_init_dev (unsigned long dev_base)
82 {
83         volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
84         unsigned long baseclk;
85         int div;
86
87         /* reset PSC */
88         psc->command = PSC_SEL_MODE_REG_1;
89
90         /* select clock sources */
91         psc->psc_clock_select = 0;
92         baseclk = (gd->ipb_clk + 16) / 32;
93
94         /* switch to UART mode */
95         psc->sicr = 0;
96
97         /* configure parity, bit length and so on */
98         psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
99         psc->mode = PSC_MODE_ONE_STOP;
100
101         /* set up UART divisor */
102         div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
103         psc->ctur = (div >> 8) & 0xff;
104         psc->ctlr = div & 0xff;
105
106         /* disable all interrupts */
107         psc->psc_imr = 0;
108
109         /* reset and enable Rx/Tx */
110         psc->command = PSC_RST_RX;
111         psc->command = PSC_RST_TX;
112         psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
113
114         return (0);
115 }
116
117 void serial_putc_dev (unsigned long dev_base, const char c)
118 {
119         volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
120
121         if (c == '\n')
122                 serial_putc_dev (dev_base, '\r');
123
124         /* Wait for last character to go. */
125         while (!(psc->psc_status & PSC_SR_TXEMP))
126                 ;
127
128         psc->psc_buffer_8 = c;
129 }
130
131 void serial_putc_raw_dev(unsigned long dev_base, const char c)
132 {
133         volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
134         /* Wait for last character to go. */
135         while (!(psc->psc_status & PSC_SR_TXEMP))
136                 ;
137
138         psc->psc_buffer_8 = c;
139 }
140
141
142 void serial_puts_dev (unsigned long dev_base, const char *s)
143 {
144         while (*s) {
145                 serial_putc_dev (dev_base, *s++);
146         }
147 }
148
149 int serial_getc_dev (unsigned long dev_base)
150 {
151         volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
152
153         /* Wait for a character to arrive. */
154         while (!(psc->psc_status & PSC_SR_RXRDY))
155                 ;
156
157         return psc->psc_buffer_8;
158 }
159
160 int serial_tstc_dev (unsigned long dev_base)
161 {
162         volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
163
164         return (psc->psc_status & PSC_SR_RXRDY);
165 }
166
167 void serial_setbrg_dev (unsigned long dev_base)
168 {
169         volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
170         unsigned long baseclk, div;
171
172         baseclk = (gd->ipb_clk + 16) / 32;
173
174         /* set up UART divisor */
175         div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
176         psc->ctur = (div >> 8) & 0xFF;
177         psc->ctlr =  div & 0xff;
178 }
179
180 void serial_setrts_dev (unsigned long dev_base, int s)
181 {
182         volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
183
184         if (s) {
185                 /* Assert RTS (become LOW) */
186                 psc->op1 = 0x1;
187         }
188         else {
189                 /* Negate RTS (become HIGH) */
190                 psc->op0 = 0x1;
191         }
192 }
193
194 int serial_getcts_dev (unsigned long dev_base)
195 {
196         volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
197
198         return (psc->ip & 0x1) ? 0 : 1;
199 }
200
201 int serial0_init(void)
202 {
203         return (serial_init_dev(PSC_BASE));
204 }
205
206 void serial0_setbrg (void)
207 {
208         serial_setbrg_dev(PSC_BASE);
209 }
210
211 void serial0_putc(const char c)
212 {
213         serial_putc_dev(PSC_BASE,c);
214 }
215
216 void serial0_puts(const char *s)
217 {
218         serial_puts_dev(PSC_BASE, s);
219 }
220
221 int serial0_getc(void)
222 {
223         return(serial_getc_dev(PSC_BASE));
224 }
225
226 int serial0_tstc(void)
227 {
228         return (serial_tstc_dev(PSC_BASE));
229 }
230
231 struct serial_device serial0_device =
232 {
233         .name   = "serial0",
234         .start  = serial0_init,
235         .stop   = NULL,
236         .setbrg = serial0_setbrg,
237         .getc   = serial0_getc,
238         .tstc   = serial0_tstc,
239         .putc   = serial0_putc,
240         .puts   = serial0_puts,
241 };
242
243 __weak struct serial_device *default_serial_console(void)
244 {
245         return &serial0_device;
246 }
247
248 #ifdef CONFIG_PSC_CONSOLE2
249 int serial1_init(void)
250 {
251         return serial_init_dev(PSC_BASE2);
252 }
253
254 void serial1_setbrg(void)
255 {
256         serial_setbrg_dev(PSC_BASE2);
257 }
258
259 void serial1_putc(const char c)
260 {
261         serial_putc_dev(PSC_BASE2, c);
262 }
263
264 void serial1_puts(const char *s)
265 {
266         serial_puts_dev(PSC_BASE2, s);
267 }
268
269 int serial1_getc(void)
270 {
271         return serial_getc_dev(PSC_BASE2);
272 }
273
274 int serial1_tstc(void)
275 {
276         return serial_tstc_dev(PSC_BASE2);
277 }
278
279 struct serial_device serial1_device =
280 {
281         .name   = "serial1",
282         .start  = serial1_init,
283         .stop   = NULL,
284         .setbrg = serial1_setbrg,
285         .getc   = serial1_getc,
286         .tstc   = serial1_tstc,
287         .putc   = serial1_putc,
288         .puts   = serial1_puts,
289 };
290 #endif /* CONFIG_PSC_CONSOLE2 */
291
292 #endif /* CONFIG_PSC_CONSOLE */