]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc5xx/serial.c
Merge remote-tracking branch 'u-boot-ti/master'
[karo-tx-uboot.git] / arch / powerpc / cpu / mpc5xx / serial.c
1 /*
2  * (C) Copyright 2003
3  * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
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,
21  */
22
23 /*
24  * File:                serial.c
25  *
26  * Discription:         Serial interface driver for SCI1 and SCI2.
27  *                      Since this code will be called from ROM use
28  *                      only non-static local variables.
29  *
30  */
31
32 #include <common.h>
33 #include <watchdog.h>
34 #include <command.h>
35 #include <mpc5xx.h>
36 #include <serial.h>
37 #include <linux/compiler.h>
38
39 DECLARE_GLOBAL_DATA_PTR;
40
41 /*
42  * Local functions
43  */
44
45 static int ready_to_send(void)
46 {
47         volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
48         volatile short status;
49
50         do {
51 #if defined(CONFIG_5xx_CONS_SCI1)
52                 status = immr->im_qsmcm.qsmcm_sc1sr;
53 #else
54                 status = immr->im_qsmcm.qsmcm_sc2sr;
55 #endif
56
57 #if defined(CONFIG_WATCHDOG)
58                 reset_5xx_watchdog (immr);
59 #endif
60         } while ((status & SCI_TDRE) == 0);
61         return 1;
62
63 }
64
65 /*
66  * Minimal global serial functions needed to use one of the SCI modules.
67  */
68
69 static int mpc5xx_serial_init(void)
70 {
71         volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
72
73         serial_setbrg();
74
75 #if defined(CONFIG_5xx_CONS_SCI1)
76         /* 10-Bit, 1 start bit, 8 data bit, no parity, 1 stop bit */
77         immr->im_qsmcm.qsmcm_scc1r1 = SCI_M_10;
78         immr->im_qsmcm.qsmcm_scc1r1 = SCI_TE | SCI_RE;
79 #else
80         immr->im_qsmcm.qsmcm_scc2r1 = SCI_M_10;
81         immr->im_qsmcm.qsmcm_scc2r1 = SCI_TE | SCI_RE;
82 #endif
83         return 0;
84 }
85
86 static void mpc5xx_serial_putc(const char c)
87 {
88         volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
89
90         /* Test for completition */
91         if(ready_to_send()) {
92 #if defined(CONFIG_5xx_CONS_SCI1)
93                 immr->im_qsmcm.qsmcm_sc1dr = (short)c;
94 #else
95                 immr->im_qsmcm.qsmcm_sc2dr = (short)c;
96 #endif
97                 if(c == '\n') {
98                         if(ready_to_send());
99 #if defined(CONFIG_5xx_CONS_SCI1)
100                         immr->im_qsmcm.qsmcm_sc1dr = (short)'\r';
101 #else
102                         immr->im_qsmcm.qsmcm_sc2dr = (short)'\r';
103 #endif
104                 }
105         }
106 }
107
108 static int mpc5xx_serial_getc(void)
109 {
110         volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
111         volatile short status;
112         unsigned char tmp;
113
114         /* New data ? */
115         do {
116 #if defined(CONFIG_5xx_CONS_SCI1)
117                 status = immr->im_qsmcm.qsmcm_sc1sr;
118 #else
119                 status = immr->im_qsmcm.qsmcm_sc2sr;
120 #endif
121
122 #if defined(CONFIG_WATCHDOG)
123                 reset_5xx_watchdog (immr);
124 #endif
125         } while ((status & SCI_RDRF) == 0);
126
127         /* Read data */
128 #if defined(CONFIG_5xx_CONS_SCI1)
129         tmp = (unsigned char)(immr->im_qsmcm.qsmcm_sc1dr & SCI_SCXDR_MK);
130 #else
131         tmp = (unsigned char)( immr->im_qsmcm.qsmcm_sc2dr & SCI_SCXDR_MK);
132 #endif
133         return  tmp;
134 }
135
136 static int mpc5xx_serial_tstc(void)
137 {
138         volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
139         short status;
140
141         /* New data character ? */
142 #if defined(CONFIG_5xx_CONS_SCI1)
143         status = immr->im_qsmcm.qsmcm_sc1sr;
144 #else
145         status = immr->im_qsmcm.qsmcm_sc2sr;
146 #endif
147         return (status & SCI_RDRF);
148 }
149
150 static void mpc5xx_serial_setbrg(void)
151 {
152         volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
153         short scxbr;
154
155         /* Set baudrate */
156         scxbr = (gd->cpu_clk / (32 * gd->baudrate));
157 #if defined(CONFIG_5xx_CONS_SCI1)
158         immr->im_qsmcm.qsmcm_scc1r0 = (scxbr & SCI_SCXBR_MK);
159 #else
160         immr->im_qsmcm.qsmcm_scc2r0 = (scxbr & SCI_SCXBR_MK);
161 #endif
162 }
163
164 static struct serial_device mpc5xx_serial_drv = {
165         .name   = "mpc5xx_serial",
166         .start  = mpc5xx_serial_init,
167         .stop   = NULL,
168         .setbrg = mpc5xx_serial_setbrg,
169         .putc   = mpc5xx_serial_putc,
170         .puts   = default_serial_puts,
171         .getc   = mpc5xx_serial_getc,
172         .tstc   = mpc5xx_serial_tstc,
173 };
174
175 void mpc5xx_serial_initialize(void)
176 {
177         serial_register(&mpc5xx_serial_drv);
178 }
179
180 __weak struct serial_device *default_serial_console(void)
181 {
182         return &mpc5xx_serial_drv;
183 }