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