uboot/drivers/serial/serial_lpuart.c
<<
>>
Prefs
   1/*
   2 * Copyright 2013 Freescale Semiconductor, Inc.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <watchdog.h>
  10#include <asm/io.h>
  11#include <serial.h>
  12#include <linux/compiler.h>
  13#include <asm/arch/imx-regs.h>
  14#include <asm/arch/clock.h>
  15
  16#define US1_TDRE        (1 << 7)
  17#define US1_RDRF        (1 << 5)
  18#define US1_OR          (1 << 3)
  19#define UC2_TE          (1 << 3)
  20#define UC2_RE          (1 << 2)
  21#define CFIFO_TXFLUSH   (1 << 7)
  22#define CFIFO_RXFLUSH   (1 << 6)
  23#define SFIFO_RXOF      (1 << 2)
  24#define SFIFO_RXUF      (1 << 0)
  25
  26#define STAT_LBKDIF     (1 << 31)
  27#define STAT_RXEDGIF    (1 << 30)
  28#define STAT_TDRE       (1 << 23)
  29#define STAT_RDRF       (1 << 21)
  30#define STAT_IDLE       (1 << 20)
  31#define STAT_OR         (1 << 19)
  32#define STAT_NF         (1 << 18)
  33#define STAT_FE         (1 << 17)
  34#define STAT_PF         (1 << 16)
  35#define STAT_MA1F       (1 << 15)
  36#define STAT_MA2F       (1 << 14)
  37#define STAT_FLAGS      (STAT_LBKDIF | STAT_RXEDGIF | STAT_IDLE | STAT_OR | \
  38                         STAT_NF | STAT_FE | STAT_PF | STAT_MA1F | STAT_MA2F)
  39
  40#define CTRL_TE         (1 << 19)
  41#define CTRL_RE         (1 << 18)
  42
  43#define FIFO_TXFE               0x80
  44#define FIFO_RXFE               0x40
  45
  46#define WATER_TXWATER_OFF       1
  47#define WATER_RXWATER_OFF       16
  48
  49DECLARE_GLOBAL_DATA_PTR;
  50
  51struct lpuart_serial_platdata {
  52        struct lpuart_fsl *reg;
  53};
  54
  55#ifndef CONFIG_LPUART_32B_REG
  56static void _lpuart_serial_setbrg(struct lpuart_fsl *base, int baudrate)
  57{
  58        u32 clk = mxc_get_clock(MXC_UART_CLK);
  59        u16 sbr;
  60
  61        sbr = (u16)(clk / (16 * baudrate));
  62
  63        /* place adjustment later - n/32 BRFA */
  64        __raw_writeb(sbr >> 8, &base->ubdh);
  65        __raw_writeb(sbr & 0xff, &base->ubdl);
  66}
  67
  68static int _lpuart_serial_getc(struct lpuart_fsl *base)
  69{
  70        while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR)))
  71                WATCHDOG_RESET();
  72
  73        barrier();
  74
  75        return __raw_readb(&base->ud);
  76}
  77
  78static void _lpuart_serial_putc(struct lpuart_fsl *base, const char c)
  79{
  80        while (!(__raw_readb(&base->us1) & US1_TDRE))
  81                WATCHDOG_RESET();
  82
  83        __raw_writeb(c, &base->ud);
  84}
  85
  86/* Test whether a character is in the RX buffer */
  87static int _lpuart_serial_tstc(struct lpuart_fsl *base)
  88{
  89        if (__raw_readb(&base->urcfifo) == 0)
  90                return 0;
  91
  92        return 1;
  93}
  94
  95/*
  96 * Initialise the serial port with the given baudrate. The settings
  97 * are always 8 data bits, no parity, 1 stop bit, no start bits.
  98 */
  99static int _lpuart_serial_init(struct lpuart_fsl *base)
 100{
 101        u8 ctrl;
 102
 103        ctrl = __raw_readb(&base->uc2);
 104        ctrl &= ~UC2_RE;
 105        ctrl &= ~UC2_TE;
 106        __raw_writeb(ctrl, &base->uc2);
 107
 108        __raw_writeb(0, &base->umodem);
 109        __raw_writeb(0, &base->uc1);
 110
 111        /* Disable FIFO and flush buffer */
 112        __raw_writeb(0x0, &base->upfifo);
 113        __raw_writeb(0x0, &base->utwfifo);
 114        __raw_writeb(0x1, &base->urwfifo);
 115        __raw_writeb(CFIFO_TXFLUSH | CFIFO_RXFLUSH, &base->ucfifo);
 116
 117        /* provide data bits, parity, stop bit, etc */
 118        _lpuart_serial_setbrg(base, gd->baudrate);
 119
 120        __raw_writeb(UC2_RE | UC2_TE, &base->uc2);
 121
 122        return 0;
 123}
 124
 125static int lpuart_serial_setbrg(struct udevice *dev, int baudrate)
 126{
 127        struct lpuart_serial_platdata *plat = dev->platdata;
 128        struct lpuart_fsl *reg = plat->reg;
 129
 130        _lpuart_serial_setbrg(reg, baudrate);
 131
 132        return 0;
 133}
 134
 135static int lpuart_serial_getc(struct udevice *dev)
 136{
 137        struct lpuart_serial_platdata *plat = dev->platdata;
 138        struct lpuart_fsl *reg = plat->reg;
 139
 140        return _lpuart_serial_getc(reg);
 141}
 142
 143static int lpuart_serial_putc(struct udevice *dev, const char c)
 144{
 145        struct lpuart_serial_platdata *plat = dev->platdata;
 146        struct lpuart_fsl *reg = plat->reg;
 147
 148        _lpuart_serial_putc(reg, c);
 149
 150        return 0;
 151}
 152
 153static int lpuart_serial_pending(struct udevice *dev, bool input)
 154{
 155        struct lpuart_serial_platdata *plat = dev->platdata;
 156        struct lpuart_fsl *reg = plat->reg;
 157
 158        if (input)
 159                return _lpuart_serial_tstc(reg);
 160        else
 161                return __raw_readb(&reg->us1) & US1_TDRE ? 0 : 1;
 162}
 163
 164static int lpuart_serial_probe(struct udevice *dev)
 165{
 166        struct lpuart_serial_platdata *plat = dev->platdata;
 167        struct lpuart_fsl *reg = plat->reg;
 168
 169        return _lpuart_serial_init(reg);
 170}
 171#else
 172
 173u32 __weak get_lpuart_clk(void)
 174{
 175        return CONFIG_SYS_CLK_FREQ;
 176}
 177
 178static void _lpuart32_serial_setbrg(struct lpuart_fsl *base, int baudrate)
 179{
 180        u32 clk = get_lpuart_clk();
 181        u32 sbr;
 182
 183        sbr = (clk / (16 * baudrate));
 184
 185        /* place adjustment later - n/32 BRFA */
 186        out_be32(&base->baud, sbr);
 187}
 188
 189static int _lpuart32_serial_getc(struct lpuart_fsl *base)
 190{
 191        u32 stat;
 192
 193        while (((stat = in_be32(&base->stat)) & STAT_RDRF) == 0) {
 194                out_be32(&base->stat, STAT_FLAGS);
 195                WATCHDOG_RESET();
 196        }
 197
 198        return in_be32(&base->data) & 0x3ff;
 199}
 200
 201static void _lpuart32_serial_putc(struct lpuart_fsl *base, const char c)
 202{
 203        while (!(in_be32(&base->stat) & STAT_TDRE))
 204                WATCHDOG_RESET();
 205
 206        out_be32(&base->data, c);
 207}
 208
 209/* Test whether a character is in the RX buffer */
 210static int _lpuart32_serial_tstc(struct lpuart_fsl *base)
 211{
 212        if ((in_be32(&base->water) >> 24) == 0)
 213                return 0;
 214
 215        return 1;
 216}
 217
 218/*
 219 * Initialise the serial port with the given baudrate. The settings
 220 * are always 8 data bits, no parity, 1 stop bit, no start bits.
 221 */
 222static int _lpuart32_serial_init(struct lpuart_fsl *base)
 223{
 224        u8 ctrl;
 225
 226        ctrl = in_be32(&base->ctrl);
 227        ctrl &= ~CTRL_RE;
 228        ctrl &= ~CTRL_TE;
 229        out_be32(&base->ctrl, ctrl);
 230
 231        out_be32(&base->modir, 0);
 232        out_be32(&base->fifo, ~(FIFO_TXFE | FIFO_RXFE));
 233
 234        out_be32(&base->match, 0);
 235
 236        /* provide data bits, parity, stop bit, etc */
 237        _lpuart32_serial_setbrg(base, gd->baudrate);
 238
 239        out_be32(&base->ctrl, CTRL_RE | CTRL_TE);
 240
 241        return 0;
 242}
 243
 244static int lpuart32_serial_setbrg(struct udevice *dev, int baudrate)
 245{
 246        struct lpuart_serial_platdata *plat = dev->platdata;
 247        struct lpuart_fsl *reg = plat->reg;
 248
 249        _lpuart32_serial_setbrg(reg, baudrate);
 250
 251        return 0;
 252}
 253
 254static int lpuart32_serial_getc(struct udevice *dev)
 255{
 256        struct lpuart_serial_platdata *plat = dev->platdata;
 257        struct lpuart_fsl *reg = plat->reg;
 258
 259        return _lpuart32_serial_getc(reg);
 260}
 261
 262static int lpuart32_serial_putc(struct udevice *dev, const char c)
 263{
 264        struct lpuart_serial_platdata *plat = dev->platdata;
 265        struct lpuart_fsl *reg = plat->reg;
 266
 267        _lpuart32_serial_putc(reg, c);
 268
 269        return 0;
 270}
 271
 272static int lpuart32_serial_pending(struct udevice *dev, bool input)
 273{
 274        struct lpuart_serial_platdata *plat = dev->platdata;
 275        struct lpuart_fsl *reg = plat->reg;
 276
 277        if (input)
 278                return _lpuart32_serial_tstc(reg);
 279        else
 280                return in_be32(&reg->stat) & STAT_TDRE ? 0 : 1;
 281}
 282
 283static int lpuart32_serial_probe(struct udevice *dev)
 284{
 285        struct lpuart_serial_platdata *plat = dev->platdata;
 286        struct lpuart_fsl *reg = plat->reg;
 287
 288        return _lpuart32_serial_init(reg);
 289}
 290#endif /* CONFIG_LPUART_32B_REG */
 291
 292static int lpuart_serial_ofdata_to_platdata(struct udevice *dev)
 293{
 294        struct lpuart_serial_platdata *plat = dev->platdata;
 295        fdt_addr_t addr;
 296
 297        addr = dev_get_addr(dev);
 298        if (addr == FDT_ADDR_T_NONE)
 299                return -EINVAL;
 300
 301        plat->reg = (struct lpuart_fsl *)addr;
 302
 303        return 0;
 304}
 305
 306#ifndef CONFIG_LPUART_32B_REG
 307static const struct dm_serial_ops lpuart_serial_ops = {
 308        .putc = lpuart_serial_putc,
 309        .pending = lpuart_serial_pending,
 310        .getc = lpuart_serial_getc,
 311        .setbrg = lpuart_serial_setbrg,
 312};
 313
 314static const struct udevice_id lpuart_serial_ids[] = {
 315        { .compatible = "fsl,vf610-lpuart" },
 316        { }
 317};
 318
 319U_BOOT_DRIVER(serial_lpuart) = {
 320        .name   = "serial_lpuart",
 321        .id     = UCLASS_SERIAL,
 322        .of_match = lpuart_serial_ids,
 323        .ofdata_to_platdata = lpuart_serial_ofdata_to_platdata,
 324        .platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata),
 325        .probe = lpuart_serial_probe,
 326        .ops    = &lpuart_serial_ops,
 327        .flags = DM_FLAG_PRE_RELOC,
 328};
 329#else /* CONFIG_LPUART_32B_REG */
 330static const struct dm_serial_ops lpuart32_serial_ops = {
 331        .putc = lpuart32_serial_putc,
 332        .pending = lpuart32_serial_pending,
 333        .getc = lpuart32_serial_getc,
 334        .setbrg = lpuart32_serial_setbrg,
 335};
 336
 337static const struct udevice_id lpuart32_serial_ids[] = {
 338        { .compatible = "fsl,ls1021a-lpuart" },
 339        { }
 340};
 341
 342U_BOOT_DRIVER(serial_lpuart32) = {
 343        .name   = "serial_lpuart32",
 344        .id     = UCLASS_SERIAL,
 345        .of_match = lpuart32_serial_ids,
 346        .ofdata_to_platdata = lpuart_serial_ofdata_to_platdata,
 347        .platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata),
 348        .probe = lpuart32_serial_probe,
 349        .ops    = &lpuart32_serial_ops,
 350        .flags = DM_FLAG_PRE_RELOC,
 351};
 352#endif /* CONFIG_LPUART_32B_REG */
 353