119b8fa0bSMarek Vasut /* 219b8fa0bSMarek Vasut * (C) Copyright 2000 319b8fa0bSMarek Vasut * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. 419b8fa0bSMarek Vasut * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 619b8fa0bSMarek Vasut */ 719b8fa0bSMarek Vasut 819b8fa0bSMarek Vasut #include <common.h> 919b8fa0bSMarek Vasut #include <linux/compiler.h> 1019b8fa0bSMarek Vasut 1119b8fa0bSMarek Vasut #include <ns16550.h> 1219b8fa0bSMarek Vasut #ifdef CONFIG_NS87308 1319b8fa0bSMarek Vasut #include <ns87308.h> 1419b8fa0bSMarek Vasut #endif 1519b8fa0bSMarek Vasut 1619b8fa0bSMarek Vasut #include <serial.h> 1719b8fa0bSMarek Vasut 1848cbc3a8SScott Wood #ifndef CONFIG_NS16550_MIN_FUNCTIONS 1948cbc3a8SScott Wood 2019b8fa0bSMarek Vasut DECLARE_GLOBAL_DATA_PTR; 2119b8fa0bSMarek Vasut 2219b8fa0bSMarek Vasut #if !defined(CONFIG_CONS_INDEX) 2396708a06SAndrew Bradford #elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 6) 2419b8fa0bSMarek Vasut #error "Invalid console index value." 2519b8fa0bSMarek Vasut #endif 2619b8fa0bSMarek Vasut 2719b8fa0bSMarek Vasut #if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1) 2819b8fa0bSMarek Vasut #error "Console port 1 defined but not configured." 2919b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2) 3019b8fa0bSMarek Vasut #error "Console port 2 defined but not configured." 3119b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3) 3219b8fa0bSMarek Vasut #error "Console port 3 defined but not configured." 3319b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4) 3419b8fa0bSMarek Vasut #error "Console port 4 defined but not configured." 3596708a06SAndrew Bradford #elif CONFIG_CONS_INDEX == 5 && !defined(CONFIG_SYS_NS16550_COM5) 3696708a06SAndrew Bradford #error "Console port 5 defined but not configured." 3796708a06SAndrew Bradford #elif CONFIG_CONS_INDEX == 6 && !defined(CONFIG_SYS_NS16550_COM6) 3896708a06SAndrew Bradford #error "Console port 6 defined but not configured." 3919b8fa0bSMarek Vasut #endif 4019b8fa0bSMarek Vasut 4119b8fa0bSMarek Vasut /* Note: The port number specified in the functions is 1 based. 4219b8fa0bSMarek Vasut * the array is 0 based. 4319b8fa0bSMarek Vasut */ 4496708a06SAndrew Bradford static NS16550_t serial_ports[6] = { 4519b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM1 4619b8fa0bSMarek Vasut (NS16550_t)CONFIG_SYS_NS16550_COM1, 4719b8fa0bSMarek Vasut #else 4819b8fa0bSMarek Vasut NULL, 4919b8fa0bSMarek Vasut #endif 5019b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM2 5119b8fa0bSMarek Vasut (NS16550_t)CONFIG_SYS_NS16550_COM2, 5219b8fa0bSMarek Vasut #else 5319b8fa0bSMarek Vasut NULL, 5419b8fa0bSMarek Vasut #endif 5519b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM3 5619b8fa0bSMarek Vasut (NS16550_t)CONFIG_SYS_NS16550_COM3, 5719b8fa0bSMarek Vasut #else 5819b8fa0bSMarek Vasut NULL, 5919b8fa0bSMarek Vasut #endif 6019b8fa0bSMarek Vasut #ifdef CONFIG_SYS_NS16550_COM4 6196708a06SAndrew Bradford (NS16550_t)CONFIG_SYS_NS16550_COM4, 6296708a06SAndrew Bradford #else 6396708a06SAndrew Bradford NULL, 6496708a06SAndrew Bradford #endif 6596708a06SAndrew Bradford #ifdef CONFIG_SYS_NS16550_COM5 6696708a06SAndrew Bradford (NS16550_t)CONFIG_SYS_NS16550_COM5, 6796708a06SAndrew Bradford #else 6896708a06SAndrew Bradford NULL, 6996708a06SAndrew Bradford #endif 7096708a06SAndrew Bradford #ifdef CONFIG_SYS_NS16550_COM6 7196708a06SAndrew Bradford (NS16550_t)CONFIG_SYS_NS16550_COM6 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) \ 81ac63f2a2SKim Phillips static int eserial##port##_init(void) \ 82ac63f2a2SKim Phillips { \ 8319b8fa0bSMarek Vasut int clock_divisor; \ 84fa54eb12SSimon Glass clock_divisor = ns16550_calc_divisor(serial_ports[port-1], \ 85fa54eb12SSimon Glass CONFIG_SYS_NS16550_CLK, gd->baudrate); \ 8619b8fa0bSMarek Vasut NS16550_init(serial_ports[port-1], clock_divisor); \ 87ac63f2a2SKim Phillips return 0 ; \ 88ac63f2a2SKim Phillips } \ 89ac63f2a2SKim Phillips static void eserial##port##_setbrg(void) \ 90ac63f2a2SKim Phillips { \ 91ac63f2a2SKim Phillips serial_setbrg_dev(port); \ 92ac63f2a2SKim Phillips } \ 93ac63f2a2SKim Phillips static int eserial##port##_getc(void) \ 94ac63f2a2SKim Phillips { \ 95ac63f2a2SKim Phillips return serial_getc_dev(port); \ 96ac63f2a2SKim Phillips } \ 97ac63f2a2SKim Phillips static int eserial##port##_tstc(void) \ 98ac63f2a2SKim Phillips { \ 99ac63f2a2SKim Phillips return serial_tstc_dev(port); \ 100ac63f2a2SKim Phillips } \ 101ac63f2a2SKim Phillips static void eserial##port##_putc(const char c) \ 102ac63f2a2SKim Phillips { \ 103ac63f2a2SKim Phillips serial_putc_dev(port, c); \ 104ac63f2a2SKim Phillips } \ 105ac63f2a2SKim Phillips static void eserial##port##_puts(const char *s) \ 106ac63f2a2SKim Phillips { \ 107ac63f2a2SKim Phillips serial_puts_dev(port, s); \ 108ac63f2a2SKim Phillips } 10919b8fa0bSMarek Vasut 11019b8fa0bSMarek Vasut /* Serial device descriptor */ 11119b8fa0bSMarek Vasut #define INIT_ESERIAL_STRUCTURE(port, __name) { \ 11219b8fa0bSMarek Vasut .name = __name, \ 11319b8fa0bSMarek Vasut .start = eserial##port##_init, \ 11419b8fa0bSMarek Vasut .stop = NULL, \ 11519b8fa0bSMarek Vasut .setbrg = eserial##port##_setbrg, \ 11619b8fa0bSMarek Vasut .getc = eserial##port##_getc, \ 11719b8fa0bSMarek Vasut .tstc = eserial##port##_tstc, \ 11819b8fa0bSMarek Vasut .putc = eserial##port##_putc, \ 11919b8fa0bSMarek Vasut .puts = eserial##port##_puts, \ 12019b8fa0bSMarek Vasut } 12119b8fa0bSMarek Vasut 122*3fdd0bb2SMasahiro Yamada static void _serial_putc(const char c, const int port) 12319b8fa0bSMarek Vasut { 12419b8fa0bSMarek Vasut if (c == '\n') 12519b8fa0bSMarek Vasut NS16550_putc(PORT, '\r'); 12619b8fa0bSMarek Vasut 12719b8fa0bSMarek Vasut NS16550_putc(PORT, c); 12819b8fa0bSMarek Vasut } 12919b8fa0bSMarek Vasut 130*3fdd0bb2SMasahiro Yamada static void _serial_putc_raw(const char c, const int port) 13119b8fa0bSMarek Vasut { 13219b8fa0bSMarek Vasut NS16550_putc(PORT, c); 13319b8fa0bSMarek Vasut } 13419b8fa0bSMarek Vasut 135*3fdd0bb2SMasahiro Yamada static void _serial_puts(const char *s, const int port) 13619b8fa0bSMarek Vasut { 13719b8fa0bSMarek Vasut while (*s) { 13819b8fa0bSMarek Vasut _serial_putc(*s++, port); 13919b8fa0bSMarek Vasut } 14019b8fa0bSMarek Vasut } 14119b8fa0bSMarek Vasut 142*3fdd0bb2SMasahiro Yamada static int _serial_getc(const int port) 14319b8fa0bSMarek Vasut { 14419b8fa0bSMarek Vasut return NS16550_getc(PORT); 14519b8fa0bSMarek Vasut } 14619b8fa0bSMarek Vasut 147*3fdd0bb2SMasahiro Yamada static int _serial_tstc(const int port) 14819b8fa0bSMarek Vasut { 14919b8fa0bSMarek Vasut return NS16550_tstc(PORT); 15019b8fa0bSMarek Vasut } 15119b8fa0bSMarek Vasut 152*3fdd0bb2SMasahiro Yamada static void _serial_setbrg(const int port) 15319b8fa0bSMarek Vasut { 15419b8fa0bSMarek Vasut int clock_divisor; 15519b8fa0bSMarek Vasut 156fa54eb12SSimon Glass clock_divisor = ns16550_calc_divisor(PORT, CONFIG_SYS_NS16550_CLK, 157fa54eb12SSimon Glass gd->baudrate); 15819b8fa0bSMarek Vasut NS16550_reinit(PORT, clock_divisor); 15919b8fa0bSMarek Vasut } 16019b8fa0bSMarek Vasut 16119b8fa0bSMarek Vasut static inline void 16219b8fa0bSMarek Vasut serial_putc_dev(unsigned int dev_index,const char c) 16319b8fa0bSMarek Vasut { 16419b8fa0bSMarek Vasut _serial_putc(c,dev_index); 16519b8fa0bSMarek Vasut } 16619b8fa0bSMarek Vasut 16719b8fa0bSMarek Vasut static inline void 16819b8fa0bSMarek Vasut serial_putc_raw_dev(unsigned int dev_index,const char c) 16919b8fa0bSMarek Vasut { 17019b8fa0bSMarek Vasut _serial_putc_raw(c,dev_index); 17119b8fa0bSMarek Vasut } 17219b8fa0bSMarek Vasut 17319b8fa0bSMarek Vasut static inline void 17419b8fa0bSMarek Vasut serial_puts_dev(unsigned int dev_index,const char *s) 17519b8fa0bSMarek Vasut { 17619b8fa0bSMarek Vasut _serial_puts(s,dev_index); 17719b8fa0bSMarek Vasut } 17819b8fa0bSMarek Vasut 17919b8fa0bSMarek Vasut static inline int 18019b8fa0bSMarek Vasut serial_getc_dev(unsigned int dev_index) 18119b8fa0bSMarek Vasut { 18219b8fa0bSMarek Vasut return _serial_getc(dev_index); 18319b8fa0bSMarek Vasut } 18419b8fa0bSMarek Vasut 18519b8fa0bSMarek Vasut static inline int 18619b8fa0bSMarek Vasut serial_tstc_dev(unsigned int dev_index) 18719b8fa0bSMarek Vasut { 18819b8fa0bSMarek Vasut return _serial_tstc(dev_index); 18919b8fa0bSMarek Vasut } 19019b8fa0bSMarek Vasut 19119b8fa0bSMarek Vasut static inline void 19219b8fa0bSMarek Vasut serial_setbrg_dev(unsigned int dev_index) 19319b8fa0bSMarek Vasut { 19419b8fa0bSMarek Vasut _serial_setbrg(dev_index); 19519b8fa0bSMarek Vasut } 19619b8fa0bSMarek Vasut 19755db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM1) 19819b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(1); 19919b8fa0bSMarek Vasut struct serial_device eserial1_device = 20019b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(1, "eserial0"); 20155db9ccaSScott Wood #endif 20255db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM2) 20319b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(2); 20419b8fa0bSMarek Vasut struct serial_device eserial2_device = 20519b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(2, "eserial1"); 20655db9ccaSScott Wood #endif 20755db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM3) 20819b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(3); 20919b8fa0bSMarek Vasut struct serial_device eserial3_device = 21019b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(3, "eserial2"); 21155db9ccaSScott Wood #endif 21255db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM4) 21319b8fa0bSMarek Vasut DECLARE_ESERIAL_FUNCTIONS(4); 21419b8fa0bSMarek Vasut struct serial_device eserial4_device = 21519b8fa0bSMarek Vasut INIT_ESERIAL_STRUCTURE(4, "eserial3"); 21655db9ccaSScott Wood #endif 21755db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM5) 21896708a06SAndrew Bradford DECLARE_ESERIAL_FUNCTIONS(5); 21996708a06SAndrew Bradford struct serial_device eserial5_device = 22096708a06SAndrew Bradford INIT_ESERIAL_STRUCTURE(5, "eserial4"); 22155db9ccaSScott Wood #endif 22255db9ccaSScott Wood #if defined(CONFIG_SYS_NS16550_COM6) 22396708a06SAndrew Bradford DECLARE_ESERIAL_FUNCTIONS(6); 22496708a06SAndrew Bradford struct serial_device eserial6_device = 22596708a06SAndrew Bradford INIT_ESERIAL_STRUCTURE(6, "eserial5"); 22655db9ccaSScott Wood #endif 22719b8fa0bSMarek Vasut 22819b8fa0bSMarek Vasut __weak struct serial_device *default_serial_console(void) 22919b8fa0bSMarek Vasut { 23019b8fa0bSMarek Vasut #if CONFIG_CONS_INDEX == 1 23119b8fa0bSMarek Vasut return &eserial1_device; 23219b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 2 23319b8fa0bSMarek Vasut return &eserial2_device; 23419b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 3 23519b8fa0bSMarek Vasut return &eserial3_device; 23619b8fa0bSMarek Vasut #elif CONFIG_CONS_INDEX == 4 23719b8fa0bSMarek Vasut return &eserial4_device; 23896708a06SAndrew Bradford #elif CONFIG_CONS_INDEX == 5 23996708a06SAndrew Bradford return &eserial5_device; 24096708a06SAndrew Bradford #elif CONFIG_CONS_INDEX == 6 24196708a06SAndrew Bradford return &eserial6_device; 24219b8fa0bSMarek Vasut #else 24319b8fa0bSMarek Vasut #error "Bad CONFIG_CONS_INDEX." 24419b8fa0bSMarek Vasut #endif 24519b8fa0bSMarek Vasut } 24619b8fa0bSMarek Vasut 24719b8fa0bSMarek Vasut void ns16550_serial_initialize(void) 24819b8fa0bSMarek Vasut { 24919b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM1) 25019b8fa0bSMarek Vasut serial_register(&eserial1_device); 25119b8fa0bSMarek Vasut #endif 25219b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM2) 25319b8fa0bSMarek Vasut serial_register(&eserial2_device); 25419b8fa0bSMarek Vasut #endif 25519b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM3) 25619b8fa0bSMarek Vasut serial_register(&eserial3_device); 25719b8fa0bSMarek Vasut #endif 25819b8fa0bSMarek Vasut #if defined(CONFIG_SYS_NS16550_COM4) 25919b8fa0bSMarek Vasut serial_register(&eserial4_device); 26019b8fa0bSMarek Vasut #endif 26196708a06SAndrew Bradford #if defined(CONFIG_SYS_NS16550_COM5) 26296708a06SAndrew Bradford serial_register(&eserial5_device); 26396708a06SAndrew Bradford #endif 26496708a06SAndrew Bradford #if defined(CONFIG_SYS_NS16550_COM6) 26596708a06SAndrew Bradford serial_register(&eserial6_device); 26696708a06SAndrew Bradford #endif 26719b8fa0bSMarek Vasut } 26848cbc3a8SScott Wood 26948cbc3a8SScott Wood #endif /* !CONFIG_NS16550_MIN_FUNCTIONS */ 270