|
| 1 | +/* |
| 2 | + * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: BSD-2-Clause |
| 5 | + */ |
| 6 | + |
| 7 | +#include <string.h> |
| 8 | +#include <stdlib.h> |
| 9 | +#include <platsupport/serial.h> |
| 10 | +#include "../../chardev.h" |
| 11 | + |
| 12 | +#define RHR 0x00 |
| 13 | +#define THR 0x00 |
| 14 | +#define IER 0x04 |
| 15 | +#define LSR 0x14 |
| 16 | +#define RHR_MASK MASK(8) |
| 17 | +#define IER_RHRIT BIT(0) |
| 18 | +#define LSR_TXFIFOE BIT(5) |
| 19 | +#define LSR_RXFIFOE BIT(0) |
| 20 | + |
| 21 | +#define REG_PTR(base, off) ((volatile uint32_t *)((base) + (off))) |
| 22 | + |
| 23 | +int uart_getchar(ps_chardevice_t *d) |
| 24 | +{ |
| 25 | + int ch = EOF; |
| 26 | + |
| 27 | + if (*REG_PTR(d->vaddr, LSR) & LSR_RXFIFOE) { |
| 28 | + ch = *REG_PTR(d->vaddr, RHR) & RHR_MASK; |
| 29 | + } |
| 30 | + return ch; |
| 31 | +} |
| 32 | + |
| 33 | +int uart_putchar(ps_chardevice_t *d, int c) |
| 34 | +{ |
| 35 | + if (c == '\n' && (d->flags & SERIAL_AUTO_CR)) { |
| 36 | + uart_putchar(d, '\r'); |
| 37 | + } |
| 38 | + while (!(*REG_PTR(d->vaddr, LSR) & LSR_TXFIFOE)) { |
| 39 | + continue; |
| 40 | + } |
| 41 | + *REG_PTR(d->vaddr, THR) = c; |
| 42 | + |
| 43 | + return c; |
| 44 | +} |
| 45 | + |
| 46 | +static void uart_handle_irq(ps_chardevice_t *d UNUSED) |
| 47 | +{ |
| 48 | + /* nothing to do */ |
| 49 | +} |
| 50 | + |
| 51 | +int uart_init(const struct dev_defn *defn, |
| 52 | + const ps_io_ops_t *ops, |
| 53 | + ps_chardevice_t *dev) |
| 54 | +{ |
| 55 | + memset(dev, 0, sizeof(*dev)); |
| 56 | + void *vaddr = chardev_map(defn, ops); |
| 57 | + if (vaddr == NULL) { |
| 58 | + return -1; |
| 59 | + } |
| 60 | + |
| 61 | + /* Set up all the device properties. */ |
| 62 | + dev->id = defn->id; |
| 63 | + dev->vaddr = (void *)vaddr; |
| 64 | + dev->read = &uart_read; |
| 65 | + dev->write = &uart_write; |
| 66 | + dev->handle_irq = &uart_handle_irq; |
| 67 | + dev->irqs = defn->irqs; |
| 68 | + dev->ioops = *ops; |
| 69 | + dev->flags = SERIAL_AUTO_CR; |
| 70 | + |
| 71 | + *REG_PTR(dev->vaddr, IER) = IER_RHRIT; |
| 72 | + return 0; |
| 73 | +} |
0 commit comments