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 UART_WFIFO 0x0 19#define UART_RFIFO 0x4 20#define UART_STATUS 0xC 21 22#define UART_TX_FULL BIT(21) 23#define UART_RX_EMPTY BIT(20) 24 25#define REG_PTR(base, off) ((volatile uint32_t *)((base) + (off))) 26 27 28int uart_getchar(ps_chardevice_t *d) 29{ 30 while ((*REG_PTR(d->vaddr, UART_STATUS) & UART_RX_EMPTY)); 31 return *REG_PTR(d->vaddr, UART_RFIFO); 32} 33 34int uart_putchar(ps_chardevice_t *d, int c) 35{ 36 while ((*REG_PTR(d->vaddr, UART_STATUS) & UART_TX_FULL)); 37 38 /* Add character to the buffer. */ 39 *REG_PTR(d->vaddr, UART_WFIFO) = c & 0x7f; 40 if (c == '\n' && (d->flags & SERIAL_AUTO_CR)) { 41 uart_putchar(d, '\r'); 42 } 43 44 return c; 45} 46 47static void uart_handle_irq(ps_chardevice_t *dev) 48{ 49 /* nothing to do, interrupts are not used */ 50} 51 52int uart_init(const struct dev_defn *defn, 53 const ps_io_ops_t *ops, 54 ps_chardevice_t *dev) 55{ 56 memset(dev, 0, sizeof(*dev)); 57 char *page_vaddr = chardev_map(defn, ops); 58 if (page_vaddr == NULL) { 59 return -1; 60 } 61 62 void *uart_vaddr; 63 switch (defn->id) { 64 case UART0: 65 uart_vaddr = page_vaddr + UART0_OFFSET; 66 break; 67 case UART1: 68 uart_vaddr = page_vaddr + UART1_OFFSET; 69 break; 70 case UART2: 71 uart_vaddr = page_vaddr + UART2_OFFSET; 72 break; 73 case UART0_AO: 74 uart_vaddr = page_vaddr + UART0_AO_OFFSET; 75 break; 76 case UART2_AO: 77 uart_vaddr = page_vaddr + UART2_AO_OFFSET; 78 break; 79 } 80 81 /* Set up all the device properties. */ 82 dev->id = defn->id; 83 dev->vaddr = uart_vaddr; 84 dev->read = &uart_read; 85 dev->write = &uart_write; 86 dev->handle_irq = &uart_handle_irq; 87 dev->irqs = defn->irqs; 88 dev->ioops = *ops; 89 dev->flags = SERIAL_AUTO_CR; 90 91 return 0; 92} 93