119b8fa0bSMarek Vasut /* 219b8fa0bSMarek Vasut * (C) Copyright 2000 319b8fa0bSMarek Vasut * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. 419b8fa0bSMarek Vasut * 519b8fa0bSMarek Vasut * See file CREDITS for list of people who contributed to this 619b8fa0bSMarek Vasut * project. 719b8fa0bSMarek Vasut * 819b8fa0bSMarek Vasut * This program is free software; you can redistribute it and/or 919b8fa0bSMarek Vasut * modify it under the terms of the GNU General Public License as 1019b8fa0bSMarek Vasut * published by the Free Software Foundation; either version 2 of 1119b8fa0bSMarek Vasut * the License, or (at your option) any later version. 1219b8fa0bSMarek Vasut * 1319b8fa0bSMarek Vasut * This program is distributed in the hope that it will be useful, 1419b8fa0bSMarek Vasut * but WITHOUT ANY WARRANTY; without even the implied warranty of 1519b8fa0bSMarek Vasut * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1619b8fa0bSMarek Vasut * GNU General Public License for more details. 1719b8fa0bSMarek Vasut * 1819b8fa0bSMarek Vasut * You should have received a copy of the GNU General Public License 1919b8fa0bSMarek Vasut * along with this program; if not, write to the Free Software 2019b8fa0bSMarek Vasut * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 2119b8fa0bSMarek Vasut * MA 02111-1307 USA 2219b8fa0bSMarek Vasut */ 2319b8fa0bSMarek Vasut 2419b8fa0bSMarek Vasut #include <common.h> 2519b8fa0bSMarek Vasut #include <linux/compiler.h> 2619b8fa0bSMarek Vasut 2719b8fa0bSMarek Vasut #include <ns16550.h> 2819b8fa0bSMarek Vasut #ifdef CONFIG_NS87308 2919b8fa0bSMarek Vasut #include <ns87308.h> 3019b8fa0bSMarek Vasut #endif 3119b8fa0bSMarek Vasut 3219b8fa0bSMarek Vasut #include <serial.h> 3319b8fa0bSMarek Vasut 3419b8fa0bSMarek Vasut DECLARE_GLOBAL_DATA_PTR; 3519b8fa0bSMarek Vasut 3619b8fa0bSMarek Vasut #if !defined(CONFIG_CONS_INDEX) 3719b8fa0bSMarek Vasut #elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 4) 3819b8fa0bSMarek Vasut #error "Invalid console index value." 3919b8fa0bSMarek Vasut #endif 4019b8fa0bSMarek Vasut 4119b8fa0bSMarek Vasut #if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1) 4219b8fa0bSMarek Vasut #error "Console port 1 defined but not configured." 4319b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2) 4419b8fa0bSMarek Vasut #error "Console port 2 defined but not configured." 4519b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3) 4619b8fa0bSMarek Vasut #error "Console port 3 defined but not configured." 4719b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4) 4819b8fa0bSMarek Vasut #error "Console port 4 defined but not configured." 4919b8fa0bSMarek Vasut #endif 5019b8fa0bSMarek Vasut 5119b8fa0bSMarek Vasut /* Note: The port number specified in the functions is 1 based. 5219b8fa0bSMarek Vasut * the array is 0 based. 5319b8fa0bSMarek Vasut */ 5419b8fa0bSMarek Vasut static NS16550_t serial_ports[4] = { 5519b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM1 5619b8fa0bSMarek Vasut (NS16550_t)CONFIG_SYS_NS16550_COM1, 5719b8fa0bSMarek Vasut #else 5819b8fa0bSMarek Vasut NULL, 5919b8fa0bSMarek Vasut #endif 6019b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM2 6119b8fa0bSMarek Vasut (NS16550_t)CONFIG_SYS_NS16550_COM2, 6219b8fa0bSMarek Vasut #else 6319b8fa0bSMarek Vasut NULL, 6419b8fa0bSMarek Vasut #endif 6519b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM3 6619b8fa0bSMarek Vasut (NS16550_t)CONFIG_SYS_NS16550_COM3, 6719b8fa0bSMarek Vasut #else 6819b8fa0bSMarek Vasut NULL, 6919b8fa0bSMarek Vasut #endif 7019b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM4 7119b8fa0bSMarek Vasut (NS16550_t)CONFIG_SYS_NS16550_COM4 7219b8fa0bSMarek Vasut #else 7319b8fa0bSMarek Vasut NULL 7419b8fa0bSMarek Vasut #endif 7519b8fa0bSMarek Vasut }; 7619b8fa0bSMarek Vasut 7719b8fa0bSMarek Vasut #define PORT serial_ports[port-1] 7819b8fa0bSMarek Vasut 7919b8fa0bSMarek Vasut /* Multi serial device functions */ 8019b8fa0bSMarek Vasut #define DECLARE_ESERIAL_FUNCTIONS(port) \ 81*ac63f2a2SKim Phillips static int eserial##port##_init(void) \ 82*ac63f2a2SKim Phillips { \ 8319b8fa0bSMarek Vasut int clock_divisor; \ 8419b8fa0bSMarek Vasut clock_divisor = calc_divisor(serial_ports[port-1]); \ 8519b8fa0bSMarek Vasut NS16550_init(serial_ports[port-1], clock_divisor); \ 86*ac63f2a2SKim Phillips return 0 ; \ 87*ac63f2a2SKim Phillips } \ 88*ac63f2a2SKim Phillips static void eserial##port##_setbrg(void) \ 89*ac63f2a2SKim Phillips { \ 90*ac63f2a2SKim Phillips serial_setbrg_dev(port); \ 91*ac63f2a2SKim Phillips } \ 92*ac63f2a2SKim Phillips static int eserial##port##_getc(void) \ 93*ac63f2a2SKim Phillips { \ 94*ac63f2a2SKim Phillips return serial_getc_dev(port); \ 95*ac63f2a2SKim Phillips } \ 96*ac63f2a2SKim Phillips static int eserial##port##_tstc(void) \ 97*ac63f2a2SKim Phillips { \ 98*ac63f2a2SKim Phillips return serial_tstc_dev(port); \ 99*ac63f2a2SKim Phillips } \ 100*ac63f2a2SKim Phillips static void eserial##port##_putc(const char c) \ 101*ac63f2a2SKim Phillips { \ 102*ac63f2a2SKim Phillips serial_putc_dev(port, c); \ 103*ac63f2a2SKim Phillips } \ 104*ac63f2a2SKim Phillips static void eserial##port##_puts(const char *s) \ 105*ac63f2a2SKim Phillips { \ 106*ac63f2a2SKim Phillips serial_puts_dev(port, s); \ 107*ac63f2a2SKim Phillips } 10819b8fa0bSMarek Vasut 10919b8fa0bSMarek Vasut /* Serial device descriptor */ 11019b8fa0bSMarek Vasut #define INIT_ESERIAL_STRUCTURE(port, __name) { \ 11119b8fa0bSMarek Vasut .name = __name, \ 11219b8fa0bSMarek Vasut .start = eserial##port##_init, \ 11319b8fa0bSMarek Vasut .stop = NULL, \ 11419b8fa0bSMarek Vasut .setbrg = eserial##port##_setbrg, \ 11519b8fa0bSMarek Vasut .getc = eserial##port##_getc, \ 11619b8fa0bSMarek Vasut .tstc = eserial##port##_tstc, \ 11719b8fa0bSMarek Vasut .putc = eserial##port##_putc, \ 11819b8fa0bSMarek Vasut .puts = eserial##port##_puts, \ 11919b8fa0bSMarek Vasut } 12019b8fa0bSMarek Vasut 12119b8fa0bSMarek Vasut static int calc_divisor (NS16550_t port) 12219b8fa0bSMarek Vasut { 12319b8fa0bSMarek Vasut #ifdef CONFIG_OMAP1510 12419b8fa0bSMarek Vasut /* If can't cleanly clock 115200 set div to 1 */ 12519b8fa0bSMarek Vasut if ((CONFIG_SYS_NS16550_CLK == 12000000) && (gd->baudrate == 115200)) { 12619b8fa0bSMarek Vasut port->osc_12m_sel = OSC_12M_SEL; /* enable 6.5 * divisor */ 12719b8fa0bSMarek Vasut return (1); /* return 1 for base divisor */ 12819b8fa0bSMarek Vasut } 12919b8fa0bSMarek Vasut port->osc_12m_sel = 0; /* clear if previsouly set */ 13019b8fa0bSMarek Vasut #endif 13119b8fa0bSMarek Vasut #ifdef CONFIG_OMAP1610 13219b8fa0bSMarek Vasut /* If can't cleanly clock 115200 set div to 1 */ 13319b8fa0bSMarek Vasut if ((CONFIG_SYS_NS16550_CLK == 48000000) && (gd->baudrate == 115200)) { 13419b8fa0bSMarek Vasut return (26); /* return 26 for base divisor */ 13519b8fa0bSMarek Vasut } 13619b8fa0bSMarek Vasut #endif 13719b8fa0bSMarek Vasut 13819b8fa0bSMarek Vasut #ifdef CONFIG_APTIX 13919b8fa0bSMarek Vasut #define MODE_X_DIV 13 14019b8fa0bSMarek Vasut #else 14119b8fa0bSMarek Vasut #define MODE_X_DIV 16 14219b8fa0bSMarek Vasut #endif 14319b8fa0bSMarek Vasut 14419b8fa0bSMarek Vasut /* Compute divisor value. Normally, we should simply return: 14519b8fa0bSMarek Vasut * CONFIG_SYS_NS16550_CLK) / MODE_X_DIV / gd->baudrate 14619b8fa0bSMarek Vasut * but we need to round that value by adding 0.5. 14719b8fa0bSMarek Vasut * Rounding is especially important at high baud rates. 14819b8fa0bSMarek Vasut */ 14919b8fa0bSMarek Vasut return (CONFIG_SYS_NS16550_CLK + (gd->baudrate * (MODE_X_DIV / 2))) / 15019b8fa0bSMarek Vasut (MODE_X_DIV * gd->baudrate); 15119b8fa0bSMarek Vasut } 15219b8fa0bSMarek Vasut 15319b8fa0bSMarek Vasut void 15419b8fa0bSMarek Vasut _serial_putc(const char c,const int port) 15519b8fa0bSMarek Vasut { 15619b8fa0bSMarek Vasut if (c == '\n') 15719b8fa0bSMarek Vasut NS16550_putc(PORT, '\r'); 15819b8fa0bSMarek Vasut 15919b8fa0bSMarek Vasut NS16550_putc(PORT, c); 16019b8fa0bSMarek Vasut } 16119b8fa0bSMarek Vasut 16219b8fa0bSMarek Vasut void 16319b8fa0bSMarek Vasut _serial_putc_raw(const char c,const int port) 16419b8fa0bSMarek Vasut { 16519b8fa0bSMarek Vasut NS16550_putc(PORT, c); 16619b8fa0bSMarek Vasut } 16719b8fa0bSMarek Vasut 16819b8fa0bSMarek Vasut void 16919b8fa0bSMarek Vasut _serial_puts (const char *s,const int port) 17019b8fa0bSMarek Vasut { 17119b8fa0bSMarek Vasut while (*s) { 17219b8fa0bSMarek Vasut _serial_putc (*s++,port); 17319b8fa0bSMarek Vasut } 17419b8fa0bSMarek Vasut } 17519b8fa0bSMarek Vasut 17619b8fa0bSMarek Vasut 17719b8fa0bSMarek Vasut int 17819b8fa0bSMarek Vasut _serial_getc(const int port) 17919b8fa0bSMarek Vasut { 18019b8fa0bSMarek Vasut return NS16550_getc(PORT); 18119b8fa0bSMarek Vasut } 18219b8fa0bSMarek Vasut 18319b8fa0bSMarek Vasut int 18419b8fa0bSMarek Vasut _serial_tstc(const int port) 18519b8fa0bSMarek Vasut { 18619b8fa0bSMarek Vasut return NS16550_tstc(PORT); 18719b8fa0bSMarek Vasut } 18819b8fa0bSMarek Vasut 18919b8fa0bSMarek Vasut void 19019b8fa0bSMarek Vasut _serial_setbrg (const int port) 19119b8fa0bSMarek Vasut { 19219b8fa0bSMarek Vasut int clock_divisor; 19319b8fa0bSMarek Vasut 19419b8fa0bSMarek Vasut clock_divisor = calc_divisor(PORT); 19519b8fa0bSMarek Vasut NS16550_reinit(PORT, clock_divisor); 19619b8fa0bSMarek Vasut } 19719b8fa0bSMarek Vasut 19819b8fa0bSMarek Vasut static inline void 19919b8fa0bSMarek Vasut serial_putc_dev(unsigned int dev_index,const char c) 20019b8fa0bSMarek Vasut { 20119b8fa0bSMarek Vasut _serial_putc(c,dev_index); 20219b8fa0bSMarek Vasut } 20319b8fa0bSMarek Vasut 20419b8fa0bSMarek Vasut static inline void 20519b8fa0bSMarek Vasut serial_putc_raw_dev(unsigned int dev_index,const char c) 20619b8fa0bSMarek Vasut { 20719b8fa0bSMarek Vasut _serial_putc_raw(c,dev_index); 20819b8fa0bSMarek Vasut } 20919b8fa0bSMarek Vasut 21019b8fa0bSMarek Vasut static inline void 21119b8fa0bSMarek Vasut serial_puts_dev(unsigned int dev_index,const char *s) 21219b8fa0bSMarek Vasut { 21319b8fa0bSMarek Vasut _serial_puts(s,dev_index); 21419b8fa0bSMarek Vasut } 21519b8fa0bSMarek Vasut 21619b8fa0bSMarek Vasut static inline int 21719b8fa0bSMarek Vasut serial_getc_dev(unsigned int dev_index) 21819b8fa0bSMarek Vasut { 21919b8fa0bSMarek Vasut return _serial_getc(dev_index); 22019b8fa0bSMarek Vasut } 22119b8fa0bSMarek Vasut 22219b8fa0bSMarek Vasut static inline int 22319b8fa0bSMarek Vasut serial_tstc_dev(unsigned int dev_index) 22419b8fa0bSMarek Vasut { 22519b8fa0bSMarek Vasut return _serial_tstc(dev_index); 22619b8fa0bSMarek Vasut } 22719b8fa0bSMarek Vasut 22819b8fa0bSMarek Vasut static inline void 22919b8fa0bSMarek Vasut serial_setbrg_dev(unsigned int dev_index) 23019b8fa0bSMarek Vasut { 23119b8fa0bSMarek Vasut _serial_setbrg(dev_index); 23219b8fa0bSMarek Vasut } 23319b8fa0bSMarek Vasut 23419b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(1); 23519b8fa0bSMarek Vasut struct serial_device eserial1_device = 23619b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(1, "eserial0"); 23719b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(2); 23819b8fa0bSMarek Vasut struct serial_device eserial2_device = 23919b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(2, "eserial1"); 24019b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(3); 24119b8fa0bSMarek Vasut struct serial_device eserial3_device = 24219b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(3, "eserial2"); 24319b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(4); 24419b8fa0bSMarek Vasut struct serial_device eserial4_device = 24519b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(4, "eserial3"); 24619b8fa0bSMarek Vasut 24719b8fa0bSMarek Vasut __weak struct serial_device *default_serial_console(void) 24819b8fa0bSMarek Vasut { 24919b8fa0bSMarek Vasut #if CONFIG_CONS_INDEX == 1 25019b8fa0bSMarek Vasut return &eserial1_device; 25119b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 2 25219b8fa0bSMarek Vasut return &eserial2_device; 25319b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 3 25419b8fa0bSMarek Vasut return &eserial3_device; 25519b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 4 25619b8fa0bSMarek Vasut return &eserial4_device; 25719b8fa0bSMarek Vasut #else 25819b8fa0bSMarek Vasut #error "Bad CONFIG_CONS_INDEX." 25919b8fa0bSMarek Vasut #endif 26019b8fa0bSMarek Vasut } 26119b8fa0bSMarek Vasut 26219b8fa0bSMarek Vasut void ns16550_serial_initialize(void) 26319b8fa0bSMarek Vasut { 26419b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM1) 26519b8fa0bSMarek Vasut serial_register(&eserial1_device); 26619b8fa0bSMarek Vasut #endif 26719b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM2) 26819b8fa0bSMarek Vasut serial_register(&eserial2_device); 26919b8fa0bSMarek Vasut #endif 27019b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM3) 27119b8fa0bSMarek Vasut serial_register(&eserial3_device); 27219b8fa0bSMarek Vasut #endif 27319b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM4) 27419b8fa0bSMarek Vasut serial_register(&eserial4_device); 27519b8fa0bSMarek Vasut #endif 27619b8fa0bSMarek Vasut } 277