uboot/arch/powerpc/cpu/mpc512x/serial.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000 - 2010
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 *
   7 * Based ont the MPC5200 PSC driver.
   8 * Adapted for MPC512x by Jan Wrobel <wrr@semihalf.com>
   9 */
  10
  11/*
  12 * Minimal serial functions needed to use one of the PSC ports
  13 * as serial console interface.
  14 */
  15
  16#include <common.h>
  17#include <linux/compiler.h>
  18#include <asm/io.h>
  19#include <asm/processor.h>
  20#include <serial.h>
  21
  22DECLARE_GLOBAL_DATA_PTR;
  23
  24#if defined(CONFIG_PSC_CONSOLE)
  25
  26static void fifo_init (volatile psc512x_t *psc)
  27{
  28        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
  29        u32 tfsize, rfsize;
  30
  31        /* reset Rx & Tx fifo slice */
  32        out_be32(&psc->rfcmd, PSC_FIFO_RESET_SLICE);
  33        out_be32(&psc->tfcmd, PSC_FIFO_RESET_SLICE);
  34
  35        /* disable Tx & Rx FIFO interrupts */
  36        out_be32(&psc->rfintmask, 0);
  37        out_be32(&psc->tfintmask, 0);
  38
  39        switch (((u32)psc & 0xf00) >> 8) {
  40        case 0:
  41                tfsize = FIFOC_PSC0_TX_SIZE | (FIFOC_PSC0_TX_ADDR << 16);
  42                rfsize = FIFOC_PSC0_RX_SIZE | (FIFOC_PSC0_RX_ADDR << 16);
  43                break;
  44        case 1:
  45                tfsize = FIFOC_PSC1_TX_SIZE | (FIFOC_PSC1_TX_ADDR << 16);
  46                rfsize = FIFOC_PSC1_RX_SIZE | (FIFOC_PSC1_RX_ADDR << 16);
  47                break;
  48        case 2:
  49                tfsize = FIFOC_PSC2_TX_SIZE | (FIFOC_PSC2_TX_ADDR << 16);
  50                rfsize = FIFOC_PSC2_RX_SIZE | (FIFOC_PSC2_RX_ADDR << 16);
  51                break;
  52        case 3:
  53                tfsize = FIFOC_PSC3_TX_SIZE | (FIFOC_PSC3_TX_ADDR << 16);
  54                rfsize = FIFOC_PSC3_RX_SIZE | (FIFOC_PSC3_RX_ADDR << 16);
  55                break;
  56        case 4:
  57                tfsize = FIFOC_PSC4_TX_SIZE | (FIFOC_PSC4_TX_ADDR << 16);
  58                rfsize = FIFOC_PSC4_RX_SIZE | (FIFOC_PSC4_RX_ADDR << 16);
  59                break;
  60        case 5:
  61                tfsize = FIFOC_PSC5_TX_SIZE | (FIFOC_PSC5_TX_ADDR << 16);
  62                rfsize = FIFOC_PSC5_RX_SIZE | (FIFOC_PSC5_RX_ADDR << 16);
  63                break;
  64        case 6:
  65                tfsize = FIFOC_PSC6_TX_SIZE | (FIFOC_PSC6_TX_ADDR << 16);
  66                rfsize = FIFOC_PSC6_RX_SIZE | (FIFOC_PSC6_RX_ADDR << 16);
  67                break;
  68        case 7:
  69                tfsize = FIFOC_PSC7_TX_SIZE | (FIFOC_PSC7_TX_ADDR << 16);
  70                rfsize = FIFOC_PSC7_RX_SIZE | (FIFOC_PSC7_RX_ADDR << 16);
  71                break;
  72        case 8:
  73                tfsize = FIFOC_PSC8_TX_SIZE | (FIFOC_PSC8_TX_ADDR << 16);
  74                rfsize = FIFOC_PSC8_RX_SIZE | (FIFOC_PSC8_RX_ADDR << 16);
  75                break;
  76        case 9:
  77                tfsize = FIFOC_PSC9_TX_SIZE | (FIFOC_PSC9_TX_ADDR << 16);
  78                rfsize = FIFOC_PSC9_RX_SIZE | (FIFOC_PSC9_RX_ADDR << 16);
  79                break;
  80        case 10:
  81                tfsize = FIFOC_PSC10_TX_SIZE | (FIFOC_PSC10_TX_ADDR << 16);
  82                rfsize = FIFOC_PSC10_RX_SIZE | (FIFOC_PSC10_RX_ADDR << 16);
  83                break;
  84        case 11:
  85                tfsize = FIFOC_PSC11_TX_SIZE | (FIFOC_PSC11_TX_ADDR << 16);
  86                rfsize = FIFOC_PSC11_RX_SIZE | (FIFOC_PSC11_RX_ADDR << 16);
  87                break;
  88        default:
  89                return;
  90        }
  91
  92        out_be32(&psc->tfsize, tfsize);
  93        out_be32(&psc->rfsize, rfsize);
  94
  95        /* enable Tx & Rx FIFO slice */
  96        out_be32(&psc->rfcmd, PSC_FIFO_ENABLE_SLICE);
  97        out_be32(&psc->tfcmd, PSC_FIFO_ENABLE_SLICE);
  98
  99        out_be32(&im->fifoc.fifoc_cmd, FIFOC_DISABLE_CLOCK_GATE);
 100        __asm__ volatile ("sync");
 101}
 102
 103void serial_setbrg_dev(unsigned int idx)
 104{
 105        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 106        volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
 107        unsigned long baseclk, div;
 108        unsigned long baudrate;
 109        char buf[16];
 110        char *br_env;
 111
 112        baudrate = gd->baudrate;
 113        if (idx != CONFIG_PSC_CONSOLE) {
 114                /* Allows setting baudrate for other serial devices
 115                 * on PSCx using environment. If not specified, use
 116                 * the same baudrate as for console.
 117                 */
 118                sprintf(buf, "psc%d_baudrate", idx);
 119                br_env = getenv(buf);
 120                if (br_env)
 121                        baudrate = simple_strtoul(br_env, NULL, 10);
 122
 123                debug("%s: idx %d, baudrate %ld\n", __func__, idx, baudrate);
 124        }
 125
 126        /* calculate divisor for setting PSC CTUR and CTLR registers */
 127        baseclk = (gd->arch.ips_clk + 8) / 16;
 128        div = (baseclk + (baudrate / 2)) / baudrate;
 129
 130        out_8(&psc->ctur, (div >> 8) & 0xff);
 131        out_8(&psc->ctlr,  div & 0xff); /* set baudrate */
 132}
 133
 134int serial_init_dev(unsigned int idx)
 135{
 136        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 137        volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
 138        u32 reg;
 139
 140        reg = in_be32(&im->clk.sccr[0]);
 141        out_be32(&im->clk.sccr[0], reg | CLOCK_SCCR1_PSC_EN(idx));
 142
 143        fifo_init (psc);
 144
 145        /* set MR register to point to MR1 */
 146        out_8(&psc->command, PSC_SEL_MODE_REG_1);
 147
 148        /* disable Tx/Rx */
 149        out_8(&psc->command, PSC_TX_DISABLE | PSC_RX_DISABLE);
 150
 151        /* choose the prescaler by 16 for the Tx/Rx clock generation */
 152        out_be16(&psc->psc_clock_select, 0xdd00);
 153
 154        /* switch to UART mode */
 155        out_be32(&psc->sicr, 0);
 156
 157        /* mode register points to mr1 */
 158        /* configure parity, bit length and so on in mode register 1*/
 159        out_8(&psc->mode, PSC_MODE_8_BITS | PSC_MODE_PARNONE);
 160        /* now, mode register points to mr2 */
 161        out_8(&psc->mode, PSC_MODE_1_STOPBIT);
 162
 163        /* set baudrate */
 164        serial_setbrg_dev(idx);
 165
 166        /* disable all interrupts */
 167        out_be16(&psc->psc_imr, 0);
 168
 169        /* reset and enable Rx/Tx */
 170        out_8(&psc->command, PSC_RST_RX);
 171        out_8(&psc->command, PSC_RST_TX);
 172        out_8(&psc->command, PSC_RX_ENABLE | PSC_TX_ENABLE);
 173
 174        return 0;
 175}
 176
 177int serial_uninit_dev(unsigned int idx)
 178{
 179        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 180        volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
 181        u32 reg;
 182
 183        out_8(&psc->command, PSC_RX_DISABLE | PSC_TX_DISABLE);
 184        reg = in_be32(&im->clk.sccr[0]);
 185        reg &= ~CLOCK_SCCR1_PSC_EN(idx);
 186        out_be32(&im->clk.sccr[0], reg);
 187
 188        return 0;
 189}
 190
 191void serial_putc_dev(unsigned int idx, const char c)
 192{
 193        volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
 194        volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
 195
 196        if (c == '\n')
 197                serial_putc_dev(idx, '\r');
 198
 199        /* Wait for last character to go. */
 200        while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP))
 201                ;
 202
 203        out_8(&psc->tfdata_8, c);
 204}
 205
 206void serial_puts_dev(unsigned int idx, const char *s)
 207{
 208        while (*s)
 209                serial_putc_dev(idx, *s++);
 210}
 211
 212int serial_getc_dev(unsigned int idx)
 213{
 214        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 215        volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
 216
 217        /* Wait for a character to arrive. */
 218        while (in_be32(&psc->rfstat) & PSC_FIFO_EMPTY)
 219                ;
 220
 221        return in_8(&psc->rfdata_8);
 222}
 223
 224int serial_tstc_dev(unsigned int idx)
 225{
 226        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 227        volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
 228
 229        return !(in_be32(&psc->rfstat) & PSC_FIFO_EMPTY);
 230}
 231
 232void serial_setrts_dev(unsigned int idx, int s)
 233{
 234        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 235        volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
 236
 237        if (s) {
 238                /* Assert RTS (become LOW) */
 239                out_8(&psc->op1, 0x1);
 240        }
 241        else {
 242                /* Negate RTS (become HIGH) */
 243                out_8(&psc->op0, 0x1);
 244        }
 245}
 246
 247int serial_getcts_dev(unsigned int idx)
 248{
 249        volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 250        volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
 251
 252        return (in_8(&psc->ip) & 0x1) ? 0 : 1;
 253}
 254#endif /* CONFIG_PSC_CONSOLE */
 255
 256#define DECLARE_PSC_SERIAL_FUNCTIONS(port) \
 257        int serial##port##_init(void) \
 258        { \
 259                return serial_init_dev(port); \
 260        } \
 261        int serial##port##_uninit(void) \
 262        { \
 263                return serial_uninit_dev(port); \
 264        } \
 265        void serial##port##_setbrg(void) \
 266        { \
 267                serial_setbrg_dev(port); \
 268        } \
 269        int serial##port##_getc(void) \
 270        { \
 271                return serial_getc_dev(port); \
 272        } \
 273        int serial##port##_tstc(void) \
 274        { \
 275                return serial_tstc_dev(port); \
 276        } \
 277        void serial##port##_putc(const char c) \
 278        { \
 279                serial_putc_dev(port, c); \
 280        } \
 281        void serial##port##_puts(const char *s) \
 282        { \
 283                serial_puts_dev(port, s); \
 284        }
 285
 286#define INIT_PSC_SERIAL_STRUCTURE(port, __name) {       \
 287        .name   = __name,                               \
 288        .start  = serial##port##_init,                  \
 289        .stop   = serial##port##_uninit,                \
 290        .setbrg = serial##port##_setbrg,                \
 291        .getc   = serial##port##_getc,                  \
 292        .tstc   = serial##port##_tstc,                  \
 293        .putc   = serial##port##_putc,                  \
 294        .puts   = serial##port##_puts,                  \
 295}
 296
 297#if defined(CONFIG_SYS_PSC1)
 298DECLARE_PSC_SERIAL_FUNCTIONS(1);
 299struct serial_device serial1_device =
 300INIT_PSC_SERIAL_STRUCTURE(1, "psc1");
 301#endif
 302
 303#if defined(CONFIG_SYS_PSC3)
 304DECLARE_PSC_SERIAL_FUNCTIONS(3);
 305struct serial_device serial3_device =
 306INIT_PSC_SERIAL_STRUCTURE(3, "psc3");
 307#endif
 308
 309#if defined(CONFIG_SYS_PSC4)
 310DECLARE_PSC_SERIAL_FUNCTIONS(4);
 311struct serial_device serial4_device =
 312INIT_PSC_SERIAL_STRUCTURE(4, "psc4");
 313#endif
 314
 315#if defined(CONFIG_SYS_PSC6)
 316DECLARE_PSC_SERIAL_FUNCTIONS(6);
 317struct serial_device serial6_device =
 318INIT_PSC_SERIAL_STRUCTURE(6, "psc6");
 319#endif
 320
 321__weak struct serial_device *default_serial_console(void)
 322{
 323#if (CONFIG_PSC_CONSOLE == 3)
 324        return &serial3_device;
 325#elif (CONFIG_PSC_CONSOLE == 6)
 326        return &serial6_device;
 327#else
 328#error "invalid CONFIG_PSC_CONSOLE"
 329#endif
 330}
 331
 332void mpc512x_serial_initialize(void)
 333{
 334#if defined(CONFIG_SYS_PSC1)
 335        serial_register(&serial1_device);
 336#endif
 337#if defined(CONFIG_SYS_PSC3)
 338        serial_register(&serial3_device);
 339#endif
 340#if defined(CONFIG_SYS_PSC4)
 341        serial_register(&serial4_device);
 342#endif
 343#if defined(CONFIG_SYS_PSC6)
 344        serial_register(&serial6_device);
 345#endif
 346}
 347
 348#include <stdio_dev.h>
 349/*
 350 * Routines for communication with serial devices over PSC
 351 */
 352/* Bitfield for initialized PSCs */
 353static unsigned int initialized;
 354
 355struct stdio_dev *open_port(int num, int baudrate)
 356{
 357        struct stdio_dev *port;
 358        char env_var[16];
 359        char env_val[10];
 360        char name[7];
 361
 362        if (num < 0 || num > 11)
 363                return NULL;
 364
 365        sprintf(name, "psc%d", num);
 366        port = stdio_get_by_name(name);
 367        if (!port)
 368                return NULL;
 369
 370        if (!test_bit(num, &initialized)) {
 371                sprintf(env_var, "psc%d_baudrate", num);
 372                sprintf(env_val, "%d", baudrate);
 373                setenv(env_var, env_val);
 374
 375                if (port->start(port))
 376                        return NULL;
 377
 378                set_bit(num, &initialized);
 379        }
 380
 381        return port;
 382}
 383
 384int close_port(int num)
 385{
 386        struct stdio_dev *port;
 387        int ret;
 388        char name[7];
 389
 390        if (num < 0 || num > 11)
 391                return -1;
 392
 393        sprintf(name, "psc%d", num);
 394        port = stdio_get_by_name(name);
 395        if (!port)
 396                return -1;
 397
 398        ret = port->stop(port);
 399        clear_bit(num, &initialized);
 400
 401        return ret;
 402}
 403
 404int write_port(struct stdio_dev *port, char *buf)
 405{
 406        if (!port || !buf)
 407                return -1;
 408
 409        port->puts(port, buf);
 410
 411        return 0;
 412}
 413
 414int read_port(struct stdio_dev *port, char *buf, int size)
 415{
 416        int cnt = 0;
 417
 418        if (!port || !buf)
 419                return -1;
 420
 421        if (!size)
 422                return 0;
 423
 424        while (port->tstc(port)) {
 425                buf[cnt++] = port->getc(port);
 426                if (cnt > size)
 427                        break;
 428        }
 429
 430        return cnt;
 431}
 432