183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 27742aa65SMarek Vasut /* 37742aa65SMarek Vasut * (C) Copyright 2004 47742aa65SMarek Vasut * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 57742aa65SMarek Vasut */ 67742aa65SMarek Vasut 77742aa65SMarek Vasut #include <common.h> 832057717SJoe Hershberger #include <environment.h> 97742aa65SMarek Vasut #include <serial.h> 107742aa65SMarek Vasut #include <stdio_dev.h> 117742aa65SMarek Vasut #include <post.h> 127742aa65SMarek Vasut #include <linux/compiler.h> 136d93e258SMarek Vasut #include <errno.h> 147742aa65SMarek Vasut 157742aa65SMarek Vasut DECLARE_GLOBAL_DATA_PTR; 167742aa65SMarek Vasut 177742aa65SMarek Vasut static struct serial_device *serial_devices; 187742aa65SMarek Vasut static struct serial_device *serial_current; 1932057717SJoe Hershberger /* 2032057717SJoe Hershberger * Table with supported baudrates (defined in config_xyz.h) 2132057717SJoe Hershberger */ 2232057717SJoe Hershberger static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE; 237742aa65SMarek Vasut 249cd2b9e4SMarek Vasut /** 259cd2b9e4SMarek Vasut * serial_null() - Void registration routine of a serial driver 269cd2b9e4SMarek Vasut * 279cd2b9e4SMarek Vasut * This routine implements a void registration routine of a serial 289cd2b9e4SMarek Vasut * driver. The registration routine of a particular driver is aliased 299cd2b9e4SMarek Vasut * to this empty function in case the driver is not compiled into 309cd2b9e4SMarek Vasut * U-Boot. 319cd2b9e4SMarek Vasut */ 327742aa65SMarek Vasut static void serial_null(void) 337742aa65SMarek Vasut { 347742aa65SMarek Vasut } 357742aa65SMarek Vasut 369cd2b9e4SMarek Vasut /** 3732057717SJoe Hershberger * on_baudrate() - Update the actual baudrate when the env var changes 3832057717SJoe Hershberger * 39*938b05a5SHeinrich Schuchardt * @name: changed environment variable 40*938b05a5SHeinrich Schuchardt * @value: new value of the environment variable 41*938b05a5SHeinrich Schuchardt * @op: operation (create, overwrite, or delete) 42*938b05a5SHeinrich Schuchardt * @flags: attributes of environment variable change, 43*938b05a5SHeinrich Schuchardt * see flags H_* in include/search.h 44*938b05a5SHeinrich Schuchardt * 4532057717SJoe Hershberger * This will check for a valid baudrate and only apply it if valid. 46*938b05a5SHeinrich Schuchardt * 47*938b05a5SHeinrich Schuchardt * Return: 0 on success, 1 on error 4832057717SJoe Hershberger */ 4932057717SJoe Hershberger static int on_baudrate(const char *name, const char *value, enum env_op op, 5032057717SJoe Hershberger int flags) 5132057717SJoe Hershberger { 5232057717SJoe Hershberger int i; 5332057717SJoe Hershberger int baudrate; 5432057717SJoe Hershberger 5532057717SJoe Hershberger switch (op) { 5632057717SJoe Hershberger case env_op_create: 5732057717SJoe Hershberger case env_op_overwrite: 5832057717SJoe Hershberger /* 5932057717SJoe Hershberger * Switch to new baudrate if new baudrate is supported 6032057717SJoe Hershberger */ 6132057717SJoe Hershberger baudrate = simple_strtoul(value, NULL, 10); 6232057717SJoe Hershberger 6332057717SJoe Hershberger /* Not actually changing */ 6432057717SJoe Hershberger if (gd->baudrate == baudrate) 6532057717SJoe Hershberger return 0; 6632057717SJoe Hershberger 679935175fSAxel Lin for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) { 6832057717SJoe Hershberger if (baudrate == baudrate_table[i]) 6932057717SJoe Hershberger break; 7032057717SJoe Hershberger } 719935175fSAxel Lin if (i == ARRAY_SIZE(baudrate_table)) { 7232057717SJoe Hershberger if ((flags & H_FORCE) == 0) 7332057717SJoe Hershberger printf("## Baudrate %d bps not supported\n", 7432057717SJoe Hershberger baudrate); 7532057717SJoe Hershberger return 1; 7632057717SJoe Hershberger } 7732057717SJoe Hershberger if ((flags & H_INTERACTIVE) != 0) { 7832057717SJoe Hershberger printf("## Switch baudrate to %d" 7932057717SJoe Hershberger " bps and press ENTER ...\n", baudrate); 8032057717SJoe Hershberger udelay(50000); 8132057717SJoe Hershberger } 8232057717SJoe Hershberger 8332057717SJoe Hershberger gd->baudrate = baudrate; 8432057717SJoe Hershberger 8532057717SJoe Hershberger serial_setbrg(); 8632057717SJoe Hershberger 8732057717SJoe Hershberger udelay(50000); 8832057717SJoe Hershberger 8932057717SJoe Hershberger if ((flags & H_INTERACTIVE) != 0) 9032057717SJoe Hershberger while (1) { 9132057717SJoe Hershberger if (getc() == '\r') 9232057717SJoe Hershberger break; 9332057717SJoe Hershberger } 9432057717SJoe Hershberger 9532057717SJoe Hershberger return 0; 9632057717SJoe Hershberger case env_op_delete: 9732057717SJoe Hershberger printf("## Baudrate may not be deleted\n"); 9832057717SJoe Hershberger return 1; 9932057717SJoe Hershberger default: 10032057717SJoe Hershberger return 0; 10132057717SJoe Hershberger } 10232057717SJoe Hershberger } 10332057717SJoe Hershberger U_BOOT_ENV_CALLBACK(baudrate, on_baudrate); 10432057717SJoe Hershberger 10532057717SJoe Hershberger /** 1069cd2b9e4SMarek Vasut * serial_initfunc() - Forward declare of driver registration routine 1079cd2b9e4SMarek Vasut * @name: Name of the real driver registration routine. 1089cd2b9e4SMarek Vasut * 1099cd2b9e4SMarek Vasut * This macro expands onto forward declaration of a driver registration 1109cd2b9e4SMarek Vasut * routine, which is then used below in serial_initialize() function. 1119cd2b9e4SMarek Vasut * The declaration is made weak and aliases to serial_null() so in case 1129cd2b9e4SMarek Vasut * the driver is not compiled in, the function is still declared and can 1139cd2b9e4SMarek Vasut * be used, but aliases to serial_null() and thus is optimized away. 1149cd2b9e4SMarek Vasut */ 1157742aa65SMarek Vasut #define serial_initfunc(name) \ 1167742aa65SMarek Vasut void name(void) \ 1177742aa65SMarek Vasut __attribute__((weak, alias("serial_null"))); 1187742aa65SMarek Vasut 11994a255dfSJeroen Hofstee serial_initfunc(atmel_serial_initialize); 12094a255dfSJeroen Hofstee serial_initfunc(mcf_serial_initialize); 1217742aa65SMarek Vasut serial_initfunc(mpc85xx_serial_initialize); 12294a255dfSJeroen Hofstee serial_initfunc(mpc8xx_serial_initialize); 1237742aa65SMarek Vasut serial_initfunc(mxc_serial_initialize); 12494a255dfSJeroen Hofstee serial_initfunc(ns16550_serial_initialize); 12594a255dfSJeroen Hofstee serial_initfunc(pl01x_serial_initialize); 12694a255dfSJeroen Hofstee serial_initfunc(pxa_serial_initialize); 12794a255dfSJeroen Hofstee serial_initfunc(sh_serial_initialize); 1287742aa65SMarek Vasut 1299cd2b9e4SMarek Vasut /** 1309cd2b9e4SMarek Vasut * serial_register() - Register serial driver with serial driver core 1319cd2b9e4SMarek Vasut * @dev: Pointer to the serial driver structure 1329cd2b9e4SMarek Vasut * 1339cd2b9e4SMarek Vasut * This function registers the serial driver supplied via @dev with 1349cd2b9e4SMarek Vasut * serial driver core, thus making U-Boot aware of it and making it 1359cd2b9e4SMarek Vasut * available for U-Boot to use. On platforms that still require manual 1369cd2b9e4SMarek Vasut * relocation of constant variables, relocation of the supplied structure 1379cd2b9e4SMarek Vasut * is performed. 1389cd2b9e4SMarek Vasut */ 1397742aa65SMarek Vasut void serial_register(struct serial_device *dev) 1407742aa65SMarek Vasut { 1417742aa65SMarek Vasut #ifdef CONFIG_NEEDS_MANUAL_RELOC 142f2760c4aSMarek Vasut if (dev->start) 1437742aa65SMarek Vasut dev->start += gd->reloc_off; 144f2760c4aSMarek Vasut if (dev->stop) 145f2760c4aSMarek Vasut dev->stop += gd->reloc_off; 146f2760c4aSMarek Vasut if (dev->setbrg) 1477742aa65SMarek Vasut dev->setbrg += gd->reloc_off; 148f2760c4aSMarek Vasut if (dev->getc) 1497742aa65SMarek Vasut dev->getc += gd->reloc_off; 150f2760c4aSMarek Vasut if (dev->tstc) 1517742aa65SMarek Vasut dev->tstc += gd->reloc_off; 152f2760c4aSMarek Vasut if (dev->putc) 1537742aa65SMarek Vasut dev->putc += gd->reloc_off; 154f2760c4aSMarek Vasut if (dev->puts) 1557742aa65SMarek Vasut dev->puts += gd->reloc_off; 1567742aa65SMarek Vasut #endif 1577742aa65SMarek Vasut 1587742aa65SMarek Vasut dev->next = serial_devices; 1597742aa65SMarek Vasut serial_devices = dev; 1607742aa65SMarek Vasut } 1617742aa65SMarek Vasut 1629cd2b9e4SMarek Vasut /** 1639cd2b9e4SMarek Vasut * serial_initialize() - Register all compiled-in serial port drivers 1649cd2b9e4SMarek Vasut * 1659cd2b9e4SMarek Vasut * This function registers all serial port drivers that are compiled 1669cd2b9e4SMarek Vasut * into the U-Boot binary with the serial core, thus making them 1679cd2b9e4SMarek Vasut * available to U-Boot to use. Lastly, this function assigns a default 1689cd2b9e4SMarek Vasut * serial port to the serial core. That serial port is then used as a 1699cd2b9e4SMarek Vasut * default output. 1709cd2b9e4SMarek Vasut */ 1717742aa65SMarek Vasut void serial_initialize(void) 1727742aa65SMarek Vasut { 17394a255dfSJeroen Hofstee atmel_serial_initialize(); 17494a255dfSJeroen Hofstee mcf_serial_initialize(); 1757742aa65SMarek Vasut mpc85xx_serial_initialize(); 17694a255dfSJeroen Hofstee mpc8xx_serial_initialize(); 1777742aa65SMarek Vasut mxc_serial_initialize(); 17894a255dfSJeroen Hofstee ns16550_serial_initialize(); 17994a255dfSJeroen Hofstee pl01x_serial_initialize(); 18094a255dfSJeroen Hofstee pxa_serial_initialize(); 18194a255dfSJeroen Hofstee sh_serial_initialize(); 1827742aa65SMarek Vasut 1837742aa65SMarek Vasut serial_assign(default_serial_console()->name); 1847742aa65SMarek Vasut } 1857742aa65SMarek Vasut 186654f8d0fSJeroen Hofstee static int serial_stub_start(struct stdio_dev *sdev) 187709ea543SSimon Glass { 188709ea543SSimon Glass struct serial_device *dev = sdev->priv; 189709ea543SSimon Glass 190709ea543SSimon Glass return dev->start(); 191709ea543SSimon Glass } 192709ea543SSimon Glass 193654f8d0fSJeroen Hofstee static int serial_stub_stop(struct stdio_dev *sdev) 194709ea543SSimon Glass { 195709ea543SSimon Glass struct serial_device *dev = sdev->priv; 196709ea543SSimon Glass 197709ea543SSimon Glass return dev->stop(); 198709ea543SSimon Glass } 199709ea543SSimon Glass 200654f8d0fSJeroen Hofstee static void serial_stub_putc(struct stdio_dev *sdev, const char ch) 201709ea543SSimon Glass { 202709ea543SSimon Glass struct serial_device *dev = sdev->priv; 203709ea543SSimon Glass 204709ea543SSimon Glass dev->putc(ch); 205709ea543SSimon Glass } 206709ea543SSimon Glass 207654f8d0fSJeroen Hofstee static void serial_stub_puts(struct stdio_dev *sdev, const char *str) 208709ea543SSimon Glass { 209709ea543SSimon Glass struct serial_device *dev = sdev->priv; 210709ea543SSimon Glass 211709ea543SSimon Glass dev->puts(str); 212709ea543SSimon Glass } 213709ea543SSimon Glass 21449ddcf3eSMasahiro Yamada static int serial_stub_getc(struct stdio_dev *sdev) 215709ea543SSimon Glass { 216709ea543SSimon Glass struct serial_device *dev = sdev->priv; 217709ea543SSimon Glass 218709ea543SSimon Glass return dev->getc(); 219709ea543SSimon Glass } 220709ea543SSimon Glass 22149ddcf3eSMasahiro Yamada static int serial_stub_tstc(struct stdio_dev *sdev) 222709ea543SSimon Glass { 223709ea543SSimon Glass struct serial_device *dev = sdev->priv; 224709ea543SSimon Glass 225709ea543SSimon Glass return dev->tstc(); 226709ea543SSimon Glass } 227709ea543SSimon Glass 2289cd2b9e4SMarek Vasut /** 2299cd2b9e4SMarek Vasut * serial_stdio_init() - Register serial ports with STDIO core 2309cd2b9e4SMarek Vasut * 2319cd2b9e4SMarek Vasut * This function generates a proxy driver for each serial port driver. 2329cd2b9e4SMarek Vasut * These proxy drivers then register with the STDIO core, making the 2339cd2b9e4SMarek Vasut * serial drivers available as STDIO devices. 2349cd2b9e4SMarek Vasut */ 2357742aa65SMarek Vasut void serial_stdio_init(void) 2367742aa65SMarek Vasut { 2377742aa65SMarek Vasut struct stdio_dev dev; 2387742aa65SMarek Vasut struct serial_device *s = serial_devices; 2397742aa65SMarek Vasut 2407742aa65SMarek Vasut while (s) { 2417742aa65SMarek Vasut memset(&dev, 0, sizeof(dev)); 2427742aa65SMarek Vasut 2437742aa65SMarek Vasut strcpy(dev.name, s->name); 2447742aa65SMarek Vasut dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; 2457742aa65SMarek Vasut 246709ea543SSimon Glass dev.start = serial_stub_start; 247709ea543SSimon Glass dev.stop = serial_stub_stop; 248709ea543SSimon Glass dev.putc = serial_stub_putc; 249709ea543SSimon Glass dev.puts = serial_stub_puts; 250709ea543SSimon Glass dev.getc = serial_stub_getc; 251709ea543SSimon Glass dev.tstc = serial_stub_tstc; 252addf9513SSimon Glass dev.priv = s; 2537742aa65SMarek Vasut 2547742aa65SMarek Vasut stdio_register(&dev); 2557742aa65SMarek Vasut 2567742aa65SMarek Vasut s = s->next; 2577742aa65SMarek Vasut } 2587742aa65SMarek Vasut } 2597742aa65SMarek Vasut 2609cd2b9e4SMarek Vasut /** 2619cd2b9e4SMarek Vasut * serial_assign() - Select the serial output device by name 2629cd2b9e4SMarek Vasut * @name: Name of the serial driver to be used as default output 2639cd2b9e4SMarek Vasut * 2649cd2b9e4SMarek Vasut * This function configures the serial output multiplexing by 2659cd2b9e4SMarek Vasut * selecting which serial device will be used as default. In case 2669cd2b9e4SMarek Vasut * the STDIO "serial" device is selected as stdin/stdout/stderr, 2679cd2b9e4SMarek Vasut * the serial device previously configured by this function will be 2689cd2b9e4SMarek Vasut * used for the particular operation. 2699cd2b9e4SMarek Vasut * 2709cd2b9e4SMarek Vasut * Returns 0 on success, negative on error. 2719cd2b9e4SMarek Vasut */ 2727742aa65SMarek Vasut int serial_assign(const char *name) 2737742aa65SMarek Vasut { 2747742aa65SMarek Vasut struct serial_device *s; 2757742aa65SMarek Vasut 2767742aa65SMarek Vasut for (s = serial_devices; s; s = s->next) { 2776d93e258SMarek Vasut if (strcmp(s->name, name)) 2786d93e258SMarek Vasut continue; 2797742aa65SMarek Vasut serial_current = s; 2807742aa65SMarek Vasut return 0; 2817742aa65SMarek Vasut } 2827742aa65SMarek Vasut 2836d93e258SMarek Vasut return -EINVAL; 2847742aa65SMarek Vasut } 2857742aa65SMarek Vasut 2869cd2b9e4SMarek Vasut /** 2879cd2b9e4SMarek Vasut * serial_reinit_all() - Reinitialize all compiled-in serial ports 2889cd2b9e4SMarek Vasut * 2899cd2b9e4SMarek Vasut * This function reinitializes all serial ports that are compiled 2909cd2b9e4SMarek Vasut * into U-Boot by calling their serial_start() functions. 2919cd2b9e4SMarek Vasut */ 2927742aa65SMarek Vasut void serial_reinit_all(void) 2937742aa65SMarek Vasut { 2947742aa65SMarek Vasut struct serial_device *s; 2957742aa65SMarek Vasut 2967742aa65SMarek Vasut for (s = serial_devices; s; s = s->next) 2977742aa65SMarek Vasut s->start(); 2987742aa65SMarek Vasut } 2997742aa65SMarek Vasut 3009cd2b9e4SMarek Vasut /** 3019cd2b9e4SMarek Vasut * get_current() - Return pointer to currently selected serial port 3029cd2b9e4SMarek Vasut * 3039cd2b9e4SMarek Vasut * This function returns a pointer to currently selected serial port. 3049cd2b9e4SMarek Vasut * The currently selected serial port is altered by serial_assign() 3059cd2b9e4SMarek Vasut * function. 3069cd2b9e4SMarek Vasut * 3079cd2b9e4SMarek Vasut * In case this function is called before relocation or before any serial 3089cd2b9e4SMarek Vasut * port is configured, this function calls default_serial_console() to 3099cd2b9e4SMarek Vasut * determine the serial port. Otherwise, the configured serial port is 3109cd2b9e4SMarek Vasut * returned. 3119cd2b9e4SMarek Vasut * 3129cd2b9e4SMarek Vasut * Returns pointer to the currently selected serial port on success, 3139cd2b9e4SMarek Vasut * NULL on error. 3149cd2b9e4SMarek Vasut */ 3157742aa65SMarek Vasut static struct serial_device *get_current(void) 3167742aa65SMarek Vasut { 3177742aa65SMarek Vasut struct serial_device *dev; 3187742aa65SMarek Vasut 319dee19416SMarek Vasut if (!(gd->flags & GD_FLG_RELOC)) 3207742aa65SMarek Vasut dev = default_serial_console(); 321dee19416SMarek Vasut else if (!serial_current) 322dee19416SMarek Vasut dev = default_serial_console(); 323dee19416SMarek Vasut else 324dee19416SMarek Vasut dev = serial_current; 3257742aa65SMarek Vasut 3267742aa65SMarek Vasut /* We must have a console device */ 3277742aa65SMarek Vasut if (!dev) { 3287742aa65SMarek Vasut #ifdef CONFIG_SPL_BUILD 3297742aa65SMarek Vasut puts("Cannot find console\n"); 3307742aa65SMarek Vasut hang(); 3317742aa65SMarek Vasut #else 3327742aa65SMarek Vasut panic("Cannot find console\n"); 3337742aa65SMarek Vasut #endif 3347742aa65SMarek Vasut } 335dee19416SMarek Vasut 3367742aa65SMarek Vasut return dev; 3377742aa65SMarek Vasut } 3387742aa65SMarek Vasut 3399cd2b9e4SMarek Vasut /** 3409cd2b9e4SMarek Vasut * serial_init() - Initialize currently selected serial port 3419cd2b9e4SMarek Vasut * 3429cd2b9e4SMarek Vasut * This function initializes the currently selected serial port. This 3439cd2b9e4SMarek Vasut * usually involves setting up the registers of that particular port, 3449cd2b9e4SMarek Vasut * enabling clock and such. This function uses the get_current() call 3459cd2b9e4SMarek Vasut * to determine which port is selected. 3469cd2b9e4SMarek Vasut * 3479cd2b9e4SMarek Vasut * Returns 0 on success, negative on error. 3489cd2b9e4SMarek Vasut */ 3497742aa65SMarek Vasut int serial_init(void) 3507742aa65SMarek Vasut { 351093f79abSSimon Glass gd->flags |= GD_FLG_SERIAL_READY; 3527742aa65SMarek Vasut return get_current()->start(); 3537742aa65SMarek Vasut } 3547742aa65SMarek Vasut 3559cd2b9e4SMarek Vasut /** 3569cd2b9e4SMarek Vasut * serial_setbrg() - Configure baud-rate of currently selected serial port 3579cd2b9e4SMarek Vasut * 3589cd2b9e4SMarek Vasut * This function configures the baud-rate of the currently selected 3599cd2b9e4SMarek Vasut * serial port. The baud-rate is retrieved from global data within 3609cd2b9e4SMarek Vasut * the serial port driver. This function uses the get_current() call 3619cd2b9e4SMarek Vasut * to determine which port is selected. 3629cd2b9e4SMarek Vasut * 3639cd2b9e4SMarek Vasut * Returns 0 on success, negative on error. 3649cd2b9e4SMarek Vasut */ 3657742aa65SMarek Vasut void serial_setbrg(void) 3667742aa65SMarek Vasut { 3677742aa65SMarek Vasut get_current()->setbrg(); 3687742aa65SMarek Vasut } 3697742aa65SMarek Vasut 3709cd2b9e4SMarek Vasut /** 3719cd2b9e4SMarek Vasut * serial_getc() - Read character from currently selected serial port 3729cd2b9e4SMarek Vasut * 3739cd2b9e4SMarek Vasut * This function retrieves a character from currently selected serial 3749cd2b9e4SMarek Vasut * port. In case there is no character waiting on the serial port, 3759cd2b9e4SMarek Vasut * this function will block and wait for the character to appear. This 3769cd2b9e4SMarek Vasut * function uses the get_current() call to determine which port is 3779cd2b9e4SMarek Vasut * selected. 3789cd2b9e4SMarek Vasut * 3799cd2b9e4SMarek Vasut * Returns the character on success, negative on error. 3809cd2b9e4SMarek Vasut */ 3817742aa65SMarek Vasut int serial_getc(void) 3827742aa65SMarek Vasut { 3837742aa65SMarek Vasut return get_current()->getc(); 3847742aa65SMarek Vasut } 3857742aa65SMarek Vasut 3869cd2b9e4SMarek Vasut /** 3879cd2b9e4SMarek Vasut * serial_tstc() - Test if data is available on currently selected serial port 3889cd2b9e4SMarek Vasut * 3899cd2b9e4SMarek Vasut * This function tests if one or more characters are available on 3909cd2b9e4SMarek Vasut * currently selected serial port. This function never blocks. This 3919cd2b9e4SMarek Vasut * function uses the get_current() call to determine which port is 3929cd2b9e4SMarek Vasut * selected. 3939cd2b9e4SMarek Vasut * 3949cd2b9e4SMarek Vasut * Returns positive if character is available, zero otherwise. 3959cd2b9e4SMarek Vasut */ 3967742aa65SMarek Vasut int serial_tstc(void) 3977742aa65SMarek Vasut { 3987742aa65SMarek Vasut return get_current()->tstc(); 3997742aa65SMarek Vasut } 4007742aa65SMarek Vasut 4019cd2b9e4SMarek Vasut /** 4029cd2b9e4SMarek Vasut * serial_putc() - Output character via currently selected serial port 4039cd2b9e4SMarek Vasut * @c: Single character to be output from the serial port. 4049cd2b9e4SMarek Vasut * 4059cd2b9e4SMarek Vasut * This function outputs a character via currently selected serial 4069cd2b9e4SMarek Vasut * port. This character is passed to the serial port driver responsible 4079cd2b9e4SMarek Vasut * for controlling the hardware. The hardware may still be in process 4089cd2b9e4SMarek Vasut * of transmitting another character, therefore this function may block 4099cd2b9e4SMarek Vasut * for a short amount of time. This function uses the get_current() 4109cd2b9e4SMarek Vasut * call to determine which port is selected. 4119cd2b9e4SMarek Vasut */ 4127742aa65SMarek Vasut void serial_putc(const char c) 4137742aa65SMarek Vasut { 4147742aa65SMarek Vasut get_current()->putc(c); 4157742aa65SMarek Vasut } 4167742aa65SMarek Vasut 4179cd2b9e4SMarek Vasut /** 4189cd2b9e4SMarek Vasut * serial_puts() - Output string via currently selected serial port 4199cd2b9e4SMarek Vasut * @s: Zero-terminated string to be output from the serial port. 4209cd2b9e4SMarek Vasut * 4219cd2b9e4SMarek Vasut * This function outputs a zero-terminated string via currently 4229cd2b9e4SMarek Vasut * selected serial port. This function behaves as an accelerator 4239cd2b9e4SMarek Vasut * in case the hardware can queue multiple characters for transfer. 4249cd2b9e4SMarek Vasut * The whole string that is to be output is available to the function 4259cd2b9e4SMarek Vasut * implementing the hardware manipulation. Transmitting the whole 4269cd2b9e4SMarek Vasut * string may take some time, thus this function may block for some 4279cd2b9e4SMarek Vasut * amount of time. This function uses the get_current() call to 4289cd2b9e4SMarek Vasut * determine which port is selected. 4299cd2b9e4SMarek Vasut */ 4307742aa65SMarek Vasut void serial_puts(const char *s) 4317742aa65SMarek Vasut { 4327742aa65SMarek Vasut get_current()->puts(s); 4337742aa65SMarek Vasut } 4347742aa65SMarek Vasut 4359cd2b9e4SMarek Vasut /** 4369cd2b9e4SMarek Vasut * default_serial_puts() - Output string by calling serial_putc() in loop 4379cd2b9e4SMarek Vasut * @s: Zero-terminated string to be output from the serial port. 4389cd2b9e4SMarek Vasut * 4399cd2b9e4SMarek Vasut * This function outputs a zero-terminated string by calling serial_putc() 4409cd2b9e4SMarek Vasut * in a loop. Most drivers do not support queueing more than one byte for 4419cd2b9e4SMarek Vasut * transfer, thus this function precisely implements their serial_puts(). 4429cd2b9e4SMarek Vasut * 4439cd2b9e4SMarek Vasut * To optimize the number of get_current() calls, this function only 4449cd2b9e4SMarek Vasut * calls get_current() once and then directly accesses the putc() call 4459cd2b9e4SMarek Vasut * of the &struct serial_device . 4469cd2b9e4SMarek Vasut */ 447bfb7d7a3SMarek Vasut void default_serial_puts(const char *s) 448bfb7d7a3SMarek Vasut { 449bfb7d7a3SMarek Vasut struct serial_device *dev = get_current(); 450bfb7d7a3SMarek Vasut while (*s) 451bfb7d7a3SMarek Vasut dev->putc(*s++); 452bfb7d7a3SMarek Vasut } 453bfb7d7a3SMarek Vasut 4547742aa65SMarek Vasut #if CONFIG_POST & CONFIG_SYS_POST_UART 4557742aa65SMarek Vasut static const int bauds[] = CONFIG_SYS_BAUDRATE_TABLE; 4567742aa65SMarek Vasut 4579cd2b9e4SMarek Vasut /** 4589cd2b9e4SMarek Vasut * uart_post_test() - Test the currently selected serial port using POST 4599cd2b9e4SMarek Vasut * @flags: POST framework flags 4609cd2b9e4SMarek Vasut * 4619cd2b9e4SMarek Vasut * Do a loopback test of the currently selected serial port. This 4629cd2b9e4SMarek Vasut * function is only useful in the context of the POST testing framwork. 4631b25e586SVagrant Cascadian * The serial port is first configured into loopback mode and then 4649cd2b9e4SMarek Vasut * characters are sent through it. 4659cd2b9e4SMarek Vasut * 4669cd2b9e4SMarek Vasut * Returns 0 on success, value otherwise. 4679cd2b9e4SMarek Vasut */ 4687742aa65SMarek Vasut /* Mark weak until post/cpu/.../uart.c migrate over */ 4697742aa65SMarek Vasut __weak 4707742aa65SMarek Vasut int uart_post_test(int flags) 4717742aa65SMarek Vasut { 4727742aa65SMarek Vasut unsigned char c; 4737742aa65SMarek Vasut int ret, saved_baud, b; 4747742aa65SMarek Vasut struct serial_device *saved_dev, *s; 4757742aa65SMarek Vasut 4767742aa65SMarek Vasut /* Save current serial state */ 4777742aa65SMarek Vasut ret = 0; 4787742aa65SMarek Vasut saved_dev = serial_current; 4798e261575SMasahiro Yamada saved_baud = gd->baudrate; 4807742aa65SMarek Vasut 4817742aa65SMarek Vasut for (s = serial_devices; s; s = s->next) { 4827742aa65SMarek Vasut /* If this driver doesn't support loop back, skip it */ 4837742aa65SMarek Vasut if (!s->loop) 4847742aa65SMarek Vasut continue; 4857742aa65SMarek Vasut 4867742aa65SMarek Vasut /* Test the next device */ 4877742aa65SMarek Vasut serial_current = s; 4887742aa65SMarek Vasut 4897742aa65SMarek Vasut ret = serial_init(); 4907742aa65SMarek Vasut if (ret) 4917742aa65SMarek Vasut goto done; 4927742aa65SMarek Vasut 4937742aa65SMarek Vasut /* Consume anything that happens to be queued */ 4947742aa65SMarek Vasut while (serial_tstc()) 4957742aa65SMarek Vasut serial_getc(); 4967742aa65SMarek Vasut 4977742aa65SMarek Vasut /* Enable loop back */ 4987742aa65SMarek Vasut s->loop(1); 4997742aa65SMarek Vasut 5007742aa65SMarek Vasut /* Test every available baud rate */ 5017742aa65SMarek Vasut for (b = 0; b < ARRAY_SIZE(bauds); ++b) { 5028e261575SMasahiro Yamada gd->baudrate = bauds[b]; 5037742aa65SMarek Vasut serial_setbrg(); 5047742aa65SMarek Vasut 5057742aa65SMarek Vasut /* 5067742aa65SMarek Vasut * Stick to printable chars to avoid issues: 5077742aa65SMarek Vasut * - terminal corruption 5087742aa65SMarek Vasut * - serial program reacting to sequences and sending 5097742aa65SMarek Vasut * back random extra data 5107742aa65SMarek Vasut * - most serial drivers add in extra chars (like \r\n) 5117742aa65SMarek Vasut */ 5127742aa65SMarek Vasut for (c = 0x20; c < 0x7f; ++c) { 5137742aa65SMarek Vasut /* Send it out */ 5147742aa65SMarek Vasut serial_putc(c); 5157742aa65SMarek Vasut 5167742aa65SMarek Vasut /* Make sure it's the same one */ 5177742aa65SMarek Vasut ret = (c != serial_getc()); 5187742aa65SMarek Vasut if (ret) { 5197742aa65SMarek Vasut s->loop(0); 5207742aa65SMarek Vasut goto done; 5217742aa65SMarek Vasut } 5227742aa65SMarek Vasut 5237742aa65SMarek Vasut /* Clean up the output in case it was sent */ 5247742aa65SMarek Vasut serial_putc('\b'); 5257742aa65SMarek Vasut ret = ('\b' != serial_getc()); 5267742aa65SMarek Vasut if (ret) { 5277742aa65SMarek Vasut s->loop(0); 5287742aa65SMarek Vasut goto done; 5297742aa65SMarek Vasut } 5307742aa65SMarek Vasut } 5317742aa65SMarek Vasut } 5327742aa65SMarek Vasut 5337742aa65SMarek Vasut /* Disable loop back */ 5347742aa65SMarek Vasut s->loop(0); 5357742aa65SMarek Vasut 5367742aa65SMarek Vasut /* XXX: There is no serial_stop() !? */ 5377742aa65SMarek Vasut if (s->stop) 5387742aa65SMarek Vasut s->stop(); 5397742aa65SMarek Vasut } 5407742aa65SMarek Vasut 5417742aa65SMarek Vasut done: 5427742aa65SMarek Vasut /* Restore previous serial state */ 5437742aa65SMarek Vasut serial_current = saved_dev; 5448e261575SMasahiro Yamada gd->baudrate = saved_baud; 5457742aa65SMarek Vasut serial_reinit_all(); 5467742aa65SMarek Vasut serial_setbrg(); 5477742aa65SMarek Vasut 5487742aa65SMarek Vasut return ret; 5497742aa65SMarek Vasut } 5507742aa65SMarek Vasut #endif 551