uboot/drivers/serial/serial_pxa.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
   4 *
   5 * (C) Copyright 2002
   6 * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
   7 *
   8 * (C) Copyright 2002
   9 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  10 * Marius Groeger <mgroeger@sysgo.de>
  11 *
  12 * (C) Copyright 2002
  13 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  14 * Alex Zuepke <azu@sysgo.de>
  15 *
  16 * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
  17 *
  18 * Modified to add driver model (DM) support
  19 * (C) Copyright 2016 Marcel Ziswiler <marcel.ziswiler@toradex.com>
  20 */
  21
  22#include <common.h>
  23#include <asm/arch/pxa-regs.h>
  24#include <asm/arch/regs-uart.h>
  25#include <asm/io.h>
  26#include <dm.h>
  27#include <dm/platform_data/serial_pxa.h>
  28#include <linux/compiler.h>
  29#include <serial.h>
  30#include <watchdog.h>
  31
  32DECLARE_GLOBAL_DATA_PTR;
  33
  34static uint32_t pxa_uart_get_baud_divider(int baudrate)
  35{
  36        return 921600 / baudrate;
  37}
  38
  39static void pxa_uart_toggle_clock(uint32_t uart_index, int enable)
  40{
  41        uint32_t clk_reg, clk_offset, reg;
  42
  43        clk_reg = UART_CLK_REG;
  44        clk_offset = UART_CLK_BASE << uart_index;
  45
  46        reg = readl(clk_reg);
  47
  48        if (enable)
  49                reg |= clk_offset;
  50        else
  51                reg &= ~clk_offset;
  52
  53        writel(reg, clk_reg);
  54}
  55
  56/*
  57 * Enable clock and set baud rate, parity etc.
  58 */
  59void pxa_setbrg_common(struct pxa_uart_regs *uart_regs, int port, int baudrate)
  60{
  61        uint32_t divider = pxa_uart_get_baud_divider(baudrate);
  62        if (!divider)
  63                hang();
  64
  65
  66        pxa_uart_toggle_clock(port, 1);
  67
  68        /* Disable interrupts and FIFOs */
  69        writel(0, &uart_regs->ier);
  70        writel(0, &uart_regs->fcr);
  71
  72        /* Set baud rate */
  73        writel(LCR_WLS0 | LCR_WLS1 | LCR_DLAB, &uart_regs->lcr);
  74        writel(divider & 0xff, &uart_regs->dll);
  75        writel(divider >> 8, &uart_regs->dlh);
  76        writel(LCR_WLS0 | LCR_WLS1, &uart_regs->lcr);
  77
  78        /* Enable UART */
  79        writel(IER_UUE, &uart_regs->ier);
  80}
  81
  82#ifndef CONFIG_DM_SERIAL
  83static struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)
  84{
  85        switch (uart_index) {
  86        case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE;
  87        case BTUART_INDEX: return (struct pxa_uart_regs *)BTUART_BASE;
  88        case STUART_INDEX: return (struct pxa_uart_regs *)STUART_BASE;
  89        case HWUART_INDEX: return (struct pxa_uart_regs *)HWUART_BASE;
  90        default:
  91                return NULL;
  92        }
  93}
  94
  95/*
  96 * Enable clock and set baud rate, parity etc.
  97 */
  98void pxa_setbrg_dev(uint32_t uart_index)
  99{
 100        struct pxa_uart_regs *uart_regs = pxa_uart_index_to_regs(uart_index);
 101        if (!uart_regs)
 102                panic("Failed getting UART registers\n");
 103
 104        pxa_setbrg_common(uart_regs, uart_index, gd->baudrate);
 105}
 106
 107/*
 108 * Initialise the serial port with the given baudrate. The settings
 109 * are always 8 data bits, no parity, 1 stop bit, no start bits.
 110 */
 111int pxa_init_dev(unsigned int uart_index)
 112{
 113        pxa_setbrg_dev(uart_index);
 114        return 0;
 115}
 116
 117/*
 118 * Output a single byte to the serial port.
 119 */
 120void pxa_putc_dev(unsigned int uart_index, const char c)
 121{
 122        struct pxa_uart_regs *uart_regs;
 123
 124        /* If \n, also do \r */
 125        if (c == '\n')
 126                pxa_putc_dev(uart_index, '\r');
 127
 128        uart_regs = pxa_uart_index_to_regs(uart_index);
 129        if (!uart_regs)
 130                hang();
 131
 132        while (!(readl(&uart_regs->lsr) & LSR_TEMT))
 133                WATCHDOG_RESET();
 134        writel(c, &uart_regs->thr);
 135}
 136
 137/*
 138 * Read a single byte from the serial port. Returns 1 on success, 0
 139 * otherwise. When the function is succesfull, the character read is
 140 * written into its argument c.
 141 */
 142int pxa_tstc_dev(unsigned int uart_index)
 143{
 144        struct pxa_uart_regs *uart_regs;
 145
 146        uart_regs = pxa_uart_index_to_regs(uart_index);
 147        if (!uart_regs)
 148                return -1;
 149
 150        return readl(&uart_regs->lsr) & LSR_DR;
 151}
 152
 153/*
 154 * Read a single byte from the serial port. Returns 1 on success, 0
 155 * otherwise. When the function is succesfull, the character read is
 156 * written into its argument c.
 157 */
 158int pxa_getc_dev(unsigned int uart_index)
 159{
 160        struct pxa_uart_regs *uart_regs;
 161
 162        uart_regs = pxa_uart_index_to_regs(uart_index);
 163        if (!uart_regs)
 164                return -1;
 165
 166        while (!(readl(&uart_regs->lsr) & LSR_DR))
 167                WATCHDOG_RESET();
 168        return readl(&uart_regs->rbr) & 0xff;
 169}
 170
 171void pxa_puts_dev(unsigned int uart_index, const char *s)
 172{
 173        while (*s)
 174                pxa_putc_dev(uart_index, *s++);
 175}
 176
 177#define pxa_uart(uart, UART)                                            \
 178        int uart##_init(void)                                           \
 179        {                                                               \
 180                return pxa_init_dev(UART##_INDEX);                      \
 181        }                                                               \
 182                                                                        \
 183        void uart##_setbrg(void)                                        \
 184        {                                                               \
 185                return pxa_setbrg_dev(UART##_INDEX);                    \
 186        }                                                               \
 187                                                                        \
 188        void uart##_putc(const char c)                                  \
 189        {                                                               \
 190                return pxa_putc_dev(UART##_INDEX, c);                   \
 191        }                                                               \
 192                                                                        \
 193        void uart##_puts(const char *s)                                 \
 194        {                                                               \
 195                return pxa_puts_dev(UART##_INDEX, s);                   \
 196        }                                                               \
 197                                                                        \
 198        int uart##_getc(void)                                           \
 199        {                                                               \
 200                return pxa_getc_dev(UART##_INDEX);                      \
 201        }                                                               \
 202                                                                        \
 203        int uart##_tstc(void)                                           \
 204        {                                                               \
 205                return pxa_tstc_dev(UART##_INDEX);                      \
 206        }                                                               \
 207
 208#define pxa_uart_desc(uart)                                             \
 209        struct serial_device serial_##uart##_device =                   \
 210        {                                                               \
 211                .name   = "serial_"#uart,                               \
 212                .start  = uart##_init,                                  \
 213                .stop   = NULL,                                         \
 214                .setbrg = uart##_setbrg,                                \
 215                .getc   = uart##_getc,                                  \
 216                .tstc   = uart##_tstc,                                  \
 217                .putc   = uart##_putc,                                  \
 218                .puts   = uart##_puts,                                  \
 219        };
 220
 221#define pxa_uart_multi(uart, UART)                                      \
 222        pxa_uart(uart, UART)                                            \
 223        pxa_uart_desc(uart)
 224
 225#if defined(CONFIG_HWUART)
 226        pxa_uart_multi(hwuart, HWUART)
 227#endif
 228#if defined(CONFIG_STUART)
 229        pxa_uart_multi(stuart, STUART)
 230#endif
 231#if defined(CONFIG_FFUART)
 232        pxa_uart_multi(ffuart, FFUART)
 233#endif
 234#if defined(CONFIG_BTUART)
 235        pxa_uart_multi(btuart, BTUART)
 236#endif
 237
 238__weak struct serial_device *default_serial_console(void)
 239{
 240#if CONFIG_CONS_INDEX == 1
 241        return &serial_hwuart_device;
 242#elif CONFIG_CONS_INDEX == 2
 243        return &serial_stuart_device;
 244#elif CONFIG_CONS_INDEX == 3
 245        return &serial_ffuart_device;
 246#elif CONFIG_CONS_INDEX == 4
 247        return &serial_btuart_device;
 248#else
 249#error "Bad CONFIG_CONS_INDEX."
 250#endif
 251}
 252
 253void pxa_serial_initialize(void)
 254{
 255#if defined(CONFIG_FFUART)
 256        serial_register(&serial_ffuart_device);
 257#endif
 258#if defined(CONFIG_BTUART)
 259        serial_register(&serial_btuart_device);
 260#endif
 261#if defined(CONFIG_STUART)
 262        serial_register(&serial_stuart_device);
 263#endif
 264}
 265#endif /* CONFIG_DM_SERIAL */
 266
 267#ifdef CONFIG_DM_SERIAL
 268static int pxa_serial_probe(struct udevice *dev)
 269{
 270        struct pxa_serial_platdata *plat = dev->platdata;
 271
 272        pxa_setbrg_common((struct pxa_uart_regs *)plat->base, plat->port,
 273                          plat->baudrate);
 274        return 0;
 275}
 276
 277static int pxa_serial_putc(struct udevice *dev, const char ch)
 278{
 279        struct pxa_serial_platdata *plat = dev->platdata;
 280        struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
 281
 282        /* Wait for last character to go. */
 283        if (!(readl(&uart_regs->lsr) & LSR_TEMT))
 284                return -EAGAIN;
 285
 286        writel(ch, &uart_regs->thr);
 287
 288        return 0;
 289}
 290
 291static int pxa_serial_getc(struct udevice *dev)
 292{
 293        struct pxa_serial_platdata *plat = dev->platdata;
 294        struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
 295
 296        /* Wait for a character to arrive. */
 297        if (!(readl(&uart_regs->lsr) & LSR_DR))
 298                return -EAGAIN;
 299
 300        return readl(&uart_regs->rbr) & 0xff;
 301}
 302
 303int pxa_serial_setbrg(struct udevice *dev, int baudrate)
 304{
 305        struct pxa_serial_platdata *plat = dev->platdata;
 306        struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
 307        int port = plat->port;
 308
 309        pxa_setbrg_common(uart_regs, port, baudrate);
 310
 311        return 0;
 312}
 313
 314static int pxa_serial_pending(struct udevice *dev, bool input)
 315{
 316        struct pxa_serial_platdata *plat = dev->platdata;
 317        struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
 318
 319        if (input)
 320                return readl(&uart_regs->lsr) & LSR_DR ? 1 : 0;
 321        else
 322                return readl(&uart_regs->lsr) & LSR_TEMT ? 0 : 1;
 323
 324        return 0;
 325}
 326
 327static const struct dm_serial_ops pxa_serial_ops = {
 328        .putc           = pxa_serial_putc,
 329        .pending        = pxa_serial_pending,
 330        .getc           = pxa_serial_getc,
 331        .setbrg         = pxa_serial_setbrg,
 332};
 333
 334U_BOOT_DRIVER(serial_pxa) = {
 335        .name   = "serial_pxa",
 336        .id     = UCLASS_SERIAL,
 337        .probe  = pxa_serial_probe,
 338        .ops    = &pxa_serial_ops,
 339        .flags  = DM_FLAG_PRE_RELOC,
 340};
 341#endif /* CONFIG_DM_SERIAL */
 342