uboot/drivers/serial/serial.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000
   3 * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25
  26#include <ns16550.h>
  27#ifdef CONFIG_NS87308
  28#include <ns87308.h>
  29#endif
  30
  31#if defined (CONFIG_SERIAL_MULTI)
  32#include <serial.h>
  33#endif
  34
  35DECLARE_GLOBAL_DATA_PTR;
  36
  37#if !defined(CONFIG_CONS_INDEX)
  38#if defined (CONFIG_SERIAL_MULTI)
  39/*   with CONFIG_SERIAL_MULTI we might have no console
  40 *  on these devices
  41 */
  42#else
  43#error  "No console index specified."
  44#endif /* CONFIG_SERIAL_MULTI */
  45#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 4)
  46#error  "Invalid console index value."
  47#endif
  48
  49#if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1)
  50#error  "Console port 1 defined but not configured."
  51#elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2)
  52#error  "Console port 2 defined but not configured."
  53#elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3)
  54#error  "Console port 3 defined but not configured."
  55#elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4)
  56#error  "Console port 4 defined but not configured."
  57#endif
  58
  59/* Note: The port number specified in the functions is 1 based.
  60 *       the array is 0 based.
  61 */
  62static NS16550_t serial_ports[4] = {
  63#ifdef CONFIG_SYS_NS16550_COM1
  64        (NS16550_t)CONFIG_SYS_NS16550_COM1,
  65#else
  66        NULL,
  67#endif
  68#ifdef CONFIG_SYS_NS16550_COM2
  69        (NS16550_t)CONFIG_SYS_NS16550_COM2,
  70#else
  71        NULL,
  72#endif
  73#ifdef CONFIG_SYS_NS16550_COM3
  74        (NS16550_t)CONFIG_SYS_NS16550_COM3,
  75#else
  76        NULL,
  77#endif
  78#ifdef CONFIG_SYS_NS16550_COM4
  79        (NS16550_t)CONFIG_SYS_NS16550_COM4
  80#else
  81        NULL
  82#endif
  83};
  84
  85#define PORT    serial_ports[port-1]
  86#if defined(CONFIG_CONS_INDEX)
  87#define CONSOLE (serial_ports[CONFIG_CONS_INDEX-1])
  88#endif
  89
  90#if defined(CONFIG_SERIAL_MULTI)
  91
  92/* Multi serial device functions */
  93#define DECLARE_ESERIAL_FUNCTIONS(port) \
  94    int  eserial##port##_init (void) {\
  95        int clock_divisor; \
  96        clock_divisor = calc_divisor(serial_ports[port-1]); \
  97        NS16550_init(serial_ports[port-1], clock_divisor); \
  98        return(0);}\
  99    void eserial##port##_setbrg (void) {\
 100        serial_setbrg_dev(port);}\
 101    int  eserial##port##_getc (void) {\
 102        return serial_getc_dev(port);}\
 103    int  eserial##port##_tstc (void) {\
 104        return serial_tstc_dev(port);}\
 105    void eserial##port##_putc (const char c) {\
 106        serial_putc_dev(port, c);}\
 107    void eserial##port##_puts (const char *s) {\
 108        serial_puts_dev(port, s);}
 109
 110/* Serial device descriptor */
 111#define INIT_ESERIAL_STRUCTURE(port,name,bus) {\
 112        name,\
 113        bus,\
 114        eserial##port##_init,\
 115        eserial##port##_setbrg,\
 116        eserial##port##_getc,\
 117        eserial##port##_tstc,\
 118        eserial##port##_putc,\
 119        eserial##port##_puts, }
 120
 121#endif /* CONFIG_SERIAL_MULTI */
 122
 123static int calc_divisor (NS16550_t port)
 124{
 125#ifdef CONFIG_OMAP1510
 126        /* If can't cleanly clock 115200 set div to 1 */
 127        if ((CONFIG_SYS_NS16550_CLK == 12000000) && (gd->baudrate == 115200)) {
 128                port->osc_12m_sel = OSC_12M_SEL;        /* enable 6.5 * divisor */
 129                return (1);                             /* return 1 for base divisor */
 130        }
 131        port->osc_12m_sel = 0;                  /* clear if previsouly set */
 132#endif
 133#ifdef CONFIG_OMAP1610
 134        /* If can't cleanly clock 115200 set div to 1 */
 135        if ((CONFIG_SYS_NS16550_CLK == 48000000) && (gd->baudrate == 115200)) {
 136                return (26);            /* return 26 for base divisor */
 137        }
 138#endif
 139
 140#ifdef CONFIG_APTIX
 141#define MODE_X_DIV 13
 142#else
 143#define MODE_X_DIV 16
 144#endif
 145
 146        /* Compute divisor value. Normally, we should simply return:
 147         *   CONFIG_SYS_NS16550_CLK) / MODE_X_DIV / gd->baudrate
 148         * but we need to round that value by adding 0.5.
 149         * Rounding is especially important at high baud rates.
 150         */
 151        return (CONFIG_SYS_NS16550_CLK + (gd->baudrate * (MODE_X_DIV / 2))) /
 152                (MODE_X_DIV * gd->baudrate);
 153}
 154
 155#if !defined(CONFIG_SERIAL_MULTI)
 156int serial_init (void)
 157{
 158        int clock_divisor;
 159
 160#ifdef CONFIG_NS87308
 161        initialise_ns87308();
 162#endif
 163
 164#ifdef CONFIG_SYS_NS16550_COM1
 165        clock_divisor = calc_divisor(serial_ports[0]);
 166        NS16550_init(serial_ports[0], clock_divisor);
 167#endif
 168#ifdef CONFIG_SYS_NS16550_COM2
 169        clock_divisor = calc_divisor(serial_ports[1]);
 170        NS16550_init(serial_ports[1], clock_divisor);
 171#endif
 172#ifdef CONFIG_SYS_NS16550_COM3
 173        clock_divisor = calc_divisor(serial_ports[2]);
 174        NS16550_init(serial_ports[2], clock_divisor);
 175#endif
 176#ifdef CONFIG_SYS_NS16550_COM4
 177        clock_divisor = calc_divisor(serial_ports[3]);
 178        NS16550_init(serial_ports[3], clock_divisor);
 179#endif
 180
 181        return (0);
 182}
 183#endif
 184
 185void
 186_serial_putc(const char c,const int port)
 187{
 188        if (c == '\n')
 189                NS16550_putc(PORT, '\r');
 190
 191        NS16550_putc(PORT, c);
 192}
 193
 194void
 195_serial_putc_raw(const char c,const int port)
 196{
 197        NS16550_putc(PORT, c);
 198}
 199
 200void
 201_serial_puts (const char *s,const int port)
 202{
 203        while (*s) {
 204                _serial_putc (*s++,port);
 205        }
 206}
 207
 208
 209int
 210_serial_getc(const int port)
 211{
 212        return NS16550_getc(PORT);
 213}
 214
 215int
 216_serial_tstc(const int port)
 217{
 218        return NS16550_tstc(PORT);
 219}
 220
 221void
 222_serial_setbrg (const int port)
 223{
 224        int clock_divisor;
 225
 226        clock_divisor = calc_divisor(PORT);
 227        NS16550_reinit(PORT, clock_divisor);
 228}
 229
 230#if defined(CONFIG_SERIAL_MULTI)
 231static inline void
 232serial_putc_dev(unsigned int dev_index,const char c)
 233{
 234        _serial_putc(c,dev_index);
 235}
 236#else
 237void
 238serial_putc(const char c)
 239{
 240        _serial_putc(c,CONFIG_CONS_INDEX);
 241}
 242#endif
 243
 244#if defined(CONFIG_SERIAL_MULTI)
 245static inline void
 246serial_putc_raw_dev(unsigned int dev_index,const char c)
 247{
 248        _serial_putc_raw(c,dev_index);
 249}
 250#else
 251void
 252serial_putc_raw(const char c)
 253{
 254        _serial_putc_raw(c,CONFIG_CONS_INDEX);
 255}
 256#endif
 257
 258#if defined(CONFIG_SERIAL_MULTI)
 259static inline void
 260serial_puts_dev(unsigned int dev_index,const char *s)
 261{
 262        _serial_puts(s,dev_index);
 263}
 264#else
 265void
 266serial_puts(const char *s)
 267{
 268        _serial_puts(s,CONFIG_CONS_INDEX);
 269}
 270#endif
 271
 272#if defined(CONFIG_SERIAL_MULTI)
 273static inline int
 274serial_getc_dev(unsigned int dev_index)
 275{
 276        return _serial_getc(dev_index);
 277}
 278#else
 279int
 280serial_getc(void)
 281{
 282        return _serial_getc(CONFIG_CONS_INDEX);
 283}
 284#endif
 285
 286#if defined(CONFIG_SERIAL_MULTI)
 287static inline int
 288serial_tstc_dev(unsigned int dev_index)
 289{
 290        return _serial_tstc(dev_index);
 291}
 292#else
 293int
 294serial_tstc(void)
 295{
 296        return _serial_tstc(CONFIG_CONS_INDEX);
 297}
 298#endif
 299
 300#if defined(CONFIG_SERIAL_MULTI)
 301static inline void
 302serial_setbrg_dev(unsigned int dev_index)
 303{
 304        _serial_setbrg(dev_index);
 305}
 306#else
 307void
 308serial_setbrg(void)
 309{
 310        _serial_setbrg(CONFIG_CONS_INDEX);
 311}
 312#endif
 313
 314#if defined(CONFIG_SERIAL_MULTI)
 315
 316DECLARE_ESERIAL_FUNCTIONS(1);
 317struct serial_device eserial1_device =
 318        INIT_ESERIAL_STRUCTURE(1,"eserial0","EUART1");
 319DECLARE_ESERIAL_FUNCTIONS(2);
 320struct serial_device eserial2_device =
 321        INIT_ESERIAL_STRUCTURE(2,"eserial1","EUART2");
 322DECLARE_ESERIAL_FUNCTIONS(3);
 323struct serial_device eserial3_device =
 324        INIT_ESERIAL_STRUCTURE(3,"eserial2","EUART3");
 325DECLARE_ESERIAL_FUNCTIONS(4);
 326struct serial_device eserial4_device =
 327        INIT_ESERIAL_STRUCTURE(4,"eserial3","EUART4");
 328#endif /* CONFIG_SERIAL_MULTI */
 329