From ad1b81c88080580b5db8b89c5a3b29d85a7488fc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 29 Oct 2014 13:09:03 -0600 Subject: dm: serial: Support changing the baud rate Implement this feature in the uclass so that the baudrate can be changed with 'setenv baudrate '. Signed-off-by: Simon Glass --- drivers/serial/serial-uclass.c | 67 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'drivers/serial/serial-uclass.c') diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 71f1a5cb910..632933f5cc3 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -22,6 +23,11 @@ DECLARE_GLOBAL_DATA_PTR; /* The currently-selected console serial device */ struct udevice *cur_dev __attribute__ ((section(".data"))); +/* + * Table with supported baudrates (defined in config_xyz.h) + */ +static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE; + #ifndef CONFIG_SYS_MALLOC_F_LEN #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work" #endif @@ -177,6 +183,67 @@ int serial_stub_tstc(struct stdio_dev *sdev) return _serial_tstc(sdev->priv); } +/** + * 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; + + for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) { + if (baudrate == baudrate_table[i]) + break; + } + if (i == ARRAY_SIZE(baudrate_table)) { + 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); + static int serial_post_probe(struct udevice *dev) { struct stdio_dev sdev; -- cgit v1.2.3 From 236f2bd30262f564c0bb71638105e525ddf47b9f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 10 Nov 2014 17:16:48 -0700 Subject: dm: Allow stdio registration to be dropped Provide a CONFIG_DM_STDIO option to enable registering a serial device with the stdio library. This is seldom useful in SPL, so disable it by default when building for SPL. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- drivers/serial/serial-uclass.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/serial/serial-uclass.c') diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 632933f5cc3..cd5324cfa3b 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -163,10 +163,12 @@ void serial_stdio_init(void) { } +#ifdef CONFIG_DM_STDIO static void serial_stub_putc(struct stdio_dev *sdev, const char ch) { _serial_putc(sdev->priv, ch); } +#endif void serial_stub_puts(struct stdio_dev *sdev, const char *str) { @@ -246,9 +248,11 @@ U_BOOT_ENV_CALLBACK(baudrate, on_baudrate); static int serial_post_probe(struct udevice *dev) { - struct stdio_dev sdev; struct dm_serial_ops *ops = serial_get_ops(dev); +#ifdef CONFIG_DM_STDIO struct serial_dev_priv *upriv = dev->uclass_priv; + struct stdio_dev sdev; +#endif int ret; /* Set the baud rate */ @@ -258,9 +262,9 @@ static int serial_post_probe(struct udevice *dev) return ret; } +#ifdef CONFIG_DM_STDIO if (!(gd->flags & GD_FLG_RELOC)) return 0; - memset(&sdev, '\0', sizeof(sdev)); strncpy(sdev.name, dev->name, sizeof(sdev.name)); @@ -271,7 +275,7 @@ static int serial_post_probe(struct udevice *dev) sdev.getc = serial_stub_getc; sdev.tstc = serial_stub_tstc; stdio_register_dev(&sdev, &upriv->sdev); - +#endif return 0; } -- cgit v1.2.3