]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/serial/serial_s3c44b0.c
karo: tx6: factor out PMIC initialization
[karo-tx-uboot.git] / drivers / serial / serial_s3c44b0.c
1 pyright 2002
2  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
3  * Marius Groeger <mgroeger@sysgo.de>
4  *
5  * (C) Copyright 2002
6  * ght 2002-2004
7  * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
8  *
9  * (C) Copyright 2002
10  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
11  * Marius Groeger <mgroeger@sysgo.de>
12  *
13  * (C) Copyright 2002
14  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
15  * Alex Zuepke <azu@sysgo.de>
16  *
17  * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
18  *
19  * SPDX-License-Identifier:     GPL-2.0+
20  */
21
22 #include <common.h>
23 #include <asm/hardware.h>
24
25 DECLARE_GLOBAL_DATA_PTR;
26
27 /* flush serial input queue. returns 0 on success or negative error
28  * number otherwise
29  */
30 static int serial_flush_input(void)
31 {
32         volatile u32 tmp;
33
34         /* keep on reading as long as the receiver is not empty */
35         while(UTRSTAT0&0x01) {
36                 tmp = REGB(URXH0);
37         }
38
39         return 0;
40 }
41
42
43 /* flush output queue. returns 0 on success or negative error number
44  * otherwise
45  */
46 static int serial_flush_output(void)
47 {
48         /* wait until the transmitter is no longer busy */
49         while(!(UTRSTAT0 & 0x02)) {
50         }
51
52         return 0;
53 }
54
55
56 static void s3c44b0_serial_setbrg(void)
57 {
58         u32 divisor = 0;
59
60         /* get correct divisor */
61         switch(gd->baudrate) {
62
63         case 1200:
64 #if CONFIG_S3C44B0_CLOCK_SPEED==66
65                 divisor = 3124;
66 #elif CONFIG_S3C44B0_CLOCK_SPEED==75
67                 divisor = 3905;
68 #else
69 # error CONFIG_S3C44B0_CLOCK_SPEED undefined
70 #endif
71                 break;
72
73         case 9600:
74 #if CONFIG_S3C44B0_CLOCK_SPEED==66
75                 divisor = 390;
76 #elif CONFIG_S3C44B0_CLOCK_SPEED==75
77                 divisor = 487;
78 #else
79 # error CONFIG_S3C44B0_CLOCK_SPEED undefined
80 #endif
81                 break;
82
83         case 19200:
84 #if CONFIG_S3C44B0_CLOCK_SPEED==66
85                 divisor = 194;
86 #elif CONFIG_S3C44B0_CLOCK_SPEED==75
87                 divisor = 243;
88 #else
89 # error CONFIG_S3C44B0_CLOCK_SPEED undefined
90 #endif
91                 break;
92
93         case 38400:
94 #if CONFIG_S3C44B0_CLOCK_SPEED==66
95                 divisor = 97;
96 #elif CONFIG_S3C44B0_CLOCK_SPEED==75
97                 divisor = 121;
98 #else
99 # error CONFIG_S3C44B0_CLOCK_SPEED undefined
100 #endif  /* break; */
101
102         case 57600:
103 #if CONFIG_S3C44B0_CLOCK_SPEED==66
104                 divisor = 64;
105 #elif CONFIG_S3C44B0_CLOCK_SPEED==75
106                 divisor = 80;
107 #else
108 # error CONFIG_S3C44B0_CLOCK_SPEED undefined
109 #endif  /* break; */
110
111         case 115200:
112 #if CONFIG_S3C44B0_CLOCK_SPEED==66
113                 divisor = 32;
114 #elif CONFIG_S3C44B0_CLOCK_SPEED==75
115                 divisor = 40;
116 #else
117 # error CONFIG_S3C44B0_CLOCK_SPEED undefined
118 #endif  /* break; */
119         }
120
121         serial_flush_output();
122         serial_flush_input();
123         UFCON0 = 0x0;
124         ULCON0 = 0x03;
125         UCON0 = 0x05;
126         UBRDIV0 = divisor;
127
128         UFCON1 = 0x0;
129         ULCON1 = 0x03;
130         UCON1 = 0x05;
131         UBRDIV1 = divisor;
132
133         for(divisor=0; divisor<100; divisor++) {
134                 /* NOP */
135         }
136 }
137
138
139 /*
140  * Initialise the serial port with the given baudrate. The settings
141  * are always 8 data bits, no parity, 1 stop bit, no start bits.
142  *
143  */
144 static int s3c44b0_serial_init(void)
145 {
146         serial_setbrg ();
147
148         return (0);
149 }
150
151
152 /*
153  * Output a single byte to the serial port.
154  */
155 static void s3c44b0_serial_putc(const char c)
156 {
157         /* wait for room in the transmit FIFO */
158         while(!(UTRSTAT0 & 0x02));
159
160         UTXH0 = (unsigned char)c;
161
162         /*
163                 to be polite with serial console add a line feed
164                 to the carriage return character
165         */
166         if (c=='\n')
167                 serial_putc('\r');
168 }
169
170 /*
171  * Read a single byte from the serial port. Returns 1 on success, 0
172  * otherwise. When the function is succesfull, the character read is
173  * written into its argument c.
174  */
175 static int s3c44b0_serial_tstc(void)
176 {
177         return (UTRSTAT0 & 0x01);
178 }
179
180 /*
181  * Read a single byte from the serial port. Returns 1 on success, 0
182  * otherwise. When the function is succesfull, the character read is
183  * written into its argument c.
184  */
185 static int s3c44b0_serial_getc(void)
186 {
187         int rv;
188
189         for(;;) {
190                 rv = s3c44b0_serial_tstc();
191
192                 if(rv > 0)
193                         return URXH0;
194         }
195 }
196
197 static struct serial_device s3c44b0_serial_drv = {
198         .name   = "s3c44b0_serial",
199         .start  = s3c44b0_serial_init,
200         .stop   = NULL,
201         .setbrg = s3c44b0_serial_setbrg,
202         .putc   = s3c44b0_serial_putc,
203         .puts   = default_serial_puts,
204         .getc   = s3c44b0_serial_getc,
205         .tstc   = s3c44b0_serial_tstc,
206 };
207
208 void s3c44b0_serial_initialize(void)
209 {
210         serial_register(&s3c44b0_serial_drv);
211 }
212
213 __weak struct serial_device *default_serial_console(void)
214 {
215         return &s3c44b0_serial_drv;
216 }