1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 219b8fa0bSMarek Vasut /* 319b8fa0bSMarek Vasut * (C) Copyright 2000 419b8fa0bSMarek Vasut * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. 519b8fa0bSMarek Vasut */ 619b8fa0bSMarek Vasut 719b8fa0bSMarek Vasut #include <common.h> 819b8fa0bSMarek Vasut #include <linux/compiler.h> 919b8fa0bSMarek Vasut 1019b8fa0bSMarek Vasut #include <ns16550.h> 1119b8fa0bSMarek Vasut #ifdef CONFIG_NS87308 1219b8fa0bSMarek Vasut #include <ns87308.h> 1319b8fa0bSMarek Vasut #endif 1419b8fa0bSMarek Vasut 1519b8fa0bSMarek Vasut #include <serial.h> 1619b8fa0bSMarek Vasut 1748cbc3a8SScott Wood #ifndef CONFIG_NS16550_MIN_FUNCTIONS 1848cbc3a8SScott Wood 1919b8fa0bSMarek Vasut DECLARE_GLOBAL_DATA_PTR; 2019b8fa0bSMarek Vasut 2119b8fa0bSMarek Vasut #if !defined(CONFIG_CONS_INDEX) 2296708a06SAndrew Bradford #elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 6) 2319b8fa0bSMarek Vasut #error "Invalid console index value." 2419b8fa0bSMarek Vasut #endif 2519b8fa0bSMarek Vasut 2619b8fa0bSMarek Vasut #if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1) 2719b8fa0bSMarek Vasut #error "Console port 1 defined but not configured." 2819b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2) 2919b8fa0bSMarek Vasut #error "Console port 2 defined but not configured." 3019b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3) 3119b8fa0bSMarek Vasut #error "Console port 3 defined but not configured." 3219b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4) 3319b8fa0bSMarek Vasut #error "Console port 4 defined but not configured." 3496708a06SAndrew Bradford #elif CONFIG_CONS_INDEX == 5 && !defined(CONFIG_SYS_NS16550_COM5) 3596708a06SAndrew Bradford #error "Console port 5 defined but not configured." 3696708a06SAndrew Bradford #elif CONFIG_CONS_INDEX == 6 && !defined(CONFIG_SYS_NS16550_COM6) 3796708a06SAndrew Bradford #error "Console port 6 defined but not configured." 3819b8fa0bSMarek Vasut #endif 3919b8fa0bSMarek Vasut 4019b8fa0bSMarek Vasut /* Note: The port number specified in the functions is 1 based. 4119b8fa0bSMarek Vasut * the array is 0 based. 4219b8fa0bSMarek Vasut */ 4396708a06SAndrew Bradford static NS16550_t serial_ports[6] = { 4419b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM1 4519b8fa0bSMarek Vasut (NS16550_t)CONFIG_SYS_NS16550_COM1, 4619b8fa0bSMarek Vasut #else 4719b8fa0bSMarek Vasut NULL, 4819b8fa0bSMarek Vasut #endif 4919b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM2 5019b8fa0bSMarek Vasut (NS16550_t)CONFIG_SYS_NS16550_COM2, 5119b8fa0bSMarek Vasut #else 5219b8fa0bSMarek Vasut NULL, 5319b8fa0bSMarek Vasut #endif 5419b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM3 5519b8fa0bSMarek Vasut (NS16550_t)CONFIG_SYS_NS16550_COM3, 5619b8fa0bSMarek Vasut #else 5719b8fa0bSMarek Vasut NULL, 5819b8fa0bSMarek Vasut #endif 5919b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM4 6096708a06SAndrew Bradford (NS16550_t)CONFIG_SYS_NS16550_COM4, 6196708a06SAndrew Bradford #else 6296708a06SAndrew Bradford NULL, 6396708a06SAndrew Bradford #endif 6496708a06SAndrew Bradford #ifdef CONFIG_SYS_NS16550_COM5 6596708a06SAndrew Bradford (NS16550_t)CONFIG_SYS_NS16550_COM5, 6696708a06SAndrew Bradford #else 6796708a06SAndrew Bradford NULL, 6896708a06SAndrew Bradford #endif 6996708a06SAndrew Bradford #ifdef CONFIG_SYS_NS16550_COM6 7096708a06SAndrew Bradford (NS16550_t)CONFIG_SYS_NS16550_COM6 7119b8fa0bSMarek Vasut #else 7219b8fa0bSMarek Vasut NULL 7319b8fa0bSMarek Vasut #endif 7419b8fa0bSMarek Vasut }; 7519b8fa0bSMarek Vasut 7619b8fa0bSMarek Vasut #define PORT serial_ports[port-1] 7719b8fa0bSMarek Vasut 7819b8fa0bSMarek Vasut /* Multi serial device functions */ 7919b8fa0bSMarek Vasut #define DECLARE_ESERIAL_FUNCTIONS(port) \ 80ac63f2a2SKim Phillips static int eserial##port##_init(void) \ 81ac63f2a2SKim Phillips { \ 8219b8fa0bSMarek Vasut int clock_divisor; \ 83fa54eb12SSimon Glass clock_divisor = ns16550_calc_divisor(serial_ports[port-1], \ 84fa54eb12SSimon Glass CONFIG_SYS_NS16550_CLK, gd->baudrate); \ 8519b8fa0bSMarek Vasut NS16550_init(serial_ports[port-1], clock_divisor); \ 86ac63f2a2SKim Phillips return 0 ; \ 87ac63f2a2SKim Phillips } \ 88ac63f2a2SKim Phillips static void eserial##port##_setbrg(void) \ 89ac63f2a2SKim Phillips { \ 90ac63f2a2SKim Phillips serial_setbrg_dev(port); \ 91ac63f2a2SKim Phillips } \ 92ac63f2a2SKim Phillips static int eserial##port##_getc(void) \ 93ac63f2a2SKim Phillips { \ 94ac63f2a2SKim Phillips return serial_getc_dev(port); \ 95ac63f2a2SKim Phillips } \ 96ac63f2a2SKim Phillips static int eserial##port##_tstc(void) \ 97ac63f2a2SKim Phillips { \ 98ac63f2a2SKim Phillips return serial_tstc_dev(port); \ 99ac63f2a2SKim Phillips } \ 100ac63f2a2SKim Phillips static void eserial##port##_putc(const char c) \ 101ac63f2a2SKim Phillips { \ 102ac63f2a2SKim Phillips serial_putc_dev(port, c); \ 103ac63f2a2SKim Phillips } \ 104ac63f2a2SKim Phillips static void eserial##port##_puts(const char *s) \ 105ac63f2a2SKim Phillips { \ 106ac63f2a2SKim Phillips serial_puts_dev(port, s); \ 107ac63f2a2SKim 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 1213fdd0bb2SMasahiro Yamada static void _serial_putc(const char c, const int port) 12219b8fa0bSMarek Vasut { 12319b8fa0bSMarek Vasut if (c == '\n') 12419b8fa0bSMarek Vasut NS16550_putc(PORT, '\r'); 12519b8fa0bSMarek Vasut 12619b8fa0bSMarek Vasut NS16550_putc(PORT, c); 12719b8fa0bSMarek Vasut } 12819b8fa0bSMarek Vasut 1293fdd0bb2SMasahiro Yamada static void _serial_puts(const char *s, const int port) 13019b8fa0bSMarek Vasut { 13119b8fa0bSMarek Vasut while (*s) { 13219b8fa0bSMarek Vasut _serial_putc(*s++, port); 13319b8fa0bSMarek Vasut } 13419b8fa0bSMarek Vasut } 13519b8fa0bSMarek Vasut 1363fdd0bb2SMasahiro Yamada static int _serial_getc(const int port) 13719b8fa0bSMarek Vasut { 13819b8fa0bSMarek Vasut return NS16550_getc(PORT); 13919b8fa0bSMarek Vasut } 14019b8fa0bSMarek Vasut 1413fdd0bb2SMasahiro Yamada static int _serial_tstc(const int port) 14219b8fa0bSMarek Vasut { 14319b8fa0bSMarek Vasut return NS16550_tstc(PORT); 14419b8fa0bSMarek Vasut } 14519b8fa0bSMarek Vasut 1463fdd0bb2SMasahiro Yamada static void _serial_setbrg(const int port) 14719b8fa0bSMarek Vasut { 14819b8fa0bSMarek Vasut int clock_divisor; 14919b8fa0bSMarek Vasut 150fa54eb12SSimon Glass clock_divisor = ns16550_calc_divisor(PORT, CONFIG_SYS_NS16550_CLK, 151fa54eb12SSimon Glass gd->baudrate); 15219b8fa0bSMarek Vasut NS16550_reinit(PORT, clock_divisor); 15319b8fa0bSMarek Vasut } 15419b8fa0bSMarek Vasut 15519b8fa0bSMarek Vasut static inline void 15619b8fa0bSMarek Vasut serial_putc_dev(unsigned int dev_index,const char c) 15719b8fa0bSMarek Vasut { 15819b8fa0bSMarek Vasut _serial_putc(c,dev_index); 15919b8fa0bSMarek Vasut } 16019b8fa0bSMarek Vasut 16119b8fa0bSMarek Vasut static inline void 16219b8fa0bSMarek Vasut serial_puts_dev(unsigned int dev_index,const char *s) 16319b8fa0bSMarek Vasut { 16419b8fa0bSMarek Vasut _serial_puts(s,dev_index); 16519b8fa0bSMarek Vasut } 16619b8fa0bSMarek Vasut 16719b8fa0bSMarek Vasut static inline int 16819b8fa0bSMarek Vasut serial_getc_dev(unsigned int dev_index) 16919b8fa0bSMarek Vasut { 17019b8fa0bSMarek Vasut return _serial_getc(dev_index); 17119b8fa0bSMarek Vasut } 17219b8fa0bSMarek Vasut 17319b8fa0bSMarek Vasut static inline int 17419b8fa0bSMarek Vasut serial_tstc_dev(unsigned int dev_index) 17519b8fa0bSMarek Vasut { 17619b8fa0bSMarek Vasut return _serial_tstc(dev_index); 17719b8fa0bSMarek Vasut } 17819b8fa0bSMarek Vasut 17919b8fa0bSMarek Vasut static inline void 18019b8fa0bSMarek Vasut serial_setbrg_dev(unsigned int dev_index) 18119b8fa0bSMarek Vasut { 18219b8fa0bSMarek Vasut _serial_setbrg(dev_index); 18319b8fa0bSMarek Vasut } 18419b8fa0bSMarek Vasut 18555db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM1) 18619b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(1); 18719b8fa0bSMarek Vasut struct serial_device eserial1_device = 18819b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(1, "eserial0"); 18955db9ccaSScott Wood #endif 19055db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM2) 19119b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(2); 19219b8fa0bSMarek Vasut struct serial_device eserial2_device = 19319b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(2, "eserial1"); 19455db9ccaSScott Wood #endif 19555db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM3) 19619b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(3); 19719b8fa0bSMarek Vasut struct serial_device eserial3_device = 19819b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(3, "eserial2"); 19955db9ccaSScott Wood #endif 20055db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM4) 20119b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(4); 20219b8fa0bSMarek Vasut struct serial_device eserial4_device = 20319b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(4, "eserial3"); 20455db9ccaSScott Wood #endif 20555db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM5) 20696708a06SAndrew Bradford DECLARE_ESERIAL_FUNCTIONS(5); 20796708a06SAndrew Bradford struct serial_device eserial5_device = 20896708a06SAndrew Bradford INIT_ESERIAL_STRUCTURE(5, "eserial4"); 20955db9ccaSScott Wood #endif 21055db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM6) 21196708a06SAndrew Bradford DECLARE_ESERIAL_FUNCTIONS(6); 21296708a06SAndrew Bradford struct serial_device eserial6_device = 21396708a06SAndrew Bradford INIT_ESERIAL_STRUCTURE(6, "eserial5"); 21455db9ccaSScott Wood #endif 21519b8fa0bSMarek Vasut 21619b8fa0bSMarek Vasut __weak struct serial_device *default_serial_console(void) 21719b8fa0bSMarek Vasut { 21819b8fa0bSMarek Vasut #if CONFIG_CONS_INDEX == 1 21919b8fa0bSMarek Vasut return &eserial1_device; 22019b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 2 22119b8fa0bSMarek Vasut return &eserial2_device; 22219b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 3 22319b8fa0bSMarek Vasut return &eserial3_device; 22419b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 4 22519b8fa0bSMarek Vasut return &eserial4_device; 22696708a06SAndrew Bradford #elif CONFIG_CONS_INDEX == 5 22796708a06SAndrew Bradford return &eserial5_device; 22896708a06SAndrew Bradford #elif CONFIG_CONS_INDEX == 6 22996708a06SAndrew Bradford return &eserial6_device; 23019b8fa0bSMarek Vasut #else 23119b8fa0bSMarek Vasut #error "Bad CONFIG_CONS_INDEX." 23219b8fa0bSMarek Vasut #endif 23319b8fa0bSMarek Vasut } 23419b8fa0bSMarek Vasut 23519b8fa0bSMarek Vasut void ns16550_serial_initialize(void) 23619b8fa0bSMarek Vasut { 23719b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM1) 23819b8fa0bSMarek Vasut serial_register(&eserial1_device); 23919b8fa0bSMarek Vasut #endif 24019b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM2) 24119b8fa0bSMarek Vasut serial_register(&eserial2_device); 24219b8fa0bSMarek Vasut #endif 24319b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM3) 24419b8fa0bSMarek Vasut serial_register(&eserial3_device); 24519b8fa0bSMarek Vasut #endif 24619b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM4) 24719b8fa0bSMarek Vasut serial_register(&eserial4_device); 24819b8fa0bSMarek Vasut #endif 24996708a06SAndrew Bradford #if defined(CONFIG_SYS_NS16550_COM5) 25096708a06SAndrew Bradford serial_register(&eserial5_device); 25196708a06SAndrew Bradford #endif 25296708a06SAndrew Bradford #if defined(CONFIG_SYS_NS16550_COM6) 25396708a06SAndrew Bradford serial_register(&eserial6_device); 25496708a06SAndrew Bradford #endif 25519b8fa0bSMarek Vasut } 25648cbc3a8SScott Wood 25748cbc3a8SScott Wood #endif /* !CONFIG_NS16550_MIN_FUNCTIONS */ 258