]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/serial/serial_max3100.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[people/ms/u-boot.git] / drivers / serial / serial_max3100.c
1 /*
2 * (C) Copyright 2003
3 *
4 * Pantelis Antoniou <panto@intracom.gr>
5 * Intracom S.A.
6 *
7 * SPDX-License-Identifier: GPL-2.0+
8 */
9
10 #include <common.h>
11 #include <watchdog.h>
12 #include <serial.h>
13 #include <linux/compiler.h>
14
15 DECLARE_GLOBAL_DATA_PTR;
16
17 /**************************************************************/
18
19 /* convienient macros */
20 #define MAX3100_SPI_RXD() (MAX3100_SPI_RXD_PORT & MAX3100_SPI_RXD_BIT)
21
22 #define MAX3100_SPI_TXD(x) \
23 do { \
24 if (x) \
25 MAX3100_SPI_TXD_PORT |= MAX3100_SPI_TXD_BIT; \
26 else \
27 MAX3100_SPI_TXD_PORT &= ~MAX3100_SPI_TXD_BIT; \
28 } while(0)
29
30 #define MAX3100_SPI_CLK(x) \
31 do { \
32 if (x) \
33 MAX3100_SPI_CLK_PORT |= MAX3100_SPI_CLK_BIT; \
34 else \
35 MAX3100_SPI_CLK_PORT &= ~MAX3100_SPI_CLK_BIT; \
36 } while(0)
37
38 #define MAX3100_SPI_CLK_TOGGLE() (MAX3100_SPI_CLK_PORT ^= MAX3100_SPI_CLK_BIT)
39
40 #define MAX3100_CS(x) \
41 do { \
42 if (x) \
43 MAX3100_CS_PORT |= MAX3100_CS_BIT; \
44 else \
45 MAX3100_CS_PORT &= ~MAX3100_CS_BIT; \
46 } while(0)
47
48 /**************************************************************/
49
50 /* MAX3100 definitions */
51
52 #define MAX3100_WC (3 << 14) /* write configuration */
53 #define MAX3100_RC (1 << 14) /* read configuration */
54 #define MAX3100_WD (2 << 14) /* write data */
55 #define MAX3100_RD (0 << 14) /* read data */
56
57 /* configuration register bits */
58 #define MAX3100_FEN (1 << 13) /* FIFO enable */
59 #define MAX3100_SHDN (1 << 12) /* shutdown bit */
60 #define MAX3100_TM (1 << 11) /* T bit irq mask */
61 #define MAX3100_RM (1 << 10) /* R bit irq mask */
62 #define MAX3100_PM (1 << 9) /* P bit irq mask */
63 #define MAX3100_RAM (1 << 8) /* mask for RA/FE bit */
64 #define MAX3100_IR (1 << 7) /* IRDA timing mode */
65 #define MAX3100_ST (1 << 6) /* transmit stop bit */
66 #define MAX3100_PE (1 << 5) /* parity enable bit */
67 #define MAX3100_L (1 << 4) /* Length bit */
68 #define MAX3100_B_MASK (0x000F) /* baud rate bits mask */
69 #define MAX3100_B(x) ((x) & 0x000F) /* baud rate select bits */
70
71 /* data register bits (write) */
72 #define MAX3100_TE (1 << 10) /* transmit enable bit (active low) */
73 #define MAX3100_RTS (1 << 9) /* request-to-send bit (inverted ~RTS pin) */
74
75 /* data register bits (read) */
76 #define MAX3100_RA (1 << 10) /* receiver activity when in shutdown mode */
77 #define MAX3100_FE (1 << 10) /* framing error when in normal mode */
78 #define MAX3100_CTS (1 << 9) /* clear-to-send bit (inverted ~CTS pin) */
79
80 /* data register bits (both directions) */
81 #define MAX3100_R (1 << 15) /* receive bit */
82 #define MAX3100_T (1 << 14) /* transmit bit */
83 #define MAX3100_P (1 << 8) /* parity bit */
84 #define MAX3100_D_MASK 0x00FF /* data bits mask */
85 #define MAX3100_D(x) ((x) & 0x00FF) /* data bits */
86
87 /* these definitions are valid only for fOSC = 3.6864MHz */
88 #define MAX3100_B_230400 MAX3100_B(0)
89 #define MAX3100_B_115200 MAX3100_B(1)
90 #define MAX3100_B_57600 MAX3100_B(2)
91 #define MAX3100_B_38400 MAX3100_B(9)
92 #define MAX3100_B_19200 MAX3100_B(10)
93 #define MAX3100_B_9600 MAX3100_B(11)
94 #define MAX3100_B_4800 MAX3100_B(12)
95 #define MAX3100_B_2400 MAX3100_B(13)
96 #define MAX3100_B_1200 MAX3100_B(14)
97 #define MAX3100_B_600 MAX3100_B(15)
98
99 /**************************************************************/
100
101 static inline unsigned int max3100_transfer(unsigned int val)
102 {
103 unsigned int rx;
104 int b;
105
106 MAX3100_SPI_CLK(0);
107 MAX3100_CS(0);
108
109 rx = 0; b = 16;
110 while (--b >= 0) {
111 MAX3100_SPI_TXD(val & 0x8000);
112 val <<= 1;
113 MAX3100_SPI_CLK_TOGGLE();
114 udelay(1);
115 rx <<= 1;
116 if (MAX3100_SPI_RXD())
117 rx |= 1;
118 MAX3100_SPI_CLK_TOGGLE();
119 udelay(1);
120 }
121
122 MAX3100_SPI_CLK(1);
123 MAX3100_CS(1);
124
125 return rx;
126 }
127
128 /**************************************************************/
129
130 /* must be power of 2 */
131 #define RXFIFO_SZ 16
132
133 static int rxfifo_cnt;
134 static int rxfifo_in;
135 static int rxfifo_out;
136 static unsigned char rxfifo_buf[16];
137
138 static void max3100_serial_putc_raw(int c)
139 {
140 unsigned int rx;
141
142 while (((rx = max3100_transfer(MAX3100_RC)) & MAX3100_T) == 0)
143 WATCHDOG_RESET();
144
145 rx = max3100_transfer(MAX3100_WD | (c & 0xff));
146 if ((rx & MAX3100_RD) != 0 && rxfifo_cnt < RXFIFO_SZ) {
147 rxfifo_cnt++;
148 rxfifo_buf[rxfifo_in++] = rx & 0xff;
149 rxfifo_in &= RXFIFO_SZ - 1;
150 }
151 }
152
153 static int max3100_serial_getc(void)
154 {
155 int c;
156 unsigned int rx;
157
158 while (rxfifo_cnt == 0) {
159 rx = max3100_transfer(MAX3100_RD);
160 if ((rx & MAX3100_R) != 0) {
161 do {
162 rxfifo_cnt++;
163 rxfifo_buf[rxfifo_in++] = rx & 0xff;
164 rxfifo_in &= RXFIFO_SZ - 1;
165
166 if (rxfifo_cnt >= RXFIFO_SZ)
167 break;
168 } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
169 }
170 WATCHDOG_RESET();
171 }
172
173 rxfifo_cnt--;
174 c = rxfifo_buf[rxfifo_out++];
175 rxfifo_out &= RXFIFO_SZ - 1;
176 return c;
177 }
178
179 static int max3100_serial_tstc(void)
180 {
181 unsigned int rx;
182
183 if (rxfifo_cnt > 0)
184 return 1;
185
186 rx = max3100_transfer(MAX3100_RD);
187 if ((rx & MAX3100_R) == 0)
188 return 0;
189
190 do {
191 rxfifo_cnt++;
192 rxfifo_buf[rxfifo_in++] = rx & 0xff;
193 rxfifo_in &= RXFIFO_SZ - 1;
194
195 if (rxfifo_cnt >= RXFIFO_SZ)
196 break;
197 } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
198
199 return 1;
200 }
201
202 static int max3100_serial_init(void)
203 {
204 unsigned int wconf, rconf;
205 int i;
206
207 wconf = 0;
208
209 /* Set baud rate */
210 switch (gd->baudrate) {
211 case 1200:
212 wconf = MAX3100_B_1200;
213 break;
214 case 2400:
215 wconf = MAX3100_B_2400;
216 break;
217 case 4800:
218 wconf = MAX3100_B_4800;
219 break;
220 case 9600:
221 wconf = MAX3100_B_9600;
222 break;
223 case 19200:
224 wconf = MAX3100_B_19200;
225 break;
226 case 38400:
227 wconf = MAX3100_B_38400;
228 break;
229 case 57600:
230 wconf = MAX3100_B_57600;
231 break;
232 default:
233 case 115200:
234 wconf = MAX3100_B_115200;
235 break;
236 case 230400:
237 wconf = MAX3100_B_230400;
238 break;
239 }
240
241 /* try for 10ms, with a 100us gap */
242 for (i = 0; i < 10000; i += 100) {
243
244 max3100_transfer(MAX3100_WC | wconf);
245 rconf = max3100_transfer(MAX3100_RC) & 0x3fff;
246
247 if (rconf == wconf)
248 break;
249 udelay(100);
250 }
251
252 rxfifo_in = rxfifo_out = rxfifo_cnt = 0;
253
254 return (0);
255 }
256
257 static void max3100_serial_putc(const char c)
258 {
259 if (c == '\n')
260 max3100_serial_putc_raw('\r');
261
262 max3100_serial_putc_raw(c);
263 }
264
265 static void max3100_serial_puts(const char *s)
266 {
267 while (*s)
268 max3100_serial_putc_raw(*s++);
269 }
270
271 static void max3100_serial_setbrg(void)
272 {
273 }
274
275 static struct serial_device max3100_serial_drv = {
276 .name = "max3100_serial",
277 .start = max3100_serial_init,
278 .stop = NULL,
279 .setbrg = max3100_serial_setbrg,
280 .putc = max3100_serial_putc,
281 .puts = max3100_serial_puts,
282 .getc = max3100_serial_getc,
283 .tstc = max3100_serial_tstc,
284 };
285
286 void max3100_serial_initialize(void)
287 {
288 serial_register(&max3100_serial_drv);
289 }
290
291 __weak struct serial_device *default_serial_console(void)
292 {
293 return &max3100_serial_drv;
294 }