uboot/arch/powerpc/cpu/mpc5xxx/serial.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000 - 2003
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   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 * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
  24 * changes based on the file arch/powerpc/mbxboot/m8260_tty.c from the
  25 * Linux/PPC sources (m8260_tty.c had no copyright info in it).
  26 *
  27 * Martin Krause, 8 Jun 2006
  28 * Added SERIAL_MULTI support
  29 */
  30
  31/*
  32 * Minimal serial functions needed to use one of the PSC ports
  33 * as serial console interface.
  34 */
  35
  36#include <common.h>
  37#include <linux/compiler.h>
  38#include <mpc5xxx.h>
  39#include <serial.h>
  40
  41DECLARE_GLOBAL_DATA_PTR;
  42
  43#if defined(CONFIG_PSC_CONSOLE)
  44
  45#if CONFIG_PSC_CONSOLE == 1
  46#define PSC_BASE MPC5XXX_PSC1
  47#elif CONFIG_PSC_CONSOLE == 2
  48#define PSC_BASE MPC5XXX_PSC2
  49#elif CONFIG_PSC_CONSOLE == 3
  50#define PSC_BASE MPC5XXX_PSC3
  51#elif CONFIG_PSC_CONSOLE == 4
  52#define PSC_BASE MPC5XXX_PSC4
  53#elif CONFIG_PSC_CONSOLE == 5
  54#define PSC_BASE MPC5XXX_PSC5
  55#elif CONFIG_PSC_CONSOLE == 6
  56#define PSC_BASE MPC5XXX_PSC6
  57#else
  58#error CONFIG_PSC_CONSOLE must be in 1 ... 6
  59#endif
  60
  61#if defined(CONFIG_PSC_CONSOLE2)
  62
  63#if CONFIG_PSC_CONSOLE2 == 1
  64#define PSC_BASE2 MPC5XXX_PSC1
  65#elif CONFIG_PSC_CONSOLE2 == 2
  66#define PSC_BASE2 MPC5XXX_PSC2
  67#elif CONFIG_PSC_CONSOLE2 == 3
  68#define PSC_BASE2 MPC5XXX_PSC3
  69#elif CONFIG_PSC_CONSOLE2 == 4
  70#define PSC_BASE2 MPC5XXX_PSC4
  71#elif CONFIG_PSC_CONSOLE2 == 5
  72#define PSC_BASE2 MPC5XXX_PSC5
  73#elif CONFIG_PSC_CONSOLE2 == 6
  74#define PSC_BASE2 MPC5XXX_PSC6
  75#else
  76#error CONFIG_PSC_CONSOLE2 must be in 1 ... 6
  77#endif
  78
  79#endif
  80
  81int serial_init_dev (unsigned long dev_base)
  82{
  83        volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
  84        unsigned long baseclk;
  85        int div;
  86
  87        /* reset PSC */
  88        psc->command = PSC_SEL_MODE_REG_1;
  89
  90        /* select clock sources */
  91        psc->psc_clock_select = 0;
  92        baseclk = (gd->arch.ipb_clk + 16) / 32;
  93
  94        /* switch to UART mode */
  95        psc->sicr = 0;
  96
  97        /* configure parity, bit length and so on */
  98        psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
  99        psc->mode = PSC_MODE_ONE_STOP;
 100
 101        /* set up UART divisor */
 102        div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
 103        psc->ctur = (div >> 8) & 0xff;
 104        psc->ctlr = div & 0xff;
 105
 106        /* disable all interrupts */
 107        psc->psc_imr = 0;
 108
 109        /* reset and enable Rx/Tx */
 110        psc->command = PSC_RST_RX;
 111        psc->command = PSC_RST_TX;
 112        psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
 113
 114        return (0);
 115}
 116
 117void serial_putc_dev (unsigned long dev_base, const char c)
 118{
 119        volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
 120
 121        if (c == '\n')
 122                serial_putc_dev (dev_base, '\r');
 123
 124        /* Wait for last character to go. */
 125        while (!(psc->psc_status & PSC_SR_TXEMP))
 126                ;
 127
 128        psc->psc_buffer_8 = c;
 129}
 130
 131void serial_putc_raw_dev(unsigned long dev_base, const char c)
 132{
 133        volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
 134        /* Wait for last character to go. */
 135        while (!(psc->psc_status & PSC_SR_TXEMP))
 136                ;
 137
 138        psc->psc_buffer_8 = c;
 139}
 140
 141
 142void serial_puts_dev (unsigned long dev_base, const char *s)
 143{
 144        while (*s) {
 145                serial_putc_dev (dev_base, *s++);
 146        }
 147}
 148
 149int serial_getc_dev (unsigned long dev_base)
 150{
 151        volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
 152
 153        /* Wait for a character to arrive. */
 154        while (!(psc->psc_status & PSC_SR_RXRDY))
 155                ;
 156
 157        return psc->psc_buffer_8;
 158}
 159
 160int serial_tstc_dev (unsigned long dev_base)
 161{
 162        volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
 163
 164        return (psc->psc_status & PSC_SR_RXRDY);
 165}
 166
 167void serial_setbrg_dev (unsigned long dev_base)
 168{
 169        volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
 170        unsigned long baseclk, div;
 171
 172        baseclk = (gd->arch.ipb_clk + 16) / 32;
 173
 174        /* set up UART divisor */
 175        div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
 176        psc->ctur = (div >> 8) & 0xFF;
 177        psc->ctlr =  div & 0xff;
 178}
 179
 180void serial_setrts_dev (unsigned long dev_base, int s)
 181{
 182        volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
 183
 184        if (s) {
 185                /* Assert RTS (become LOW) */
 186                psc->op1 = 0x1;
 187        }
 188        else {
 189                /* Negate RTS (become HIGH) */
 190                psc->op0 = 0x1;
 191        }
 192}
 193
 194int serial_getcts_dev (unsigned long dev_base)
 195{
 196        volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
 197
 198        return (psc->ip & 0x1) ? 0 : 1;
 199}
 200
 201int serial0_init(void)
 202{
 203        return (serial_init_dev(PSC_BASE));
 204}
 205
 206void serial0_setbrg (void)
 207{
 208        serial_setbrg_dev(PSC_BASE);
 209}
 210
 211void serial0_putc(const char c)
 212{
 213        serial_putc_dev(PSC_BASE,c);
 214}
 215
 216void serial0_puts(const char *s)
 217{
 218        serial_puts_dev(PSC_BASE, s);
 219}
 220
 221int serial0_getc(void)
 222{
 223        return(serial_getc_dev(PSC_BASE));
 224}
 225
 226int serial0_tstc(void)
 227{
 228        return (serial_tstc_dev(PSC_BASE));
 229}
 230
 231struct serial_device serial0_device =
 232{
 233        .name   = "serial0",
 234        .start  = serial0_init,
 235        .stop   = NULL,
 236        .setbrg = serial0_setbrg,
 237        .getc   = serial0_getc,
 238        .tstc   = serial0_tstc,
 239        .putc   = serial0_putc,
 240        .puts   = serial0_puts,
 241};
 242
 243__weak struct serial_device *default_serial_console(void)
 244{
 245        return &serial0_device;
 246}
 247
 248#ifdef CONFIG_PSC_CONSOLE2
 249int serial1_init(void)
 250{
 251        return serial_init_dev(PSC_BASE2);
 252}
 253
 254void serial1_setbrg(void)
 255{
 256        serial_setbrg_dev(PSC_BASE2);
 257}
 258
 259void serial1_putc(const char c)
 260{
 261        serial_putc_dev(PSC_BASE2, c);
 262}
 263
 264void serial1_puts(const char *s)
 265{
 266        serial_puts_dev(PSC_BASE2, s);
 267}
 268
 269int serial1_getc(void)
 270{
 271        return serial_getc_dev(PSC_BASE2);
 272}
 273
 274int serial1_tstc(void)
 275{
 276        return serial_tstc_dev(PSC_BASE2);
 277}
 278
 279struct serial_device serial1_device =
 280{
 281        .name   = "serial1",
 282        .start  = serial1_init,
 283        .stop   = NULL,
 284        .setbrg = serial1_setbrg,
 285        .getc   = serial1_getc,
 286        .tstc   = serial1_tstc,
 287        .putc   = serial1_putc,
 288        .puts   = serial1_puts,
 289};
 290#endif /* CONFIG_PSC_CONSOLE2 */
 291
 292#endif /* CONFIG_PSC_CONSOLE */
 293