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 
mpc8260_scc_serial_init(void)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 
mpc8260_scc_serial_setbrg(void)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 
mpc8260_scc_serial_putc(const char c)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 
mpc8260_scc_serial_getc(void)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 
mpc8260_scc_serial_tstc(void)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 
mpc8260_scc_serial_initialize(void)252 void mpc8260_scc_serial_initialize(void)
253 {
254 	serial_register(&mpc8260_scc_serial_drv);
255 }
256 
default_serial_console(void)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
kgdb_serial_init(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
putDebugChar(const char c)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
putDebugStr(const char * s)454 putDebugStr (const char *s)
455 {
456 	while (*s) {
457 		putDebugChar (*s++);
458 	}
459 }
460 
461 int
getDebugChar(void)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
kgdb_interruptible(int yes)487 kgdb_interruptible(int yes)
488 {
489 	return;
490 }
491 
492 #endif	/* CONFIG_KGDB_ON_SCC */
493