1*7742aa65SMarek Vasut /* 2*7742aa65SMarek Vasut * (C) Copyright 2004 3*7742aa65SMarek Vasut * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4*7742aa65SMarek Vasut * 5*7742aa65SMarek Vasut * See file CREDITS for list of people who contributed to this 6*7742aa65SMarek Vasut * project. 7*7742aa65SMarek Vasut * 8*7742aa65SMarek Vasut * This program is free software; you can redistribute it and/or 9*7742aa65SMarek Vasut * modify it under the terms of the GNU General Public License as 10*7742aa65SMarek Vasut * published by the Free Software Foundation; either version 2 of 11*7742aa65SMarek Vasut * the License, or (at your option) any later version. 12*7742aa65SMarek Vasut * 13*7742aa65SMarek Vasut * This program is distributed in the hope that it will be useful, 14*7742aa65SMarek Vasut * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*7742aa65SMarek Vasut * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*7742aa65SMarek Vasut * GNU General Public License for more details. 17*7742aa65SMarek Vasut * 18*7742aa65SMarek Vasut * You should have received a copy of the GNU General Public License 19*7742aa65SMarek Vasut * along with this program; if not, write to the Free Software 20*7742aa65SMarek Vasut * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21*7742aa65SMarek Vasut * MA 02111-1307 USA 22*7742aa65SMarek Vasut */ 23*7742aa65SMarek Vasut 24*7742aa65SMarek Vasut #include <common.h> 25*7742aa65SMarek Vasut #include <serial.h> 26*7742aa65SMarek Vasut #include <stdio_dev.h> 27*7742aa65SMarek Vasut #include <post.h> 28*7742aa65SMarek Vasut #include <linux/compiler.h> 29*7742aa65SMarek Vasut 30*7742aa65SMarek Vasut DECLARE_GLOBAL_DATA_PTR; 31*7742aa65SMarek Vasut 32*7742aa65SMarek Vasut static struct serial_device *serial_devices; 33*7742aa65SMarek Vasut static struct serial_device *serial_current; 34*7742aa65SMarek Vasut 35*7742aa65SMarek Vasut static void serial_null(void) 36*7742aa65SMarek Vasut { 37*7742aa65SMarek Vasut } 38*7742aa65SMarek Vasut 39*7742aa65SMarek Vasut #define serial_initfunc(name) \ 40*7742aa65SMarek Vasut void name(void) \ 41*7742aa65SMarek Vasut __attribute__((weak, alias("serial_null"))); 42*7742aa65SMarek Vasut 43*7742aa65SMarek Vasut serial_initfunc(mpc8xx_serial_initialize); 44*7742aa65SMarek Vasut serial_initfunc(ns16550_serial_initialize); 45*7742aa65SMarek Vasut serial_initfunc(pxa_serial_initialize); 46*7742aa65SMarek Vasut serial_initfunc(s3c24xx_serial_initialize); 47*7742aa65SMarek Vasut serial_initfunc(s5p_serial_initialize); 48*7742aa65SMarek Vasut serial_initfunc(zynq_serial_initalize); 49*7742aa65SMarek Vasut serial_initfunc(bfin_serial_initialize); 50*7742aa65SMarek Vasut serial_initfunc(bfin_jtag_initialize); 51*7742aa65SMarek Vasut serial_initfunc(mpc512x_serial_initialize); 52*7742aa65SMarek Vasut serial_initfunc(uartlite_serial_initialize); 53*7742aa65SMarek Vasut serial_initfunc(au1x00_serial_initialize); 54*7742aa65SMarek Vasut serial_initfunc(asc_serial_initialize); 55*7742aa65SMarek Vasut serial_initfunc(jz_serial_initialize); 56*7742aa65SMarek Vasut serial_initfunc(mpc5xx_serial_initialize); 57*7742aa65SMarek Vasut serial_initfunc(mpc8220_serial_initialize); 58*7742aa65SMarek Vasut serial_initfunc(mpc8260_scc_serial_initialize); 59*7742aa65SMarek Vasut serial_initfunc(mpc8260_smc_serial_initialize); 60*7742aa65SMarek Vasut serial_initfunc(mpc85xx_serial_initialize); 61*7742aa65SMarek Vasut serial_initfunc(iop480_serial_initialize); 62*7742aa65SMarek Vasut serial_initfunc(leon2_serial_initialize); 63*7742aa65SMarek Vasut serial_initfunc(leon3_serial_initialize); 64*7742aa65SMarek Vasut serial_initfunc(marvell_serial_initialize); 65*7742aa65SMarek Vasut serial_initfunc(amirix_serial_initialize); 66*7742aa65SMarek Vasut serial_initfunc(bmw_serial_initialize); 67*7742aa65SMarek Vasut serial_initfunc(cogent_serial_initialize); 68*7742aa65SMarek Vasut serial_initfunc(cpci750_serial_initialize); 69*7742aa65SMarek Vasut serial_initfunc(evb64260_serial_initialize); 70*7742aa65SMarek Vasut serial_initfunc(ml2_serial_initialize); 71*7742aa65SMarek Vasut serial_initfunc(sconsole_serial_initialize); 72*7742aa65SMarek Vasut serial_initfunc(p3mx_serial_initialize); 73*7742aa65SMarek Vasut serial_initfunc(altera_jtag_serial_initialize); 74*7742aa65SMarek Vasut serial_initfunc(altera_serial_initialize); 75*7742aa65SMarek Vasut serial_initfunc(atmel_serial_initialize); 76*7742aa65SMarek Vasut serial_initfunc(lpc32xx_serial_initialize); 77*7742aa65SMarek Vasut serial_initfunc(mcf_serial_initialize); 78*7742aa65SMarek Vasut serial_initfunc(ns9750_serial_initialize); 79*7742aa65SMarek Vasut serial_initfunc(oc_serial_initialize); 80*7742aa65SMarek Vasut serial_initfunc(s3c4510b_serial_initialize); 81*7742aa65SMarek Vasut serial_initfunc(s3c64xx_serial_initialize); 82*7742aa65SMarek Vasut serial_initfunc(sandbox_serial_initialize); 83*7742aa65SMarek Vasut serial_initfunc(clps7111_serial_initialize); 84*7742aa65SMarek Vasut serial_initfunc(imx_serial_initialize); 85*7742aa65SMarek Vasut serial_initfunc(ixp_serial_initialize); 86*7742aa65SMarek Vasut serial_initfunc(ks8695_serial_initialize); 87*7742aa65SMarek Vasut serial_initfunc(lh7a40x_serial_initialize); 88*7742aa65SMarek Vasut serial_initfunc(lpc2292_serial_initialize); 89*7742aa65SMarek Vasut serial_initfunc(max3100_serial_initialize); 90*7742aa65SMarek Vasut serial_initfunc(mxc_serial_initialize); 91*7742aa65SMarek Vasut serial_initfunc(netarm_serial_initialize); 92*7742aa65SMarek Vasut serial_initfunc(pl01x_serial_initialize); 93*7742aa65SMarek Vasut serial_initfunc(s3c44b0_serial_initialize); 94*7742aa65SMarek Vasut serial_initfunc(sa1100_serial_initialize); 95*7742aa65SMarek Vasut serial_initfunc(sh_serial_initialize); 96*7742aa65SMarek Vasut 97*7742aa65SMarek Vasut void serial_register(struct serial_device *dev) 98*7742aa65SMarek Vasut { 99*7742aa65SMarek Vasut #ifdef CONFIG_NEEDS_MANUAL_RELOC 100*7742aa65SMarek Vasut dev->start += gd->reloc_off; 101*7742aa65SMarek Vasut dev->setbrg += gd->reloc_off; 102*7742aa65SMarek Vasut dev->getc += gd->reloc_off; 103*7742aa65SMarek Vasut dev->tstc += gd->reloc_off; 104*7742aa65SMarek Vasut dev->putc += gd->reloc_off; 105*7742aa65SMarek Vasut dev->puts += gd->reloc_off; 106*7742aa65SMarek Vasut #endif 107*7742aa65SMarek Vasut 108*7742aa65SMarek Vasut dev->next = serial_devices; 109*7742aa65SMarek Vasut serial_devices = dev; 110*7742aa65SMarek Vasut } 111*7742aa65SMarek Vasut 112*7742aa65SMarek Vasut void serial_initialize(void) 113*7742aa65SMarek Vasut { 114*7742aa65SMarek Vasut mpc8xx_serial_initialize(); 115*7742aa65SMarek Vasut ns16550_serial_initialize(); 116*7742aa65SMarek Vasut pxa_serial_initialize(); 117*7742aa65SMarek Vasut s3c24xx_serial_initialize(); 118*7742aa65SMarek Vasut s5p_serial_initialize(); 119*7742aa65SMarek Vasut mpc512x_serial_initialize(); 120*7742aa65SMarek Vasut bfin_serial_initialize(); 121*7742aa65SMarek Vasut bfin_jtag_initialize(); 122*7742aa65SMarek Vasut uartlite_serial_initialize(); 123*7742aa65SMarek Vasut zynq_serial_initalize(); 124*7742aa65SMarek Vasut au1x00_serial_initialize(); 125*7742aa65SMarek Vasut asc_serial_initialize(); 126*7742aa65SMarek Vasut jz_serial_initialize(); 127*7742aa65SMarek Vasut mpc5xx_serial_initialize(); 128*7742aa65SMarek Vasut mpc8220_serial_initialize(); 129*7742aa65SMarek Vasut mpc8260_scc_serial_initialize(); 130*7742aa65SMarek Vasut mpc8260_smc_serial_initialize(); 131*7742aa65SMarek Vasut mpc85xx_serial_initialize(); 132*7742aa65SMarek Vasut iop480_serial_initialize(); 133*7742aa65SMarek Vasut leon2_serial_initialize(); 134*7742aa65SMarek Vasut leon3_serial_initialize(); 135*7742aa65SMarek Vasut marvell_serial_initialize(); 136*7742aa65SMarek Vasut amirix_serial_initialize(); 137*7742aa65SMarek Vasut bmw_serial_initialize(); 138*7742aa65SMarek Vasut cogent_serial_initialize(); 139*7742aa65SMarek Vasut cpci750_serial_initialize(); 140*7742aa65SMarek Vasut evb64260_serial_initialize(); 141*7742aa65SMarek Vasut ml2_serial_initialize(); 142*7742aa65SMarek Vasut sconsole_serial_initialize(); 143*7742aa65SMarek Vasut p3mx_serial_initialize(); 144*7742aa65SMarek Vasut altera_jtag_serial_initialize(); 145*7742aa65SMarek Vasut altera_serial_initialize(); 146*7742aa65SMarek Vasut atmel_serial_initialize(); 147*7742aa65SMarek Vasut lpc32xx_serial_initialize(); 148*7742aa65SMarek Vasut mcf_serial_initialize(); 149*7742aa65SMarek Vasut ns9750_serial_initialize(); 150*7742aa65SMarek Vasut oc_serial_initialize(); 151*7742aa65SMarek Vasut s3c4510b_serial_initialize(); 152*7742aa65SMarek Vasut s3c64xx_serial_initialize(); 153*7742aa65SMarek Vasut sandbox_serial_initialize(); 154*7742aa65SMarek Vasut clps7111_serial_initialize(); 155*7742aa65SMarek Vasut imx_serial_initialize(); 156*7742aa65SMarek Vasut ixp_serial_initialize(); 157*7742aa65SMarek Vasut ks8695_serial_initialize(); 158*7742aa65SMarek Vasut lh7a40x_serial_initialize(); 159*7742aa65SMarek Vasut lpc2292_serial_initialize(); 160*7742aa65SMarek Vasut max3100_serial_initialize(); 161*7742aa65SMarek Vasut mxc_serial_initialize(); 162*7742aa65SMarek Vasut netarm_serial_initialize(); 163*7742aa65SMarek Vasut pl01x_serial_initialize(); 164*7742aa65SMarek Vasut s3c44b0_serial_initialize(); 165*7742aa65SMarek Vasut sa1100_serial_initialize(); 166*7742aa65SMarek Vasut sh_serial_initialize(); 167*7742aa65SMarek Vasut 168*7742aa65SMarek Vasut serial_assign(default_serial_console()->name); 169*7742aa65SMarek Vasut } 170*7742aa65SMarek Vasut 171*7742aa65SMarek Vasut void serial_stdio_init(void) 172*7742aa65SMarek Vasut { 173*7742aa65SMarek Vasut struct stdio_dev dev; 174*7742aa65SMarek Vasut struct serial_device *s = serial_devices; 175*7742aa65SMarek Vasut 176*7742aa65SMarek Vasut while (s) { 177*7742aa65SMarek Vasut memset(&dev, 0, sizeof(dev)); 178*7742aa65SMarek Vasut 179*7742aa65SMarek Vasut strcpy(dev.name, s->name); 180*7742aa65SMarek Vasut dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; 181*7742aa65SMarek Vasut 182*7742aa65SMarek Vasut dev.start = s->start; 183*7742aa65SMarek Vasut dev.stop = s->stop; 184*7742aa65SMarek Vasut dev.putc = s->putc; 185*7742aa65SMarek Vasut dev.puts = s->puts; 186*7742aa65SMarek Vasut dev.getc = s->getc; 187*7742aa65SMarek Vasut dev.tstc = s->tstc; 188*7742aa65SMarek Vasut 189*7742aa65SMarek Vasut stdio_register(&dev); 190*7742aa65SMarek Vasut 191*7742aa65SMarek Vasut s = s->next; 192*7742aa65SMarek Vasut } 193*7742aa65SMarek Vasut } 194*7742aa65SMarek Vasut 195*7742aa65SMarek Vasut int serial_assign(const char *name) 196*7742aa65SMarek Vasut { 197*7742aa65SMarek Vasut struct serial_device *s; 198*7742aa65SMarek Vasut 199*7742aa65SMarek Vasut for (s = serial_devices; s; s = s->next) { 200*7742aa65SMarek Vasut if (strcmp(s->name, name) == 0) { 201*7742aa65SMarek Vasut serial_current = s; 202*7742aa65SMarek Vasut return 0; 203*7742aa65SMarek Vasut } 204*7742aa65SMarek Vasut } 205*7742aa65SMarek Vasut 206*7742aa65SMarek Vasut return 1; 207*7742aa65SMarek Vasut } 208*7742aa65SMarek Vasut 209*7742aa65SMarek Vasut void serial_reinit_all(void) 210*7742aa65SMarek Vasut { 211*7742aa65SMarek Vasut struct serial_device *s; 212*7742aa65SMarek Vasut 213*7742aa65SMarek Vasut for (s = serial_devices; s; s = s->next) 214*7742aa65SMarek Vasut s->start(); 215*7742aa65SMarek Vasut } 216*7742aa65SMarek Vasut 217*7742aa65SMarek Vasut static struct serial_device *get_current(void) 218*7742aa65SMarek Vasut { 219*7742aa65SMarek Vasut struct serial_device *dev; 220*7742aa65SMarek Vasut 221*7742aa65SMarek Vasut if (!(gd->flags & GD_FLG_RELOC) || !serial_current) { 222*7742aa65SMarek Vasut dev = default_serial_console(); 223*7742aa65SMarek Vasut 224*7742aa65SMarek Vasut /* We must have a console device */ 225*7742aa65SMarek Vasut if (!dev) { 226*7742aa65SMarek Vasut #ifdef CONFIG_SPL_BUILD 227*7742aa65SMarek Vasut puts("Cannot find console\n"); 228*7742aa65SMarek Vasut hang(); 229*7742aa65SMarek Vasut #else 230*7742aa65SMarek Vasut panic("Cannot find console\n"); 231*7742aa65SMarek Vasut #endif 232*7742aa65SMarek Vasut } 233*7742aa65SMarek Vasut } else 234*7742aa65SMarek Vasut dev = serial_current; 235*7742aa65SMarek Vasut return dev; 236*7742aa65SMarek Vasut } 237*7742aa65SMarek Vasut 238*7742aa65SMarek Vasut int serial_init(void) 239*7742aa65SMarek Vasut { 240*7742aa65SMarek Vasut return get_current()->start(); 241*7742aa65SMarek Vasut } 242*7742aa65SMarek Vasut 243*7742aa65SMarek Vasut void serial_setbrg(void) 244*7742aa65SMarek Vasut { 245*7742aa65SMarek Vasut get_current()->setbrg(); 246*7742aa65SMarek Vasut } 247*7742aa65SMarek Vasut 248*7742aa65SMarek Vasut int serial_getc(void) 249*7742aa65SMarek Vasut { 250*7742aa65SMarek Vasut return get_current()->getc(); 251*7742aa65SMarek Vasut } 252*7742aa65SMarek Vasut 253*7742aa65SMarek Vasut int serial_tstc(void) 254*7742aa65SMarek Vasut { 255*7742aa65SMarek Vasut return get_current()->tstc(); 256*7742aa65SMarek Vasut } 257*7742aa65SMarek Vasut 258*7742aa65SMarek Vasut void serial_putc(const char c) 259*7742aa65SMarek Vasut { 260*7742aa65SMarek Vasut get_current()->putc(c); 261*7742aa65SMarek Vasut } 262*7742aa65SMarek Vasut 263*7742aa65SMarek Vasut void serial_puts(const char *s) 264*7742aa65SMarek Vasut { 265*7742aa65SMarek Vasut get_current()->puts(s); 266*7742aa65SMarek Vasut } 267*7742aa65SMarek Vasut 268*7742aa65SMarek Vasut #if CONFIG_POST & CONFIG_SYS_POST_UART 269*7742aa65SMarek Vasut static const int bauds[] = CONFIG_SYS_BAUDRATE_TABLE; 270*7742aa65SMarek Vasut 271*7742aa65SMarek Vasut /* Mark weak until post/cpu/.../uart.c migrate over */ 272*7742aa65SMarek Vasut __weak 273*7742aa65SMarek Vasut int uart_post_test(int flags) 274*7742aa65SMarek Vasut { 275*7742aa65SMarek Vasut unsigned char c; 276*7742aa65SMarek Vasut int ret, saved_baud, b; 277*7742aa65SMarek Vasut struct serial_device *saved_dev, *s; 278*7742aa65SMarek Vasut bd_t *bd = gd->bd; 279*7742aa65SMarek Vasut 280*7742aa65SMarek Vasut /* Save current serial state */ 281*7742aa65SMarek Vasut ret = 0; 282*7742aa65SMarek Vasut saved_dev = serial_current; 283*7742aa65SMarek Vasut saved_baud = bd->bi_baudrate; 284*7742aa65SMarek Vasut 285*7742aa65SMarek Vasut for (s = serial_devices; s; s = s->next) { 286*7742aa65SMarek Vasut /* If this driver doesn't support loop back, skip it */ 287*7742aa65SMarek Vasut if (!s->loop) 288*7742aa65SMarek Vasut continue; 289*7742aa65SMarek Vasut 290*7742aa65SMarek Vasut /* Test the next device */ 291*7742aa65SMarek Vasut serial_current = s; 292*7742aa65SMarek Vasut 293*7742aa65SMarek Vasut ret = serial_init(); 294*7742aa65SMarek Vasut if (ret) 295*7742aa65SMarek Vasut goto done; 296*7742aa65SMarek Vasut 297*7742aa65SMarek Vasut /* Consume anything that happens to be queued */ 298*7742aa65SMarek Vasut while (serial_tstc()) 299*7742aa65SMarek Vasut serial_getc(); 300*7742aa65SMarek Vasut 301*7742aa65SMarek Vasut /* Enable loop back */ 302*7742aa65SMarek Vasut s->loop(1); 303*7742aa65SMarek Vasut 304*7742aa65SMarek Vasut /* Test every available baud rate */ 305*7742aa65SMarek Vasut for (b = 0; b < ARRAY_SIZE(bauds); ++b) { 306*7742aa65SMarek Vasut bd->bi_baudrate = bauds[b]; 307*7742aa65SMarek Vasut serial_setbrg(); 308*7742aa65SMarek Vasut 309*7742aa65SMarek Vasut /* 310*7742aa65SMarek Vasut * Stick to printable chars to avoid issues: 311*7742aa65SMarek Vasut * - terminal corruption 312*7742aa65SMarek Vasut * - serial program reacting to sequences and sending 313*7742aa65SMarek Vasut * back random extra data 314*7742aa65SMarek Vasut * - most serial drivers add in extra chars (like \r\n) 315*7742aa65SMarek Vasut */ 316*7742aa65SMarek Vasut for (c = 0x20; c < 0x7f; ++c) { 317*7742aa65SMarek Vasut /* Send it out */ 318*7742aa65SMarek Vasut serial_putc(c); 319*7742aa65SMarek Vasut 320*7742aa65SMarek Vasut /* Make sure it's the same one */ 321*7742aa65SMarek Vasut ret = (c != serial_getc()); 322*7742aa65SMarek Vasut if (ret) { 323*7742aa65SMarek Vasut s->loop(0); 324*7742aa65SMarek Vasut goto done; 325*7742aa65SMarek Vasut } 326*7742aa65SMarek Vasut 327*7742aa65SMarek Vasut /* Clean up the output in case it was sent */ 328*7742aa65SMarek Vasut serial_putc('\b'); 329*7742aa65SMarek Vasut ret = ('\b' != serial_getc()); 330*7742aa65SMarek Vasut if (ret) { 331*7742aa65SMarek Vasut s->loop(0); 332*7742aa65SMarek Vasut goto done; 333*7742aa65SMarek Vasut } 334*7742aa65SMarek Vasut } 335*7742aa65SMarek Vasut } 336*7742aa65SMarek Vasut 337*7742aa65SMarek Vasut /* Disable loop back */ 338*7742aa65SMarek Vasut s->loop(0); 339*7742aa65SMarek Vasut 340*7742aa65SMarek Vasut /* XXX: There is no serial_stop() !? */ 341*7742aa65SMarek Vasut if (s->stop) 342*7742aa65SMarek Vasut s->stop(); 343*7742aa65SMarek Vasut } 344*7742aa65SMarek Vasut 345*7742aa65SMarek Vasut done: 346*7742aa65SMarek Vasut /* Restore previous serial state */ 347*7742aa65SMarek Vasut serial_current = saved_dev; 348*7742aa65SMarek Vasut bd->bi_baudrate = saved_baud; 349*7742aa65SMarek Vasut serial_reinit_all(); 350*7742aa65SMarek Vasut serial_setbrg(); 351*7742aa65SMarek Vasut 352*7742aa65SMarek Vasut return ret; 353*7742aa65SMarek Vasut } 354*7742aa65SMarek Vasut #endif 355