serial.c 16.4 KB
Newer Older
W
wdenk 已提交
1 2 3 4
/*
 * (C) Copyright 2004
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
5
 * SPDX-License-Identifier:	GPL-2.0+
W
wdenk 已提交
6 7 8
 */

#include <common.h>
J
Joe Hershberger 已提交
9
#include <environment.h>
W
wdenk 已提交
10
#include <serial.h>
11
#include <stdio_dev.h>
12 13
#include <post.h>
#include <linux/compiler.h>
M
Marek Vasut 已提交
14
#include <errno.h>
W
wdenk 已提交
15

16 17
DECLARE_GLOBAL_DATA_PTR;

18 19
static struct serial_device *serial_devices;
static struct serial_device *serial_current;
J
Joe Hershberger 已提交
20 21 22 23
/*
 * Table with supported baudrates (defined in config_xyz.h)
 */
static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
W
wdenk 已提交
24

25 26 27 28 29 30 31 32
/**
 * serial_null() - Void registration routine of a serial driver
 *
 * This routine implements a void registration routine of a serial
 * driver. The registration routine of a particular driver is aliased
 * to this empty function in case the driver is not compiled into
 * U-Boot.
 */
33 34 35 36
static void serial_null(void)
{
}

J
Joe Hershberger 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
/**
 * on_baudrate() - Update the actual baudrate when the env var changes
 *
 * This will check for a valid baudrate and only apply it if valid.
 */
static int on_baudrate(const char *name, const char *value, enum env_op op,
	int flags)
{
	int i;
	int baudrate;

	switch (op) {
	case env_op_create:
	case env_op_overwrite:
		/*
		 * Switch to new baudrate if new baudrate is supported
		 */
		baudrate = simple_strtoul(value, NULL, 10);

		/* Not actually changing */
		if (gd->baudrate == baudrate)
			return 0;

60
		for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
J
Joe Hershberger 已提交
61 62 63
			if (baudrate == baudrate_table[i])
				break;
		}
64
		if (i == ARRAY_SIZE(baudrate_table)) {
J
Joe Hershberger 已提交
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
			if ((flags & H_FORCE) == 0)
				printf("## Baudrate %d bps not supported\n",
					baudrate);
			return 1;
		}
		if ((flags & H_INTERACTIVE) != 0) {
			printf("## Switch baudrate to %d"
				" bps and press ENTER ...\n", baudrate);
			udelay(50000);
		}

		gd->baudrate = baudrate;

		serial_setbrg();

		udelay(50000);

		if ((flags & H_INTERACTIVE) != 0)
			while (1) {
				if (getc() == '\r')
					break;
			}

		return 0;
	case env_op_delete:
		printf("## Baudrate may not be deleted\n");
		return 1;
	default:
		return 0;
	}
}
U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);

98 99 100 101 102 103 104 105 106 107
/**
 * serial_initfunc() - Forward declare of driver registration routine
 * @name:	Name of the real driver registration routine.
 *
 * This macro expands onto forward declaration of a driver registration
 * routine, which is then used below in serial_initialize() function.
 * The declaration is made weak and aliases to serial_null() so in case
 * the driver is not compiled in, the function is still declared and can
 * be used, but aliases to serial_null() and thus is optimized away.
 */
108 109 110 111
#define serial_initfunc(name)					\
	void name(void)						\
		__attribute__((weak, alias("serial_null")));

112 113
serial_initfunc(altera_jtag_serial_initialize);
serial_initfunc(altera_serial_initialize);
114
serial_initfunc(amirix_serial_initialize);
115 116 117 118 119 120 121
serial_initfunc(arc_serial_initialize);
serial_initfunc(arm_dcc_initialize);
serial_initfunc(asc_serial_initialize);
serial_initfunc(atmel_serial_initialize);
serial_initfunc(au1x00_serial_initialize);
serial_initfunc(bfin_jtag_initialize);
serial_initfunc(bfin_serial_initialize);
122
serial_initfunc(bmw_serial_initialize);
123
serial_initfunc(clps7111_serial_initialize);
124
serial_initfunc(cogent_serial_initialize);
125
serial_initfunc(cpci750_serial_initialize);
126
serial_initfunc(evb64260_serial_initialize);
127
serial_initfunc(imx_serial_initialize);
128 129 130 131
serial_initfunc(iop480_serial_initialize);
serial_initfunc(jz_serial_initialize);
serial_initfunc(leon2_serial_initialize);
serial_initfunc(leon3_serial_initialize);
132
serial_initfunc(lh7a40x_serial_initialize);
133 134
serial_initfunc(lpc32xx_serial_initialize);
serial_initfunc(marvell_serial_initialize);
135
serial_initfunc(max3100_serial_initialize);
136 137 138 139 140 141 142 143
serial_initfunc(mcf_serial_initialize);
serial_initfunc(ml2_serial_initialize);
serial_initfunc(mpc512x_serial_initialize);
serial_initfunc(mpc5xx_serial_initialize);
serial_initfunc(mpc8260_scc_serial_initialize);
serial_initfunc(mpc8260_smc_serial_initialize);
serial_initfunc(mpc85xx_serial_initialize);
serial_initfunc(mpc8xx_serial_initialize);
144
serial_initfunc(mxc_serial_initialize);
145 146 147 148
serial_initfunc(mxs_auart_initialize);
serial_initfunc(ns16550_serial_initialize);
serial_initfunc(oc_serial_initialize);
serial_initfunc(p3mx_serial_initialize);
149
serial_initfunc(pl01x_serial_initialize);
150 151 152
serial_initfunc(pxa_serial_initialize);
serial_initfunc(s3c24xx_serial_initialize);
serial_initfunc(s5p_serial_initialize);
153
serial_initfunc(sa1100_serial_initialize);
154 155
serial_initfunc(sandbox_serial_initialize);
serial_initfunc(sconsole_serial_initialize);
156
serial_initfunc(sh_serial_initialize);
157 158
serial_initfunc(uartlite_serial_initialize);
serial_initfunc(zynq_serial_initialize);
159

160 161 162 163 164 165 166 167 168 169
/**
 * serial_register() - Register serial driver with serial driver core
 * @dev:	Pointer to the serial driver structure
 *
 * This function registers the serial driver supplied via @dev with
 * serial driver core, thus making U-Boot aware of it and making it
 * available for U-Boot to use. On platforms that still require manual
 * relocation of constant variables, relocation of the supplied structure
 * is performed.
 */
170
void serial_register(struct serial_device *dev)
W
wdenk 已提交
171
{
172
#ifdef CONFIG_NEEDS_MANUAL_RELOC
173 174 175 176 177 178 179 180 181 182 183 184 185 186
	if (dev->start)
		dev->start += gd->reloc_off;
	if (dev->stop)
		dev->stop += gd->reloc_off;
	if (dev->setbrg)
		dev->setbrg += gd->reloc_off;
	if (dev->getc)
		dev->getc += gd->reloc_off;
	if (dev->tstc)
		dev->tstc += gd->reloc_off;
	if (dev->putc)
		dev->putc += gd->reloc_off;
	if (dev->puts)
		dev->puts += gd->reloc_off;
187
#endif
W
wdenk 已提交
188 189 190 191 192

	dev->next = serial_devices;
	serial_devices = dev;
}

193 194 195 196 197 198 199 200 201
/**
 * serial_initialize() - Register all compiled-in serial port drivers
 *
 * This function registers all serial port drivers that are compiled
 * into the U-Boot binary with the serial core, thus making them
 * available to U-Boot to use. Lastly, this function assigns a default
 * serial port to the serial core. That serial port is then used as a
 * default output.
 */
202
void serial_initialize(void)
W
wdenk 已提交
203
{
204 205
	altera_jtag_serial_initialize();
	altera_serial_initialize();
206
	amirix_serial_initialize();
207 208 209 210 211 212 213
	arc_serial_initialize();
	arm_dcc_initialize();
	asc_serial_initialize();
	atmel_serial_initialize();
	au1x00_serial_initialize();
	bfin_jtag_initialize();
	bfin_serial_initialize();
214
	bmw_serial_initialize();
215
	clps7111_serial_initialize();
216
	cogent_serial_initialize();
217
	cpci750_serial_initialize();
218
	evb64260_serial_initialize();
219
	imx_serial_initialize();
220 221 222 223
	iop480_serial_initialize();
	jz_serial_initialize();
	leon2_serial_initialize();
	leon3_serial_initialize();
224
	lh7a40x_serial_initialize();
225 226
	lpc32xx_serial_initialize();
	marvell_serial_initialize();
227
	max3100_serial_initialize();
228 229 230 231 232 233 234 235
	mcf_serial_initialize();
	ml2_serial_initialize();
	mpc512x_serial_initialize();
	mpc5xx_serial_initialize();
	mpc8260_scc_serial_initialize();
	mpc8260_smc_serial_initialize();
	mpc85xx_serial_initialize();
	mpc8xx_serial_initialize();
236
	mxc_serial_initialize();
237 238 239 240
	mxs_auart_initialize();
	ns16550_serial_initialize();
	oc_serial_initialize();
	p3mx_serial_initialize();
241
	pl01x_serial_initialize();
242 243 244
	pxa_serial_initialize();
	s3c24xx_serial_initialize();
	s5p_serial_initialize();
245
	sa1100_serial_initialize();
246 247
	sandbox_serial_initialize();
	sconsole_serial_initialize();
248
	sh_serial_initialize();
249 250
	uartlite_serial_initialize();
	zynq_serial_initialize();
251

252
	serial_assign(default_serial_console()->name);
W
wdenk 已提交
253 254
}

255
static int serial_stub_start(struct stdio_dev *sdev)
256 257 258 259 260 261
{
	struct serial_device *dev = sdev->priv;

	return dev->start();
}

262
static int serial_stub_stop(struct stdio_dev *sdev)
263 264 265 266 267 268
{
	struct serial_device *dev = sdev->priv;

	return dev->stop();
}

269
static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
270 271 272 273 274 275
{
	struct serial_device *dev = sdev->priv;

	dev->putc(ch);
}

276
static void serial_stub_puts(struct stdio_dev *sdev, const char *str)
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
{
	struct serial_device *dev = sdev->priv;

	dev->puts(str);
}

int serial_stub_getc(struct stdio_dev *sdev)
{
	struct serial_device *dev = sdev->priv;

	return dev->getc();
}

int serial_stub_tstc(struct stdio_dev *sdev)
{
	struct serial_device *dev = sdev->priv;

	return dev->tstc();
}

297 298 299 300 301 302 303
/**
 * serial_stdio_init() - Register serial ports with STDIO core
 *
 * This function generates a proxy driver for each serial port driver.
 * These proxy drivers then register with the STDIO core, making the
 * serial drivers available as STDIO devices.
 */
304
void serial_stdio_init(void)
W
wdenk 已提交
305
{
306
	struct stdio_dev dev;
W
wdenk 已提交
307 308
	struct serial_device *s = serial_devices;

W
wdenk 已提交
309
	while (s) {
310
		memset(&dev, 0, sizeof(dev));
W
wdenk 已提交
311

312
		strcpy(dev.name, s->name);
W
wdenk 已提交
313 314
		dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;

315 316 317 318 319 320
		dev.start = serial_stub_start;
		dev.stop = serial_stub_stop;
		dev.putc = serial_stub_putc;
		dev.puts = serial_stub_puts;
		dev.getc = serial_stub_getc;
		dev.tstc = serial_stub_tstc;
321
		dev.priv = s;
W
wdenk 已提交
322

323
		stdio_register(&dev);
W
wdenk 已提交
324 325 326 327 328

		s = s->next;
	}
}

329 330 331 332 333 334 335 336 337 338 339 340
/**
 * serial_assign() - Select the serial output device by name
 * @name:	Name of the serial driver to be used as default output
 *
 * This function configures the serial output multiplexing by
 * selecting which serial device will be used as default. In case
 * the STDIO "serial" device is selected as stdin/stdout/stderr,
 * the serial device previously configured by this function will be
 * used for the particular operation.
 *
 * Returns 0 on success, negative on error.
 */
341
int serial_assign(const char *name)
W
wdenk 已提交
342 343 344
{
	struct serial_device *s;

W
wdenk 已提交
345
	for (s = serial_devices; s; s = s->next) {
M
Marek Vasut 已提交
346 347 348 349
		if (strcmp(s->name, name))
			continue;
		serial_current = s;
		return 0;
W
wdenk 已提交
350 351
	}

M
Marek Vasut 已提交
352
	return -EINVAL;
W
wdenk 已提交
353 354
}

355 356 357 358 359 360
/**
 * serial_reinit_all() - Reinitialize all compiled-in serial ports
 *
 * This function reinitializes all serial ports that are compiled
 * into U-Boot by calling their serial_start() functions.
 */
361
void serial_reinit_all(void)
W
wdenk 已提交
362 363 364
{
	struct serial_device *s;

365
	for (s = serial_devices; s; s = s->next)
366
		s->start();
W
wdenk 已提交
367 368
}

369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
/**
 * get_current() - Return pointer to currently selected serial port
 *
 * This function returns a pointer to currently selected serial port.
 * The currently selected serial port is altered by serial_assign()
 * function.
 *
 * In case this function is called before relocation or before any serial
 * port is configured, this function calls default_serial_console() to
 * determine the serial port. Otherwise, the configured serial port is
 * returned.
 *
 * Returns pointer to the currently selected serial port on success,
 * NULL on error.
 */
384
static struct serial_device *get_current(void)
W
wdenk 已提交
385
{
386
	struct serial_device *dev;
W
wdenk 已提交
387

M
Marek Vasut 已提交
388
	if (!(gd->flags & GD_FLG_RELOC))
389
		dev = default_serial_console();
M
Marek Vasut 已提交
390 391 392 393
	else if (!serial_current)
		dev = default_serial_console();
	else
		dev = serial_current;
394

M
Marek Vasut 已提交
395 396
	/* We must have a console device */
	if (!dev) {
397
#ifdef CONFIG_SPL_BUILD
M
Marek Vasut 已提交
398 399
		puts("Cannot find console\n");
		hang();
400
#else
M
Marek Vasut 已提交
401
		panic("Cannot find console\n");
402
#endif
M
Marek Vasut 已提交
403 404
	}

405 406
	return dev;
}
W
wdenk 已提交
407

408 409 410 411 412 413 414 415 416 417
/**
 * serial_init() - Initialize currently selected serial port
 *
 * This function initializes the currently selected serial port. This
 * usually involves setting up the registers of that particular port,
 * enabling clock and such. This function uses the get_current() call
 * to determine which port is selected.
 *
 * Returns 0 on success, negative on error.
 */
418 419
int serial_init(void)
{
420
	gd->flags |= GD_FLG_SERIAL_READY;
421
	return get_current()->start();
W
wdenk 已提交
422 423
}

424 425 426 427 428 429 430 431 432 433
/**
 * serial_setbrg() - Configure baud-rate of currently selected serial port
 *
 * This function configures the baud-rate of the currently selected
 * serial port. The baud-rate is retrieved from global data within
 * the serial port driver. This function uses the get_current() call
 * to determine which port is selected.
 *
 * Returns 0 on success, negative on error.
 */
434
void serial_setbrg(void)
W
wdenk 已提交
435
{
436
	get_current()->setbrg();
W
wdenk 已提交
437 438
}

439 440 441 442 443 444 445 446 447 448 449
/**
 * serial_getc() - Read character from currently selected serial port
 *
 * This function retrieves a character from currently selected serial
 * port. In case there is no character waiting on the serial port,
 * this function will block and wait for the character to appear. This
 * function uses the get_current() call to determine which port is
 * selected.
 *
 * Returns the character on success, negative on error.
 */
450
int serial_getc(void)
W
wdenk 已提交
451
{
452
	return get_current()->getc();
W
wdenk 已提交
453 454
}

455 456 457 458 459 460 461 462 463 464
/**
 * serial_tstc() - Test if data is available on currently selected serial port
 *
 * This function tests if one or more characters are available on
 * currently selected serial port. This function never blocks. This
 * function uses the get_current() call to determine which port is
 * selected.
 *
 * Returns positive if character is available, zero otherwise.
 */
465
int serial_tstc(void)
W
wdenk 已提交
466
{
467
	return get_current()->tstc();
W
wdenk 已提交
468 469
}

470 471 472 473 474 475 476 477 478 479 480
/**
 * serial_putc() - Output character via currently selected serial port
 * @c:	Single character to be output from the serial port.
 *
 * This function outputs a character via currently selected serial
 * port. This character is passed to the serial port driver responsible
 * for controlling the hardware. The hardware may still be in process
 * of transmitting another character, therefore this function may block
 * for a short amount of time. This function uses the get_current()
 * call to determine which port is selected.
 */
481
void serial_putc(const char c)
W
wdenk 已提交
482
{
483
	get_current()->putc(c);
W
wdenk 已提交
484 485
}

486 487 488 489 490 491 492 493 494 495 496 497 498
/**
 * serial_puts() - Output string via currently selected serial port
 * @s:	Zero-terminated string to be output from the serial port.
 *
 * This function outputs a zero-terminated string via currently
 * selected serial port. This function behaves as an accelerator
 * in case the hardware can queue multiple characters for transfer.
 * The whole string that is to be output is available to the function
 * implementing the hardware manipulation. Transmitting the whole
 * string may take some time, thus this function may block for some
 * amount of time. This function uses the get_current() call to
 * determine which port is selected.
 */
499
void serial_puts(const char *s)
W
wdenk 已提交
500
{
501
	get_current()->puts(s);
W
wdenk 已提交
502
}
503

504 505 506 507 508 509 510 511 512 513 514 515
/**
 * default_serial_puts() - Output string by calling serial_putc() in loop
 * @s:	Zero-terminated string to be output from the serial port.
 *
 * This function outputs a zero-terminated string by calling serial_putc()
 * in a loop. Most drivers do not support queueing more than one byte for
 * transfer, thus this function precisely implements their serial_puts().
 *
 * To optimize the number of get_current() calls, this function only
 * calls get_current() once and then directly accesses the putc() call
 * of the &struct serial_device .
 */
516 517 518 519 520 521 522
void default_serial_puts(const char *s)
{
	struct serial_device *dev = get_current();
	while (*s)
		dev->putc(*s++);
}

523 524 525
#if CONFIG_POST & CONFIG_SYS_POST_UART
static const int bauds[] = CONFIG_SYS_BAUDRATE_TABLE;

526 527 528 529 530 531 532 533 534 535 536
/**
 * uart_post_test() - Test the currently selected serial port using POST
 * @flags:	POST framework flags
 *
 * Do a loopback test of the currently selected serial port. This
 * function is only useful in the context of the POST testing framwork.
 * The serial port is firstly configured into loopback mode and then
 * characters are sent through it.
 *
 * Returns 0 on success, value otherwise.
 */
537 538 539 540 541 542 543 544 545 546 547
/* Mark weak until post/cpu/.../uart.c migrate over */
__weak
int uart_post_test(int flags)
{
	unsigned char c;
	int ret, saved_baud, b;
	struct serial_device *saved_dev, *s;

	/* Save current serial state */
	ret = 0;
	saved_dev = serial_current;
548
	saved_baud = gd->baudrate;
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570

	for (s = serial_devices; s; s = s->next) {
		/* If this driver doesn't support loop back, skip it */
		if (!s->loop)
			continue;

		/* Test the next device */
		serial_current = s;

		ret = serial_init();
		if (ret)
			goto done;

		/* Consume anything that happens to be queued */
		while (serial_tstc())
			serial_getc();

		/* Enable loop back */
		s->loop(1);

		/* Test every available baud rate */
		for (b = 0; b < ARRAY_SIZE(bauds); ++b) {
571
			gd->baudrate = bauds[b];
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
			serial_setbrg();

			/*
			 * Stick to printable chars to avoid issues:
			 *  - terminal corruption
			 *  - serial program reacting to sequences and sending
			 *    back random extra data
			 *  - most serial drivers add in extra chars (like \r\n)
			 */
			for (c = 0x20; c < 0x7f; ++c) {
				/* Send it out */
				serial_putc(c);

				/* Make sure it's the same one */
				ret = (c != serial_getc());
				if (ret) {
					s->loop(0);
					goto done;
				}

				/* Clean up the output in case it was sent */
				serial_putc('\b');
				ret = ('\b' != serial_getc());
				if (ret) {
					s->loop(0);
					goto done;
				}
			}
		}

		/* Disable loop back */
		s->loop(0);

605 606 607
		/* XXX: There is no serial_stop() !? */
		if (s->stop)
			s->stop();
608 609 610 611 612
	}

 done:
	/* Restore previous serial state */
	serial_current = saved_dev;
613
	gd->baudrate = saved_baud;
614 615 616 617 618 619
	serial_reinit_all();
	serial_setbrg();

	return ret;
}
#endif