8bfb3dedcbb590e3748d7d21401ebbb2f5e4b168
[platform/kernel/u-boot.git] / arch / powerpc / cpu / mpc8260 / serial_scc.c
1 /*
2  * (C) Copyright 2000
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  *
7  * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
8  */
9
10 /*
11  * Minimal serial functions needed to use one of the SCC ports
12  * as serial console interface.
13  */
14
15 #include <common.h>
16 #include <mpc8260.h>
17 #include <asm/cpm_8260.h>
18 #include <serial.h>
19 #include <linux/compiler.h>
20
21 DECLARE_GLOBAL_DATA_PTR;
22
23 #if defined(CONFIG_CONS_ON_SCC)
24
25 #if CONFIG_CONS_INDEX == 1      /* Console on SCC1 */
26
27 #define SCC_INDEX               0
28 #define PROFF_SCC               PROFF_SCC1
29 #define CMXSCR_MASK             (CMXSCR_GR1|CMXSCR_SC1|\
30                                         CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
31 #define CMXSCR_VALUE            (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
32 #define CPM_CR_SCC_PAGE         CPM_CR_SCC1_PAGE
33 #define CPM_CR_SCC_SBLOCK       CPM_CR_SCC1_SBLOCK
34
35 #elif CONFIG_CONS_INDEX == 2    /* Console on SCC2 */
36
37 #define SCC_INDEX               1
38 #define PROFF_SCC               PROFF_SCC2
39 #define CMXSCR_MASK             (CMXSCR_GR2|CMXSCR_SC2|\
40                                         CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
41 #define CMXSCR_VALUE            (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
42 #define CPM_CR_SCC_PAGE         CPM_CR_SCC2_PAGE
43 #define CPM_CR_SCC_SBLOCK       CPM_CR_SCC2_SBLOCK
44
45 #elif CONFIG_CONS_INDEX == 3    /* Console on SCC3 */
46
47 #define SCC_INDEX               2
48 #define PROFF_SCC               PROFF_SCC3
49 #define CMXSCR_MASK             (CMXSCR_GR3|CMXSCR_SC3|\
50                                         CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
51 #define CMXSCR_VALUE            (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
52 #define CPM_CR_SCC_PAGE         CPM_CR_SCC3_PAGE
53 #define CPM_CR_SCC_SBLOCK       CPM_CR_SCC3_SBLOCK
54
55 #elif CONFIG_CONS_INDEX == 4    /* Console on SCC4 */
56
57 #define SCC_INDEX               3
58 #define PROFF_SCC               PROFF_SCC4
59 #define CMXSCR_MASK             (CMXSCR_GR4|CMXSCR_SC4|\
60                                         CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
61 #define CMXSCR_VALUE            (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
62 #define CPM_CR_SCC_PAGE         CPM_CR_SCC4_PAGE
63 #define CPM_CR_SCC_SBLOCK       CPM_CR_SCC4_SBLOCK
64
65 #else
66
67 #error "console not correctly defined"
68
69 #endif
70
71 static int mpc8260_scc_serial_init(void)
72 {
73         volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
74         volatile scc_t *sp;
75         volatile scc_uart_t *up;
76         volatile cbd_t *tbdf, *rbdf;
77         volatile cpm8260_t *cp = &(im->im_cpm);
78         uint    dpaddr;
79
80         /* initialize pointers to SCC */
81
82         sp = (scc_t *) &(im->im_scc[SCC_INDEX]);
83         up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
84
85         /* Disable transmitter/receiver.
86         */
87         sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
88
89         /* put the SCC channel into NMSI (non multiplexd serial interface)
90          * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
91          */
92         im->im_cpmux.cmx_scr = (im->im_cpmux.cmx_scr&~CMXSCR_MASK)|CMXSCR_VALUE;
93
94         /* Set up the baud rate generator.
95         */
96         serial_setbrg ();
97
98         /* Allocate space for two buffer descriptors in the DP ram.
99          * damm: allocating space after the two buffers for rx/tx data
100          */
101
102         dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
103
104         /* Set the physical address of the host memory buffers in
105          * the buffer descriptors.
106          */
107         rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
108         rbdf->cbd_bufaddr = (uint) (rbdf+2);
109         rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
110         tbdf = rbdf + 1;
111         tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
112         tbdf->cbd_sc = BD_SC_WRAP;
113
114         /* Set up the uart parameters in the parameter ram.
115         */
116         up->scc_genscc.scc_rbase = dpaddr;
117         up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
118         up->scc_genscc.scc_rfcr = CPMFCR_EB;
119         up->scc_genscc.scc_tfcr = CPMFCR_EB;
120         up->scc_genscc.scc_mrblr = 1;
121         up->scc_maxidl = 0;
122         up->scc_brkcr = 1;
123         up->scc_parec = 0;
124         up->scc_frmec = 0;
125         up->scc_nosec = 0;
126         up->scc_brkec = 0;
127         up->scc_uaddr1 = 0;
128         up->scc_uaddr2 = 0;
129         up->scc_toseq = 0;
130         up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
131         up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
132         up->scc_rccm = 0xc0ff;
133
134         /* Mask all interrupts and remove anything pending.
135         */
136         sp->scc_sccm = 0;
137         sp->scc_scce = 0xffff;
138
139         /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
140         */
141         sp->scc_gsmrh = SCC_GSMRH_RFW;  /* 8 bit FIFO */
142         sp->scc_gsmrl = \
143                 SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
144
145         /* Set CTS flow control, 1 stop bit, 8 bit character length,
146          * normal async UART mode, no parity
147          */
148         sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
149
150         /* execute the "Init Rx and Tx params" CP command.
151         */
152
153         while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
154           ;
155
156         cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
157                                         0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
158
159         while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
160           ;
161
162         /* Enable transmitter/receiver.
163         */
164         sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
165
166         return (0);
167 }
168
169 static void mpc8260_scc_serial_setbrg(void)
170 {
171 #if defined(CONFIG_CONS_USE_EXTC)
172         m8260_cpm_extcbrg(SCC_INDEX, gd->baudrate,
173                 CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
174 #else
175         m8260_cpm_setbrg(SCC_INDEX, gd->baudrate);
176 #endif
177 }
178
179 static void mpc8260_scc_serial_putc(const char c)
180 {
181         volatile scc_uart_t     *up;
182         volatile cbd_t          *tbdf;
183         volatile immap_t        *im;
184
185         if (c == '\n')
186                 serial_putc ('\r');
187
188         im = (immap_t *)CONFIG_SYS_IMMR;
189         up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
190         tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
191
192         /* Wait for last character to go.
193          */
194         while (tbdf->cbd_sc & BD_SC_READY)
195                 ;
196
197         /* Load the character into the transmit buffer.
198          */
199         *(volatile char *)tbdf->cbd_bufaddr = c;
200         tbdf->cbd_datlen = 1;
201         tbdf->cbd_sc |= BD_SC_READY;
202 }
203
204 static int mpc8260_scc_serial_getc(void)
205 {
206         volatile cbd_t          *rbdf;
207         volatile scc_uart_t     *up;
208         volatile immap_t        *im;
209         unsigned char           c;
210
211         im = (immap_t *)CONFIG_SYS_IMMR;
212         up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
213         rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
214
215         /* Wait for character to show up.
216          */
217         while (rbdf->cbd_sc & BD_SC_EMPTY)
218                 ;
219
220         /* Grab the char and clear the buffer again.
221          */
222         c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
223         rbdf->cbd_sc |= BD_SC_EMPTY;
224
225         return (c);
226 }
227
228 static int mpc8260_scc_serial_tstc(void)
229 {
230         volatile cbd_t          *rbdf;
231         volatile scc_uart_t     *up;
232         volatile immap_t        *im;
233
234         im = (immap_t *)CONFIG_SYS_IMMR;
235         up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
236         rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
237
238         return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
239 }
240
241 static struct serial_device mpc8260_scc_serial_drv = {
242         .name   = "mpc8260_scc_uart",
243         .start  = mpc8260_scc_serial_init,
244         .stop   = NULL,
245         .setbrg = mpc8260_scc_serial_setbrg,
246         .putc   = mpc8260_scc_serial_putc,
247         .puts   = default_serial_puts,
248         .getc   = mpc8260_scc_serial_getc,
249         .tstc   = mpc8260_scc_serial_tstc,
250 };
251
252 void mpc8260_scc_serial_initialize(void)
253 {
254         serial_register(&mpc8260_scc_serial_drv);
255 }
256
257 __weak struct serial_device *default_serial_console(void)
258 {
259         return &mpc8260_scc_serial_drv;
260 }
261 #endif  /* CONFIG_CONS_ON_SCC */
262
263 #if defined(CONFIG_KGDB_ON_SCC)
264
265 #if defined(CONFIG_CONS_ON_SCC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
266 #error Whoops! serial console and kgdb are on the same scc serial port
267 #endif
268
269 #if CONFIG_KGDB_INDEX == 1      /* KGDB Port on SCC1 */
270
271 #define KGDB_SCC_INDEX          0
272 #define KGDB_PROFF_SCC          PROFF_SCC1
273 #define KGDB_CMXSCR_MASK        (CMXSCR_GR1|CMXSCR_SC1|\
274                                         CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
275 #define KGDB_CMXSCR_VALUE       (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
276 #define KGDB_CPM_CR_SCC_PAGE    CPM_CR_SCC1_PAGE
277 #define KGDB_CPM_CR_SCC_SBLOCK  CPM_CR_SCC1_SBLOCK
278
279 #elif CONFIG_KGDB_INDEX == 2    /* KGDB Port on SCC2 */
280
281 #define KGDB_SCC_INDEX          1
282 #define KGDB_PROFF_SCC          PROFF_SCC2
283 #define KGDB_CMXSCR_MASK        (CMXSCR_GR2|CMXSCR_SC2|\
284                                         CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
285 #define KGDB_CMXSCR_VALUE       (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
286 #define KGDB_CPM_CR_SCC_PAGE    CPM_CR_SCC2_PAGE
287 #define KGDB_CPM_CR_SCC_SBLOCK  CPM_CR_SCC2_SBLOCK
288
289 #elif CONFIG_KGDB_INDEX == 3    /* KGDB Port on SCC3 */
290
291 #define KGDB_SCC_INDEX          2
292 #define KGDB_PROFF_SCC          PROFF_SCC3
293 #define KGDB_CMXSCR_MASK        (CMXSCR_GR3|CMXSCR_SC3|\
294                                         CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
295 #define KGDB_CMXSCR_VALUE       (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
296 #define KGDB_CPM_CR_SCC_PAGE    CPM_CR_SCC3_PAGE
297 #define KGDB_CPM_CR_SCC_SBLOCK  CPM_CR_SCC3_SBLOCK
298
299 #elif CONFIG_KGDB_INDEX == 4    /* KGDB Port on SCC4 */
300
301 #define KGDB_SCC_INDEX          3
302 #define KGDB_PROFF_SCC          PROFF_SCC4
303 #define KGDB_CMXSCR_MASK        (CMXSCR_GR4|CMXSCR_SC4|\
304                                         CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
305 #define KGDB_CMXSCR_VALUE       (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
306 #define KGDB_CPM_CR_SCC_PAGE    CPM_CR_SCC4_PAGE
307 #define KGDB_CPM_CR_SCC_SBLOCK  CPM_CR_SCC4_SBLOCK
308
309 #else
310
311 #error "kgdb serial port not correctly defined"
312
313 #endif
314
315 void
316 kgdb_serial_init (void)
317 {
318         volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
319         volatile scc_t *sp;
320         volatile scc_uart_t *up;
321         volatile cbd_t *tbdf, *rbdf;
322         volatile cpm8260_t *cp = &(im->im_cpm);
323         uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
324         char *s, *e;
325
326         if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
327                 ulong rate = simple_strtoul(s, &e, 10);
328                 if (e > s && *e == '\0')
329                         speed = rate;
330         }
331
332         /* initialize pointers to SCC */
333
334         sp = (scc_t *) &(im->im_scc[KGDB_SCC_INDEX]);
335         up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
336
337         /* Disable transmitter/receiver.
338         */
339         sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
340
341         /* put the SCC channel into NMSI (non multiplexd serial interface)
342          * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
343          */
344         im->im_cpmux.cmx_scr = \
345                 (im->im_cpmux.cmx_scr & ~KGDB_CMXSCR_MASK) | KGDB_CMXSCR_VALUE;
346
347         /* Set up the baud rate generator.
348         */
349 #if defined(CONFIG_KGDB_USE_EXTC)
350         m8260_cpm_extcbrg(KGDB_SCC_INDEX, speed,
351                 CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
352 #else
353         m8260_cpm_setbrg(KGDB_SCC_INDEX, speed);
354 #endif
355
356         /* Allocate space for two buffer descriptors in the DP ram.
357          * damm: allocating space after the two buffers for rx/tx data
358          */
359
360         dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
361
362         /* Set the physical address of the host memory buffers in
363          * the buffer descriptors.
364          */
365         rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
366         rbdf->cbd_bufaddr = (uint) (rbdf+2);
367         rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
368         tbdf = rbdf + 1;
369         tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
370         tbdf->cbd_sc = BD_SC_WRAP;
371
372         /* Set up the uart parameters in the parameter ram.
373         */
374         up->scc_genscc.scc_rbase = dpaddr;
375         up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
376         up->scc_genscc.scc_rfcr = CPMFCR_EB;
377         up->scc_genscc.scc_tfcr = CPMFCR_EB;
378         up->scc_genscc.scc_mrblr = 1;
379         up->scc_maxidl = 0;
380         up->scc_brkcr = 1;
381         up->scc_parec = 0;
382         up->scc_frmec = 0;
383         up->scc_nosec = 0;
384         up->scc_brkec = 0;
385         up->scc_uaddr1 = 0;
386         up->scc_uaddr2 = 0;
387         up->scc_toseq = 0;
388         up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
389         up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
390         up->scc_rccm = 0xc0ff;
391
392         /* Mask all interrupts and remove anything pending.
393         */
394         sp->scc_sccm = 0;
395         sp->scc_scce = 0xffff;
396
397         /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
398         */
399         sp->scc_gsmrh = SCC_GSMRH_RFW;  /* 8 bit FIFO */
400         sp->scc_gsmrl = \
401                 SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
402
403         /* Set CTS flow control, 1 stop bit, 8 bit character length,
404          * normal async UART mode, no parity
405          */
406         sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
407
408         /* execute the "Init Rx and Tx params" CP command.
409         */
410
411         while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
412           ;
413
414         cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SCC_PAGE, KGDB_CPM_CR_SCC_SBLOCK,
415                                         0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
416
417         while (cp->cp_cpcr & CPM_CR_FLG)  /* wait if cp is busy */
418           ;
419
420         /* Enable transmitter/receiver.
421         */
422         sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
423
424         printf("SCC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
425 }
426
427 void
428 putDebugChar(const char c)
429 {
430         volatile scc_uart_t     *up;
431         volatile cbd_t          *tbdf;
432         volatile immap_t        *im;
433
434         if (c == '\n')
435                 putDebugChar ('\r');
436
437         im = (immap_t *)CONFIG_SYS_IMMR;
438         up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
439         tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
440
441         /* Wait for last character to go.
442          */
443         while (tbdf->cbd_sc & BD_SC_READY)
444                 ;
445
446         /* Load the character into the transmit buffer.
447          */
448         *(volatile char *)tbdf->cbd_bufaddr = c;
449         tbdf->cbd_datlen = 1;
450         tbdf->cbd_sc |= BD_SC_READY;
451 }
452
453 void
454 putDebugStr (const char *s)
455 {
456         while (*s) {
457                 putDebugChar (*s++);
458         }
459 }
460
461 int
462 getDebugChar(void)
463 {
464         volatile cbd_t          *rbdf;
465         volatile scc_uart_t     *up;
466         volatile immap_t        *im;
467         unsigned char           c;
468
469         im = (immap_t *)CONFIG_SYS_IMMR;
470         up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
471         rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
472
473         /* Wait for character to show up.
474          */
475         while (rbdf->cbd_sc & BD_SC_EMPTY)
476                 ;
477
478         /* Grab the char and clear the buffer again.
479          */
480         c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
481         rbdf->cbd_sc |= BD_SC_EMPTY;
482
483         return (c);
484 }
485
486 void
487 kgdb_interruptible(int yes)
488 {
489         return;
490 }
491
492 #endif  /* CONFIG_KGDB_ON_SCC */