| /* |
| * Copyright 2017, Data61 |
| * Commonwealth Scientific and Industrial Research Organisation (CSIRO) |
| * ABN 41 687 119 230. |
| * |
| * This software may be distributed and modified according to the terms of |
| * the BSD 2-Clause license. Note that NO WARRANTY is provided. |
| * See "LICENSE_BSD2.txt" for details. |
| * |
| * @TAG(DATA61_BSD) |
| */ |
| |
| #include <stdlib.h> |
| #include <platsupport/serial.h> |
| #include <platsupport/plat/serial.h> |
| #include "serial.h" |
| #include <string.h> |
| |
| #define REG_PTR(base, off) ((volatile uint32_t *)((base) + (off))) |
| |
| /* When DLAB=1, MU_IO is a baud rate register. |
| * Otherwise, write to TX, read to RX */ |
| #define MU_IO 0x40 |
| /* When DLAB=1, MU_IIR is a baud rate register. |
| * Otherwise IRQ enable */ |
| #define MU_IIR 0x44 |
| #define MU_IER 0x48 |
| #define MU_LCR 0x4C |
| #define MU_MCR 0x50 |
| #define MU_LSR 0x54 |
| #define MU_MSR 0x58 |
| #define MU_SCRATCH 0x5C |
| #define MU_CNTL 0x60 |
| |
| /* This bit is set if the transmit FIFO can accept at least one byte.*/ |
| #define MU_LSR_TXEMPTY BIT(5) |
| /* This bit is set if the transmit FIFO is empty and the |
| * transmitter is idle. (Finished shifting out the last bit). */ |
| #define MU_LSR_TXIDLE BIT(6) |
| #define MU_LSR_RXOVERRUN BIT(1) |
| #define MU_LSR_DATAREADY BIT(0) |
| |
| #define MU_LCR_DLAB BIT(7) |
| #define MU_LCR_BREAK BIT(6) |
| #define MU_LCR_DATASIZE BIT(0) |
| |
| static void |
| uart_handle_irq(ps_chardevice_t* d UNUSED) |
| { |
| } |
| |
| int uart_putchar(ps_chardevice_t* d, int c) |
| { |
| while ( !(*REG_PTR(d->vaddr, MU_LSR) & MU_LSR_TXIDLE) ); |
| *REG_PTR(d->vaddr, MU_IO) = (c & 0xff); |
| |
| return 0; |
| } |
| |
| int uart_getchar(ps_chardevice_t* d UNUSED) |
| { |
| while ( !(*REG_PTR(d->vaddr, MU_LSR) & MU_LSR_DATAREADY) ); |
| return *REG_PTR(d->vaddr, MU_IO); |
| } |
| |
| int uart_init(const struct dev_defn* defn, |
| const ps_io_ops_t* ops, |
| ps_chardevice_t* dev) |
| { |
| /* Attempt to map the virtual address, assure this works */ |
| void* vaddr = chardev_map(defn, ops); |
| memset(dev, 0, sizeof(*dev)); |
| if (vaddr == NULL) { |
| return -1; |
| } |
| |
| /* Set up all the device properties. */ |
| dev->id = defn->id; |
| dev->vaddr = (void*)vaddr; |
| dev->read = &uart_read; |
| dev->write = &uart_write; |
| dev->handle_irq = &uart_handle_irq; |
| dev->irqs = defn->irqs; |
| dev->ioops = *ops; |
| dev->flags = SERIAL_AUTO_CR; |
| |
| return 0; |
| } |