]> git.sur5r.net Git - u-boot/blob - post/cpu/mpc8xx/uart.c
mpc8xx: remove RPXlite_dw, quantum board support
[u-boot] / post / cpu / mpc8xx / uart.c
1 /*
2  * (C) Copyright 2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9
10 /*
11  * UART test
12  *
13  * The Serial Management Controllers (SMC) and the Serial Communication
14  * Controllers (SCC) listed in ctlr_list array below are tested in
15  * the loopback UART mode.
16  * The controllers are configured accordingly and several characters
17  * are transmitted. The configurable test parameters are:
18  *   MIN_PACKET_LENGTH - minimum size of packet to transmit
19  *   MAX_PACKET_LENGTH - maximum size of packet to transmit
20  *   TEST_NUM - number of tests
21  */
22
23 #include <post.h>
24 #if CONFIG_POST & CONFIG_SYS_POST_UART
25 #if defined(CONFIG_8xx)
26 #include <commproc.h>
27 #elif defined(CONFIG_MPC8260)
28 #include <asm/cpm_8260.h>
29 #else
30 #error "Apparently a bad configuration, please fix."
31 #endif
32 #include <command.h>
33 #include <serial.h>
34
35 DECLARE_GLOBAL_DATA_PTR;
36
37 #define CTLR_SMC 0
38 #define CTLR_SCC 1
39
40 /* The list of controllers to test */
41 #if defined(CONFIG_MPC823)
42 static int ctlr_list[][2] =
43                 { {CTLR_SMC, 0}, {CTLR_SMC, 1}, {CTLR_SCC, 1} };
44 #else
45 static int ctlr_list[][2] = { };
46 #endif
47
48 static struct {
49         void (*init) (int index);
50         void (*halt) (int index);
51         void (*putc) (int index, const char c);
52         int (*getc) (int index);
53 } ctlr_proc[2];
54
55 static char *ctlr_name[2] = { "SMC", "SCC" };
56
57 static int proff_smc[] = { PROFF_SMC1, PROFF_SMC2 };
58 static int proff_scc[] =
59                 { PROFF_SCC1, PROFF_SCC2, PROFF_SCC3, PROFF_SCC4 };
60
61 /*
62  * SMC callbacks
63  */
64
65 static void smc_init (int smc_index)
66 {
67         static int cpm_cr_ch[] = { CPM_CR_CH_SMC1, CPM_CR_CH_SMC2 };
68
69         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
70         volatile smc_t *sp;
71         volatile smc_uart_t *up;
72         volatile cbd_t *tbdf, *rbdf;
73         volatile cpm8xx_t *cp = &(im->im_cpm);
74         uint dpaddr;
75
76         /* initialize pointers to SMC */
77
78         sp = (smc_t *) & (cp->cp_smc[smc_index]);
79         up = (smc_uart_t *) & cp->cp_dparam[proff_smc[smc_index]];
80
81         /* Disable transmitter/receiver.
82          */
83         sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
84
85         /* Enable SDMA.
86          */
87         im->im_siu_conf.sc_sdcr = 1;
88
89         /* clear error conditions */
90 #ifdef  CONFIG_SYS_SDSR
91         im->im_sdma.sdma_sdsr = CONFIG_SYS_SDSR;
92 #else
93         im->im_sdma.sdma_sdsr = 0x83;
94 #endif
95
96         /* clear SDMA interrupt mask */
97 #ifdef  CONFIG_SYS_SDMR
98         im->im_sdma.sdma_sdmr = CONFIG_SYS_SDMR;
99 #else
100         im->im_sdma.sdma_sdmr = 0x00;
101 #endif
102
103 #if defined(CONFIG_FADS)
104         /* Enable RS232 */
105         *((uint *) BCSR1) &=
106                         ~(smc_index == 1 ? BCSR1_RS232EN_1 : BCSR1_RS232EN_2);
107 #endif
108
109         /* Set the physical address of the host memory buffers in
110          * the buffer descriptors.
111          */
112
113 #ifdef CONFIG_SYS_ALLOC_DPRAM
114         dpaddr = dpram_alloc_align (sizeof (cbd_t) * 2 + 2, 8);
115 #else
116         dpaddr = CPM_POST_BASE;
117 #endif
118
119         /* Allocate space for two buffer descriptors in the DP ram.
120          * For now, this address seems OK, but it may have to
121          * change with newer versions of the firmware.
122          * damm: allocating space after the two buffers for rx/tx data
123          */
124
125         rbdf = (cbd_t *) & cp->cp_dpmem[dpaddr];
126         rbdf->cbd_bufaddr = (uint) (rbdf + 2);
127         rbdf->cbd_sc = 0;
128         tbdf = rbdf + 1;
129         tbdf->cbd_bufaddr = ((uint) (rbdf + 2)) + 1;
130         tbdf->cbd_sc = 0;
131
132         /* Set up the uart parameters in the parameter ram.
133          */
134         up->smc_rbase = dpaddr;
135         up->smc_tbase = dpaddr + sizeof (cbd_t);
136         up->smc_rfcr = SMC_EB;
137         up->smc_tfcr = SMC_EB;
138
139         /* Set UART mode, 8 bit, no parity, one stop.
140          * Enable receive and transmit.
141          * Set local loopback mode.
142          */
143         sp->smc_smcmr = smcr_mk_clen (9) | SMCMR_SM_UART | (ushort) 0x0004;
144
145         /* Mask all interrupts and remove anything pending.
146          */
147         sp->smc_smcm = 0;
148         sp->smc_smce = 0xff;
149
150         /* Set up the baud rate generator.
151          */
152         cp->cp_simode = 0x00000000;
153
154         cp->cp_brgc1 =
155                         (((gd->cpu_clk / 16 / gd->baudrate) -
156                           1) << 1) | CPM_BRG_EN;
157
158         /* Make the first buffer the only buffer.
159          */
160         tbdf->cbd_sc |= BD_SC_WRAP;
161         rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
162
163         /* Single character receive.
164          */
165         up->smc_mrblr = 1;
166         up->smc_maxidl = 0;
167
168         /* Initialize Tx/Rx parameters.
169          */
170
171         while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
172                 ;
173
174         cp->cp_cpcr =
175                         mk_cr_cmd (cpm_cr_ch[smc_index], CPM_CR_INIT_TRX) | CPM_CR_FLG;
176
177         while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
178                 ;
179
180         /* Enable transmitter/receiver.
181          */
182         sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
183 }
184
185 static void smc_halt(int smc_index)
186 {
187 }
188
189 static void smc_putc (int smc_index, const char c)
190 {
191         volatile cbd_t *tbdf;
192         volatile char *buf;
193         volatile smc_uart_t *up;
194         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
195         volatile cpm8xx_t *cpmp = &(im->im_cpm);
196
197         up = (smc_uart_t *) & cpmp->cp_dparam[proff_smc[smc_index]];
198
199         tbdf = (cbd_t *) & cpmp->cp_dpmem[up->smc_tbase];
200
201         /* Wait for last character to go.
202          */
203
204         buf = (char *) tbdf->cbd_bufaddr;
205 #if 0
206         __asm__ ("eieio");
207         while (tbdf->cbd_sc & BD_SC_READY)
208                 __asm__ ("eieio");
209 #endif
210
211         *buf = c;
212         tbdf->cbd_datlen = 1;
213         tbdf->cbd_sc |= BD_SC_READY;
214         __asm__ ("eieio");
215 #if 1
216         while (tbdf->cbd_sc & BD_SC_READY)
217                 __asm__ ("eieio");
218 #endif
219 }
220
221 static int smc_getc (int smc_index)
222 {
223         volatile cbd_t *rbdf;
224         volatile unsigned char *buf;
225         volatile smc_uart_t *up;
226         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
227         volatile cpm8xx_t *cpmp = &(im->im_cpm);
228         unsigned char c;
229         int i;
230
231         up = (smc_uart_t *) & cpmp->cp_dparam[proff_smc[smc_index]];
232
233         rbdf = (cbd_t *) & cpmp->cp_dpmem[up->smc_rbase];
234
235         /* Wait for character to show up.
236          */
237         buf = (unsigned char *) rbdf->cbd_bufaddr;
238 #if 0
239         while (rbdf->cbd_sc & BD_SC_EMPTY);
240 #else
241         for (i = 100; i > 0; i--) {
242                 if (!(rbdf->cbd_sc & BD_SC_EMPTY))
243                         break;
244                 udelay (1000);
245         }
246
247         if (i == 0)
248                 return -1;
249 #endif
250         c = *buf;
251         rbdf->cbd_sc |= BD_SC_EMPTY;
252
253         return (c);
254 }
255
256   /*
257    * SCC callbacks
258    */
259
260 static void scc_init (int scc_index)
261 {
262         static int cpm_cr_ch[] = {
263                 CPM_CR_CH_SCC1,
264                 CPM_CR_CH_SCC2,
265                 CPM_CR_CH_SCC3,
266                 CPM_CR_CH_SCC4,
267         };
268
269         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
270         volatile scc_t *sp;
271         volatile scc_uart_t *up;
272         volatile cbd_t *tbdf, *rbdf;
273         volatile cpm8xx_t *cp = &(im->im_cpm);
274         uint dpaddr;
275
276         /* initialize pointers to SCC */
277
278         sp = (scc_t *) & (cp->cp_scc[scc_index]);
279         up = (scc_uart_t *) & cp->cp_dparam[proff_scc[scc_index]];
280
281         /* Disable transmitter/receiver.
282          */
283         sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
284
285
286         /* Allocate space for two buffer descriptors in the DP ram.
287          */
288
289 #ifdef CONFIG_SYS_ALLOC_DPRAM
290         dpaddr = dpram_alloc_align (sizeof (cbd_t) * 2 + 2, 8);
291 #else
292         dpaddr = CPM_POST_BASE;
293 #endif
294
295         /* Enable SDMA.
296          */
297         im->im_siu_conf.sc_sdcr = 0x0001;
298
299         /* Set the physical address of the host memory buffers in
300          * the buffer descriptors.
301          */
302
303         rbdf = (cbd_t *) & cp->cp_dpmem[dpaddr];
304         rbdf->cbd_bufaddr = (uint) (rbdf + 2);
305         rbdf->cbd_sc = 0;
306         tbdf = rbdf + 1;
307         tbdf->cbd_bufaddr = ((uint) (rbdf + 2)) + 1;
308         tbdf->cbd_sc = 0;
309
310         /* Set up the baud rate generator.
311          */
312         cp->cp_sicr &= ~(0x000000FF << (8 * scc_index));
313         /* no |= needed, since BRG1 is 000 */
314
315         cp->cp_brgc1 =
316                         (((gd->cpu_clk / 16 / gd->baudrate) -
317                           1) << 1) | CPM_BRG_EN;
318
319         /* Set up the uart parameters in the parameter ram.
320          */
321         up->scc_genscc.scc_rbase = dpaddr;
322         up->scc_genscc.scc_tbase = dpaddr + sizeof (cbd_t);
323
324         /* Initialize Tx/Rx parameters.
325          */
326         while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
327                 ;
328         cp->cp_cpcr =
329                         mk_cr_cmd (cpm_cr_ch[scc_index], CPM_CR_INIT_TRX) | CPM_CR_FLG;
330
331         while (cp->cp_cpcr & CPM_CR_FLG)        /* wait if cp is busy */
332                 ;
333
334         up->scc_genscc.scc_rfcr = SCC_EB | 0x05;
335         up->scc_genscc.scc_tfcr = SCC_EB | 0x05;
336
337         up->scc_genscc.scc_mrblr = 1;   /* Single character receive */
338         up->scc_maxidl = 0;             /* disable max idle */
339         up->scc_brkcr = 1;              /* send one break character on stop TX */
340         up->scc_parec = 0;
341         up->scc_frmec = 0;
342         up->scc_nosec = 0;
343         up->scc_brkec = 0;
344         up->scc_uaddr1 = 0;
345         up->scc_uaddr2 = 0;
346         up->scc_toseq = 0;
347         up->scc_char1 = 0x8000;
348         up->scc_char2 = 0x8000;
349         up->scc_char3 = 0x8000;
350         up->scc_char4 = 0x8000;
351         up->scc_char5 = 0x8000;
352         up->scc_char6 = 0x8000;
353         up->scc_char7 = 0x8000;
354         up->scc_char8 = 0x8000;
355         up->scc_rccm = 0xc0ff;
356
357         /* Set low latency / small fifo.
358          */
359         sp->scc_gsmrh = SCC_GSMRH_RFW;
360
361         /* Set UART mode
362          */
363         sp->scc_gsmrl &= ~0xF;
364         sp->scc_gsmrl |= SCC_GSMRL_MODE_UART;
365
366         /* Set local loopback mode.
367          */
368         sp->scc_gsmrl &= ~SCC_GSMRL_DIAG_LE;
369         sp->scc_gsmrl |= SCC_GSMRL_DIAG_LOOP;
370
371         /* Set clock divider 16 on Tx and Rx
372          */
373         sp->scc_gsmrl |= (SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
374
375         sp->scc_psmr |= SCU_PSMR_CL;
376
377         /* Mask all interrupts and remove anything pending.
378          */
379         sp->scc_sccm = 0;
380         sp->scc_scce = 0xffff;
381         sp->scc_dsr = 0x7e7e;
382         sp->scc_psmr = 0x3000;
383
384         /* Make the first buffer the only buffer.
385          */
386         tbdf->cbd_sc |= BD_SC_WRAP;
387         rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
388
389         /* Enable transmitter/receiver.
390          */
391         sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
392 }
393
394 static void scc_halt(int scc_index)
395 {
396         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
397         volatile cpm8xx_t *cp = &(im->im_cpm);
398         volatile scc_t *sp = (scc_t *) & (cp->cp_scc[scc_index]);
399
400         sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT | SCC_GSMRL_DIAG_LE);
401 }
402
403 static void scc_putc (int scc_index, const char c)
404 {
405         volatile cbd_t *tbdf;
406         volatile char *buf;
407         volatile scc_uart_t *up;
408         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
409         volatile cpm8xx_t *cpmp = &(im->im_cpm);
410
411         up = (scc_uart_t *) & cpmp->cp_dparam[proff_scc[scc_index]];
412
413         tbdf = (cbd_t *) & cpmp->cp_dpmem[up->scc_genscc.scc_tbase];
414
415         /* Wait for last character to go.
416          */
417
418         buf = (char *) tbdf->cbd_bufaddr;
419 #if 0
420         __asm__ ("eieio");
421         while (tbdf->cbd_sc & BD_SC_READY)
422                 __asm__ ("eieio");
423 #endif
424
425         *buf = c;
426         tbdf->cbd_datlen = 1;
427         tbdf->cbd_sc |= BD_SC_READY;
428         __asm__ ("eieio");
429 #if 1
430         while (tbdf->cbd_sc & BD_SC_READY)
431                 __asm__ ("eieio");
432 #endif
433 }
434
435 static int scc_getc (int scc_index)
436 {
437         volatile cbd_t *rbdf;
438         volatile unsigned char *buf;
439         volatile scc_uart_t *up;
440         volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
441         volatile cpm8xx_t *cpmp = &(im->im_cpm);
442         unsigned char c;
443         int i;
444
445         up = (scc_uart_t *) & cpmp->cp_dparam[proff_scc[scc_index]];
446
447         rbdf = (cbd_t *) & cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
448
449         /* Wait for character to show up.
450          */
451         buf = (unsigned char *) rbdf->cbd_bufaddr;
452 #if 0
453         while (rbdf->cbd_sc & BD_SC_EMPTY);
454 #else
455         for (i = 100; i > 0; i--) {
456                 if (!(rbdf->cbd_sc & BD_SC_EMPTY))
457                         break;
458                 udelay (1000);
459         }
460
461         if (i == 0)
462                 return -1;
463 #endif
464         c = *buf;
465         rbdf->cbd_sc |= BD_SC_EMPTY;
466
467         return (c);
468 }
469
470   /*
471    * Test routines
472    */
473
474 static int test_ctlr (int ctlr, int index)
475 {
476         int res = -1;
477         char test_str[] = "*** UART Test String ***\r\n";
478         int i;
479
480         ctlr_proc[ctlr].init (index);
481
482         for (i = 0; i < sizeof (test_str) - 1; i++) {
483                 ctlr_proc[ctlr].putc (index, test_str[i]);
484                 if (ctlr_proc[ctlr].getc (index) != test_str[i])
485                         goto Done;
486         }
487
488         res = 0;
489
490 Done:
491         ctlr_proc[ctlr].halt (index);
492
493         if (res != 0) {
494                 post_log ("uart %s%d test failed\n",
495                                 ctlr_name[ctlr], index + 1);
496         }
497
498         return res;
499 }
500
501 int uart_post_test (int flags)
502 {
503         int res = 0;
504         int i;
505
506         ctlr_proc[CTLR_SMC].init = smc_init;
507         ctlr_proc[CTLR_SMC].halt = smc_halt;
508         ctlr_proc[CTLR_SMC].putc = smc_putc;
509         ctlr_proc[CTLR_SMC].getc = smc_getc;
510
511         ctlr_proc[CTLR_SCC].init = scc_init;
512         ctlr_proc[CTLR_SCC].halt = scc_halt;
513         ctlr_proc[CTLR_SCC].putc = scc_putc;
514         ctlr_proc[CTLR_SCC].getc = scc_getc;
515
516         for (i = 0; i < ARRAY_SIZE(ctlr_list); i++) {
517                 if (test_ctlr (ctlr_list[i][0], ctlr_list[i][1]) != 0) {
518                         res = -1;
519                 }
520         }
521
522 #if !defined(CONFIG_8xx_CONS_NONE)
523         serial_reinit_all ();
524 #endif
525
526         return res;
527 }
528
529 #endif /* CONFIG_POST & CONFIG_SYS_POST_UART */