uboot/drivers/serial/serial_ns16550.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2000
   4 * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
   5 */
   6
   7#include <common.h>
   8#include <clock_legacy.h>
   9#include <ns16550.h>
  10#include <serial.h>
  11#include <asm/global_data.h>
  12#include <linux/compiler.h>
  13
  14#ifndef CONFIG_NS16550_MIN_FUNCTIONS
  15
  16DECLARE_GLOBAL_DATA_PTR;
  17
  18#if !defined(CONFIG_CONS_INDEX)
  19#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 6)
  20#error  "Invalid console index value."
  21#endif
  22
  23#if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1)
  24#error  "Console port 1 defined but not configured."
  25#elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2)
  26#error  "Console port 2 defined but not configured."
  27#elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3)
  28#error  "Console port 3 defined but not configured."
  29#elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4)
  30#error  "Console port 4 defined but not configured."
  31#elif CONFIG_CONS_INDEX == 5 && !defined(CONFIG_SYS_NS16550_COM5)
  32#error  "Console port 5 defined but not configured."
  33#elif CONFIG_CONS_INDEX == 6 && !defined(CONFIG_SYS_NS16550_COM6)
  34#error  "Console port 6 defined but not configured."
  35#endif
  36
  37/* Note: The port number specified in the functions is 1 based.
  38 *       the array is 0 based.
  39 */
  40static struct ns16550 *serial_ports[6] = {
  41#ifdef CONFIG_SYS_NS16550_COM1
  42        (struct ns16550 *)CONFIG_SYS_NS16550_COM1,
  43#else
  44        NULL,
  45#endif
  46#ifdef CONFIG_SYS_NS16550_COM2
  47        (struct ns16550 *)CONFIG_SYS_NS16550_COM2,
  48#else
  49        NULL,
  50#endif
  51#ifdef CONFIG_SYS_NS16550_COM3
  52        (struct ns16550 *)CONFIG_SYS_NS16550_COM3,
  53#else
  54        NULL,
  55#endif
  56#ifdef CONFIG_SYS_NS16550_COM4
  57        (struct ns16550 *)CONFIG_SYS_NS16550_COM4,
  58#else
  59        NULL,
  60#endif
  61#ifdef CONFIG_SYS_NS16550_COM5
  62        (struct ns16550 *)CONFIG_SYS_NS16550_COM5,
  63#else
  64        NULL,
  65#endif
  66#ifdef CONFIG_SYS_NS16550_COM6
  67        (struct ns16550 *)CONFIG_SYS_NS16550_COM6
  68#else
  69        NULL
  70#endif
  71};
  72
  73#define PORT    serial_ports[port-1]
  74
  75/* Multi serial device functions */
  76#define DECLARE_ESERIAL_FUNCTIONS(port) \
  77        static int  eserial##port##_init(void) \
  78        { \
  79                int clock_divisor; \
  80                clock_divisor = ns16550_calc_divisor(serial_ports[port-1], \
  81                                CONFIG_SYS_NS16550_CLK, gd->baudrate); \
  82                ns16550_init(serial_ports[port - 1], clock_divisor); \
  83                return 0 ; \
  84        } \
  85        static void eserial##port##_setbrg(void) \
  86        { \
  87                serial_setbrg_dev(port); \
  88        } \
  89        static int  eserial##port##_getc(void) \
  90        { \
  91                return serial_getc_dev(port); \
  92        } \
  93        static int  eserial##port##_tstc(void) \
  94        { \
  95                return serial_tstc_dev(port); \
  96        } \
  97        static void eserial##port##_putc(const char c) \
  98        { \
  99                serial_putc_dev(port, c); \
 100        } \
 101        static void eserial##port##_puts(const char *s) \
 102        { \
 103                serial_puts_dev(port, s); \
 104        }
 105
 106/* Serial device descriptor */
 107#define INIT_ESERIAL_STRUCTURE(port, __name) {  \
 108        .name   = __name,                       \
 109        .start  = eserial##port##_init,         \
 110        .stop   = NULL,                         \
 111        .setbrg = eserial##port##_setbrg,       \
 112        .getc   = eserial##port##_getc,         \
 113        .tstc   = eserial##port##_tstc,         \
 114        .putc   = eserial##port##_putc,         \
 115        .puts   = eserial##port##_puts,         \
 116}
 117
 118static void _serial_putc(const char c, const int port)
 119{
 120        if (c == '\n')
 121                ns16550_putc(PORT, '\r');
 122
 123        ns16550_putc(PORT, c);
 124}
 125
 126static void _serial_puts(const char *s, const int port)
 127{
 128        while (*s) {
 129                _serial_putc(*s++, port);
 130        }
 131}
 132
 133static int _serial_getc(const int port)
 134{
 135        return ns16550_getc(PORT);
 136}
 137
 138static int _serial_tstc(const int port)
 139{
 140        return ns16550_tstc(PORT);
 141}
 142
 143static void _serial_setbrg(const int port)
 144{
 145        int clock_divisor;
 146
 147        clock_divisor = ns16550_calc_divisor(PORT, CONFIG_SYS_NS16550_CLK,
 148                                             gd->baudrate);
 149        ns16550_reinit(PORT, clock_divisor);
 150}
 151
 152static inline void
 153serial_putc_dev(unsigned int dev_index,const char c)
 154{
 155        _serial_putc(c,dev_index);
 156}
 157
 158static inline void
 159serial_puts_dev(unsigned int dev_index,const char *s)
 160{
 161        _serial_puts(s,dev_index);
 162}
 163
 164static inline int
 165serial_getc_dev(unsigned int dev_index)
 166{
 167        return _serial_getc(dev_index);
 168}
 169
 170static inline int
 171serial_tstc_dev(unsigned int dev_index)
 172{
 173        return _serial_tstc(dev_index);
 174}
 175
 176static inline void
 177serial_setbrg_dev(unsigned int dev_index)
 178{
 179        _serial_setbrg(dev_index);
 180}
 181
 182#if defined(CONFIG_SYS_NS16550_COM1)
 183DECLARE_ESERIAL_FUNCTIONS(1);
 184struct serial_device eserial1_device =
 185        INIT_ESERIAL_STRUCTURE(1, "eserial0");
 186#endif
 187#if defined(CONFIG_SYS_NS16550_COM2)
 188DECLARE_ESERIAL_FUNCTIONS(2);
 189struct serial_device eserial2_device =
 190        INIT_ESERIAL_STRUCTURE(2, "eserial1");
 191#endif
 192#if defined(CONFIG_SYS_NS16550_COM3)
 193DECLARE_ESERIAL_FUNCTIONS(3);
 194struct serial_device eserial3_device =
 195        INIT_ESERIAL_STRUCTURE(3, "eserial2");
 196#endif
 197#if defined(CONFIG_SYS_NS16550_COM4)
 198DECLARE_ESERIAL_FUNCTIONS(4);
 199struct serial_device eserial4_device =
 200        INIT_ESERIAL_STRUCTURE(4, "eserial3");
 201#endif
 202#if defined(CONFIG_SYS_NS16550_COM5)
 203DECLARE_ESERIAL_FUNCTIONS(5);
 204struct serial_device eserial5_device =
 205        INIT_ESERIAL_STRUCTURE(5, "eserial4");
 206#endif
 207#if defined(CONFIG_SYS_NS16550_COM6)
 208DECLARE_ESERIAL_FUNCTIONS(6);
 209struct serial_device eserial6_device =
 210        INIT_ESERIAL_STRUCTURE(6, "eserial5");
 211#endif
 212
 213__weak struct serial_device *default_serial_console(void)
 214{
 215#if CONFIG_CONS_INDEX == 1
 216        return &eserial1_device;
 217#elif CONFIG_CONS_INDEX == 2
 218        return &eserial2_device;
 219#elif CONFIG_CONS_INDEX == 3
 220        return &eserial3_device;
 221#elif CONFIG_CONS_INDEX == 4
 222        return &eserial4_device;
 223#elif CONFIG_CONS_INDEX == 5
 224        return &eserial5_device;
 225#elif CONFIG_CONS_INDEX == 6
 226        return &eserial6_device;
 227#else
 228#error "Bad CONFIG_CONS_INDEX."
 229#endif
 230}
 231
 232void ns16550_serial_initialize(void)
 233{
 234#if defined(CONFIG_SYS_NS16550_COM1)
 235        serial_register(&eserial1_device);
 236#endif
 237#if defined(CONFIG_SYS_NS16550_COM2)
 238        serial_register(&eserial2_device);
 239#endif
 240#if defined(CONFIG_SYS_NS16550_COM3)
 241        serial_register(&eserial3_device);
 242#endif
 243#if defined(CONFIG_SYS_NS16550_COM4)
 244        serial_register(&eserial4_device);
 245#endif
 246#if defined(CONFIG_SYS_NS16550_COM5)
 247        serial_register(&eserial5_device);
 248#endif
 249#if defined(CONFIG_SYS_NS16550_COM6)
 250        serial_register(&eserial6_device);
 251#endif
 252}
 253
 254#endif /* !CONFIG_NS16550_MIN_FUNCTIONS */
 255