]> git.sur5r.net Git - u-boot/blob - drivers/serial/serial_max3100.c
Merge branch 'master' of git://git.denx.de/u-boot-mips
[u-boot] / 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 }