1f3003a0dSAndrew Turner /*- 2f3003a0dSAndrew Turner * SPDX-License-Identifier: BSD-2-Clause 3f3003a0dSAndrew Turner * 4f3003a0dSAndrew Turner * Copyright (c) 2020 Andrew Turner 5f3003a0dSAndrew Turner * 6f3003a0dSAndrew Turner * This work was supported by Innovate UK project 105694, "Digital Security 7f3003a0dSAndrew Turner * by Design (DSbD) Technology Platform Prototype". 8f3003a0dSAndrew Turner * 9f3003a0dSAndrew Turner * Redistribution and use in source and binary forms, with or without 10f3003a0dSAndrew Turner * modification, are permitted provided that the following conditions 11f3003a0dSAndrew Turner * are met: 12f3003a0dSAndrew Turner * 1. Redistributions of source code must retain the above copyright 13f3003a0dSAndrew Turner * notice, this list of conditions and the following disclaimer. 14f3003a0dSAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright 15f3003a0dSAndrew Turner * notice, this list of conditions and the following disclaimer in the 16f3003a0dSAndrew Turner * documentation and/or other materials provided with the distribution. 17f3003a0dSAndrew Turner * 18f3003a0dSAndrew Turner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19f3003a0dSAndrew Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20f3003a0dSAndrew Turner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21f3003a0dSAndrew Turner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22f3003a0dSAndrew Turner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23f3003a0dSAndrew Turner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24f3003a0dSAndrew Turner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25f3003a0dSAndrew Turner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26f3003a0dSAndrew Turner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27f3003a0dSAndrew Turner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28f3003a0dSAndrew Turner * SUCH DAMAGE. 29f3003a0dSAndrew Turner */ 30f3003a0dSAndrew Turner 31f3003a0dSAndrew Turner #include <sys/param.h> 32f3003a0dSAndrew Turner 33f3003a0dSAndrew Turner #include <assert.h> 34f3003a0dSAndrew Turner #include <stdbool.h> 35f3003a0dSAndrew Turner #include <stdio.h> 36f3003a0dSAndrew Turner #include <stdlib.h> 37f3003a0dSAndrew Turner 38f3003a0dSAndrew Turner #include "uart_backend.h" 39f3003a0dSAndrew Turner #include "uart_emul.h" 40f3003a0dSAndrew Turner 41f3003a0dSAndrew Turner #define UART_FIFO_SIZE 16 42f3003a0dSAndrew Turner 43f3003a0dSAndrew Turner #define UARTDR 0x00 44f3003a0dSAndrew Turner #define UARTDR_RSR_SHIFT 8 45f3003a0dSAndrew Turner 46f3003a0dSAndrew Turner #define UARTRSR 0x01 47f3003a0dSAndrew Turner #define UARTRSR_OE (1 << 3) 48f3003a0dSAndrew Turner 49f3003a0dSAndrew Turner #define UARTFR 0x06 50f3003a0dSAndrew Turner #define UARTFR_TXFE (1 << 7) 51f3003a0dSAndrew Turner #define UARTFR_RXFF (1 << 6) 52f3003a0dSAndrew Turner #define UARTFR_TXFF (1 << 5) 53f3003a0dSAndrew Turner #define UARTFR_RXFE (1 << 4) 54f3003a0dSAndrew Turner 55f3003a0dSAndrew Turner #define UARTRTINTR (1 << 6) 56f3003a0dSAndrew Turner #define UARTTXINTR (1 << 5) 57f3003a0dSAndrew Turner #define UARTRXINTR (1 << 4) 58f3003a0dSAndrew Turner 59f3003a0dSAndrew Turner #define UARTIBRD 0x09 60f3003a0dSAndrew Turner 61f3003a0dSAndrew Turner #define UARTFBRD 0x0a 62f3003a0dSAndrew Turner #define UARTFBRD_MASK 0x003f 63f3003a0dSAndrew Turner 64f3003a0dSAndrew Turner #define UARTLCR_H 0x0b 65f3003a0dSAndrew Turner #define UARTLCR_H_MASK 0x00ff 66f3003a0dSAndrew Turner #define UARTLCR_H_FEN (1 << 4) 67f3003a0dSAndrew Turner 68f3003a0dSAndrew Turner #define UARTCR 0x0c 69f3003a0dSAndrew Turner /* TODO: Check the flags in the UARTCR register */ 70f3003a0dSAndrew Turner #define UARTCR_MASK 0xffc7 71f3003a0dSAndrew Turner #define UARTCR_LBE (1 << 7) 72f3003a0dSAndrew Turner 73f3003a0dSAndrew Turner #define UARTIFLS 0x0d 74f3003a0dSAndrew Turner #define UARTIFLS_MASK 0x003f 75f3003a0dSAndrew Turner #define UARTIFLS_RXIFLSEL(x) (((x) >> 3) & 0x7) 76f3003a0dSAndrew Turner #define UARTIFLS_TXIFLSEL(x) (((x) >> 0) & 0x7) 77f3003a0dSAndrew Turner 78f3003a0dSAndrew Turner #define UARTIMSC 0x0e 79f3003a0dSAndrew Turner #define UARTIMSC_MASK 0x07ff 80f3003a0dSAndrew Turner 81f3003a0dSAndrew Turner #define UARTRIS 0x0f 82f3003a0dSAndrew Turner #define UARTMIS 0x10 83f3003a0dSAndrew Turner 84f3003a0dSAndrew Turner #define UARTICR 0x11 85f3003a0dSAndrew Turner 86f3003a0dSAndrew Turner #define UARTPeriphID 0x00241011 87f3003a0dSAndrew Turner #define UARTPeriphID0 0x3f8 88f3003a0dSAndrew Turner #define UARTPeriphID0_VAL (((UARTPeriphID) >> 0) & 0xff) 89f3003a0dSAndrew Turner #define UARTPeriphID1 0x3f9 90f3003a0dSAndrew Turner #define UARTPeriphID1_VAL (((UARTPeriphID) >> 8) & 0xff) 91f3003a0dSAndrew Turner #define UARTPeriphID2 0x3fa 92f3003a0dSAndrew Turner #define UARTPeriphID2_VAL (((UARTPeriphID) >> 16) & 0xff) 93f3003a0dSAndrew Turner #define UARTPeriphID3 0x3fb 94f3003a0dSAndrew Turner #define UARTPeriphID3_VAL (((UARTPeriphID) >> 24) & 0xff) 95f3003a0dSAndrew Turner 96f3003a0dSAndrew Turner #define UARTPCellID 0xb105f00d 97f3003a0dSAndrew Turner #define UARTPCellID0 0x3fc 98f3003a0dSAndrew Turner #define UARTPCellID0_VAL (((UARTPCellID) >> 0) & 0xff) 99f3003a0dSAndrew Turner #define UARTPCellID1 0x3fd 100f3003a0dSAndrew Turner #define UARTPCellID1_VAL (((UARTPCellID) >> 8) & 0xff) 101f3003a0dSAndrew Turner #define UARTPCellID2 0x3fe 102f3003a0dSAndrew Turner #define UARTPCellID2_VAL (((UARTPCellID) >> 16) & 0xff) 103f3003a0dSAndrew Turner #define UARTPCellID3 0x3ff 104f3003a0dSAndrew Turner #define UARTPCellID3_VAL (((UARTPCellID) >> 24) & 0xff) 105f3003a0dSAndrew Turner 106f3003a0dSAndrew Turner struct uart_pl011_softc { 107f3003a0dSAndrew Turner struct uart_softc *backend; 108f3003a0dSAndrew Turner 109f3003a0dSAndrew Turner uint16_t irq_state; 110f3003a0dSAndrew Turner 111f3003a0dSAndrew Turner uint16_t rsr; 112f3003a0dSAndrew Turner 113f3003a0dSAndrew Turner uint16_t cr; 114f3003a0dSAndrew Turner uint16_t ifls; 115f3003a0dSAndrew Turner uint16_t imsc; 116f3003a0dSAndrew Turner uint16_t lcr_h; 117f3003a0dSAndrew Turner 118f3003a0dSAndrew Turner uint16_t ibrd; 119f3003a0dSAndrew Turner uint16_t fbrd; 120f3003a0dSAndrew Turner 121f3003a0dSAndrew Turner void *arg; 122f3003a0dSAndrew Turner uart_intr_func_t intr_assert; 123f3003a0dSAndrew Turner uart_intr_func_t intr_deassert; 124f3003a0dSAndrew Turner }; 125f3003a0dSAndrew Turner 126f3003a0dSAndrew Turner static void 127f3003a0dSAndrew Turner uart_reset(struct uart_pl011_softc *sc) 128f3003a0dSAndrew Turner { 129f3003a0dSAndrew Turner sc->ifls = 0x12; 130f3003a0dSAndrew Turner 131f3003a0dSAndrew Turner /* no fifo until enabled by software */ 132f3003a0dSAndrew Turner uart_rxfifo_reset(sc->backend, 1); 133f3003a0dSAndrew Turner } 134f3003a0dSAndrew Turner 135f3003a0dSAndrew Turner static int 136f3003a0dSAndrew Turner uart_rx_trigger_level(struct uart_pl011_softc *sc) 137f3003a0dSAndrew Turner { 138f3003a0dSAndrew Turner /* If the FIFO is disabled trigger when we have any data */ 139f3003a0dSAndrew Turner if ((sc->lcr_h & UARTLCR_H_FEN) != 0) 140f3003a0dSAndrew Turner return (1); 141f3003a0dSAndrew Turner 142f3003a0dSAndrew Turner /* Trigger base on how full the fifo is */ 143f3003a0dSAndrew Turner switch (UARTIFLS_RXIFLSEL(sc->ifls)) { 144f3003a0dSAndrew Turner case 0: 145f3003a0dSAndrew Turner return (UART_FIFO_SIZE / 8); 146f3003a0dSAndrew Turner case 1: 147f3003a0dSAndrew Turner return (UART_FIFO_SIZE / 4); 148f3003a0dSAndrew Turner case 2: 149f3003a0dSAndrew Turner return (UART_FIFO_SIZE / 2); 150f3003a0dSAndrew Turner case 3: 151f3003a0dSAndrew Turner return (UART_FIFO_SIZE * 3 / 4); 152f3003a0dSAndrew Turner case 4: 153f3003a0dSAndrew Turner return (UART_FIFO_SIZE * 7 / 8); 154f3003a0dSAndrew Turner default: 155f3003a0dSAndrew Turner /* TODO: Find out what happens in this case */ 156f3003a0dSAndrew Turner return (UART_FIFO_SIZE); 157f3003a0dSAndrew Turner } 158f3003a0dSAndrew Turner } 159f3003a0dSAndrew Turner 160f3003a0dSAndrew Turner static void 161f3003a0dSAndrew Turner uart_toggle_intr(struct uart_pl011_softc *sc) 162f3003a0dSAndrew Turner { 163f3003a0dSAndrew Turner if ((sc->irq_state & sc->imsc) == 0) 164f3003a0dSAndrew Turner (*sc->intr_deassert)(sc->arg); 165f3003a0dSAndrew Turner else 166f3003a0dSAndrew Turner (*sc->intr_assert)(sc->arg); 167f3003a0dSAndrew Turner } 168f3003a0dSAndrew Turner 169f3003a0dSAndrew Turner static void 170f3003a0dSAndrew Turner uart_drain(int fd __unused, enum ev_type ev, void *arg) 171f3003a0dSAndrew Turner { 172f3003a0dSAndrew Turner struct uart_pl011_softc *sc; 173f3003a0dSAndrew Turner int old_size, trig_lvl; 174f3003a0dSAndrew Turner bool loopback; 175f3003a0dSAndrew Turner 176f3003a0dSAndrew Turner sc = arg; 177f3003a0dSAndrew Turner 178f3003a0dSAndrew Turner assert(ev == EVF_READ); 179f3003a0dSAndrew Turner 180f3003a0dSAndrew Turner /* 181f3003a0dSAndrew Turner * This routine is called in the context of the mevent thread 182f3003a0dSAndrew Turner * to take out the softc lock to protect against concurrent 183f3003a0dSAndrew Turner * access from a vCPU i/o exit 184f3003a0dSAndrew Turner */ 185*e10b9d66SSHENG-YI HONG uart_softc_lock(sc->backend); 186f3003a0dSAndrew Turner 187f3003a0dSAndrew Turner old_size = uart_rxfifo_numchars(sc->backend); 188f3003a0dSAndrew Turner 189f3003a0dSAndrew Turner loopback = (sc->cr & UARTCR_LBE) != 0; 190f3003a0dSAndrew Turner uart_rxfifo_drain(sc->backend, loopback); 191f3003a0dSAndrew Turner 192f3003a0dSAndrew Turner /* If we cross the trigger level raise UARTRXINTR */ 193f3003a0dSAndrew Turner trig_lvl = uart_rx_trigger_level(sc); 194f3003a0dSAndrew Turner if (old_size < trig_lvl && 195f3003a0dSAndrew Turner uart_rxfifo_numchars(sc->backend) >= trig_lvl) 196f3003a0dSAndrew Turner sc->irq_state |= UARTRXINTR; 197f3003a0dSAndrew Turner 198f3003a0dSAndrew Turner if (uart_rxfifo_numchars(sc->backend) > 0) 199f3003a0dSAndrew Turner sc->irq_state |= UARTRTINTR; 200f3003a0dSAndrew Turner if (!loopback) 201f3003a0dSAndrew Turner uart_toggle_intr(sc); 202f3003a0dSAndrew Turner 203*e10b9d66SSHENG-YI HONG uart_softc_unlock(sc->backend); 204f3003a0dSAndrew Turner } 205f3003a0dSAndrew Turner 206f3003a0dSAndrew Turner void 207f3003a0dSAndrew Turner uart_pl011_write(struct uart_pl011_softc *sc, int offset, uint32_t value) 208f3003a0dSAndrew Turner { 209f3003a0dSAndrew Turner bool loopback; 210f3003a0dSAndrew Turner 211*e10b9d66SSHENG-YI HONG uart_softc_lock(sc->backend); 212f3003a0dSAndrew Turner switch (offset) { 213f3003a0dSAndrew Turner case UARTDR: 214f3003a0dSAndrew Turner loopback = (sc->cr & UARTCR_LBE) != 0; 215f3003a0dSAndrew Turner if (uart_rxfifo_putchar(sc->backend, value & 0xff, loopback)) 216f3003a0dSAndrew Turner sc->rsr |= UARTRSR_OE; 217f3003a0dSAndrew Turner 218f3003a0dSAndrew Turner /* We don't have a TX fifo, so trigger when we have data */ 219f3003a0dSAndrew Turner sc->irq_state |= UARTTXINTR; 220f3003a0dSAndrew Turner break; 221f3003a0dSAndrew Turner case UARTRSR: 222f3003a0dSAndrew Turner /* Any write clears this register */ 223f3003a0dSAndrew Turner sc->rsr = 0; 224f3003a0dSAndrew Turner break; 225f3003a0dSAndrew Turner case UARTFR: 226f3003a0dSAndrew Turner /* UARTFR is a read-only register */ 227f3003a0dSAndrew Turner break; 228f3003a0dSAndrew Turner /* TODO: UARTILPR */ 229f3003a0dSAndrew Turner case UARTIBRD: 230f3003a0dSAndrew Turner sc->ibrd = value; 231f3003a0dSAndrew Turner break; 232f3003a0dSAndrew Turner case UARTFBRD: 233f3003a0dSAndrew Turner sc->fbrd = value & UARTFBRD_MASK; 234f3003a0dSAndrew Turner break; 235f3003a0dSAndrew Turner case UARTLCR_H: 236f3003a0dSAndrew Turner /* Check if the FIFO enable bit changed */ 237f3003a0dSAndrew Turner if (((sc->lcr_h ^ value) & UARTLCR_H_FEN) != 0) { 238f3003a0dSAndrew Turner if ((value & UARTLCR_H_FEN) != 0) { 239f3003a0dSAndrew Turner uart_rxfifo_reset(sc->backend, UART_FIFO_SIZE); 240f3003a0dSAndrew Turner } else { 241f3003a0dSAndrew Turner uart_rxfifo_reset(sc->backend, 1); 242f3003a0dSAndrew Turner } 243f3003a0dSAndrew Turner } 244f3003a0dSAndrew Turner sc->lcr_h = value & UARTLCR_H_MASK; 245f3003a0dSAndrew Turner break; 246f3003a0dSAndrew Turner case UARTCR: 247f3003a0dSAndrew Turner sc->cr = value & UARTCR_MASK; 248f3003a0dSAndrew Turner break; 249f3003a0dSAndrew Turner case UARTIFLS: 250f3003a0dSAndrew Turner sc->ifls = value & UARTCR_MASK; 251f3003a0dSAndrew Turner break; 252f3003a0dSAndrew Turner case UARTIMSC: 253f3003a0dSAndrew Turner sc->imsc = value & UARTIMSC_MASK; 254f3003a0dSAndrew Turner break; 255f3003a0dSAndrew Turner case UARTRIS: 256f3003a0dSAndrew Turner case UARTMIS: 257f3003a0dSAndrew Turner /* UARTRIS and UARTMIS are read-only registers */ 258f3003a0dSAndrew Turner break; 259f3003a0dSAndrew Turner case UARTICR: 260f3003a0dSAndrew Turner sc->irq_state &= ~value; 261f3003a0dSAndrew Turner break; 262f3003a0dSAndrew Turner default: 263f3003a0dSAndrew Turner /* Ignore writes to unassigned/ID registers */ 264f3003a0dSAndrew Turner break; 265f3003a0dSAndrew Turner } 266f3003a0dSAndrew Turner uart_toggle_intr(sc); 267*e10b9d66SSHENG-YI HONG uart_softc_unlock(sc->backend); 268f3003a0dSAndrew Turner } 269f3003a0dSAndrew Turner 270f3003a0dSAndrew Turner uint32_t 271f3003a0dSAndrew Turner uart_pl011_read(struct uart_pl011_softc *sc, int offset) 272f3003a0dSAndrew Turner { 273f3003a0dSAndrew Turner uint32_t reg; 274f3003a0dSAndrew Turner int fifo_sz; 275f3003a0dSAndrew Turner 276f3003a0dSAndrew Turner reg = 0; 277*e10b9d66SSHENG-YI HONG uart_softc_lock(sc->backend); 278f3003a0dSAndrew Turner switch (offset) { 279f3003a0dSAndrew Turner case UARTDR: 280f3003a0dSAndrew Turner reg = uart_rxfifo_getchar(sc->backend); 281f3003a0dSAndrew Turner /* Deassert the irq if below the trigger level */ 282f3003a0dSAndrew Turner fifo_sz = uart_rxfifo_numchars(sc->backend); 283f3003a0dSAndrew Turner if (fifo_sz < uart_rx_trigger_level(sc)) 284f3003a0dSAndrew Turner sc->irq_state &= ~UARTRXINTR; 285f3003a0dSAndrew Turner if (fifo_sz == 0) 286f3003a0dSAndrew Turner sc->irq_state &= ~UARTRTINTR; 287f3003a0dSAndrew Turner 288f3003a0dSAndrew Turner reg |= sc->rsr << UARTDR_RSR_SHIFT; 289f3003a0dSAndrew Turner 290f3003a0dSAndrew Turner /* After reading from the fifo there is now space in it */ 291f3003a0dSAndrew Turner sc->rsr &= UARTRSR_OE; 292f3003a0dSAndrew Turner break; 293f3003a0dSAndrew Turner case UARTRSR: 294f3003a0dSAndrew Turner /* Any write clears this register */ 295f3003a0dSAndrew Turner reg = sc->rsr; 296f3003a0dSAndrew Turner break; 297f3003a0dSAndrew Turner case UARTFR: 298f3003a0dSAndrew Turner /* Transmit is intstant, so the fifo is always empty */ 299f3003a0dSAndrew Turner reg = UARTFR_TXFE; 300f3003a0dSAndrew Turner 301f3003a0dSAndrew Turner /* Set the receive fifo full/empty flags */ 302f3003a0dSAndrew Turner fifo_sz = uart_rxfifo_numchars(sc->backend); 303f3003a0dSAndrew Turner if (fifo_sz == UART_FIFO_SIZE) 304f3003a0dSAndrew Turner reg |= UARTFR_RXFF; 305f3003a0dSAndrew Turner else if (fifo_sz == 0) 306f3003a0dSAndrew Turner reg |= UARTFR_RXFE; 307f3003a0dSAndrew Turner break; 308f3003a0dSAndrew Turner /* TODO: UARTILPR */ 309f3003a0dSAndrew Turner case UARTIBRD: 310f3003a0dSAndrew Turner reg = sc->ibrd; 311f3003a0dSAndrew Turner break; 312f3003a0dSAndrew Turner case UARTFBRD: 313f3003a0dSAndrew Turner reg = sc->fbrd; 314f3003a0dSAndrew Turner break; 315f3003a0dSAndrew Turner case UARTLCR_H: 316f3003a0dSAndrew Turner reg = sc->lcr_h; 317f3003a0dSAndrew Turner break; 318f3003a0dSAndrew Turner case UARTCR: 319f3003a0dSAndrew Turner reg = sc->cr; 320f3003a0dSAndrew Turner break; 321f3003a0dSAndrew Turner case UARTIMSC: 322f3003a0dSAndrew Turner reg = sc->imsc; 323f3003a0dSAndrew Turner break; 324f3003a0dSAndrew Turner case UARTRIS: 325f3003a0dSAndrew Turner reg = sc->irq_state; 326f3003a0dSAndrew Turner break; 327f3003a0dSAndrew Turner case UARTMIS: 328f3003a0dSAndrew Turner reg = sc->irq_state & sc->imsc; 329f3003a0dSAndrew Turner break; 330f3003a0dSAndrew Turner case UARTICR: 331f3003a0dSAndrew Turner reg = 0; 332f3003a0dSAndrew Turner break; 333f3003a0dSAndrew Turner case UARTPeriphID0: 334f3003a0dSAndrew Turner reg = UARTPeriphID0_VAL; 335f3003a0dSAndrew Turner break; 336f3003a0dSAndrew Turner case UARTPeriphID1: 337f3003a0dSAndrew Turner reg =UARTPeriphID1_VAL; 338f3003a0dSAndrew Turner break; 339f3003a0dSAndrew Turner case UARTPeriphID2: 340f3003a0dSAndrew Turner reg = UARTPeriphID2_VAL; 341f3003a0dSAndrew Turner break; 342f3003a0dSAndrew Turner case UARTPeriphID3: 343f3003a0dSAndrew Turner reg = UARTPeriphID3_VAL; 344f3003a0dSAndrew Turner break; 345f3003a0dSAndrew Turner case UARTPCellID0: 346f3003a0dSAndrew Turner reg = UARTPCellID0_VAL; 347f3003a0dSAndrew Turner break; 348f3003a0dSAndrew Turner case UARTPCellID1: 349f3003a0dSAndrew Turner reg = UARTPCellID1_VAL; 350f3003a0dSAndrew Turner break; 351f3003a0dSAndrew Turner case UARTPCellID2: 352f3003a0dSAndrew Turner reg = UARTPCellID2_VAL; 353f3003a0dSAndrew Turner break; 354f3003a0dSAndrew Turner case UARTPCellID3: 355f3003a0dSAndrew Turner reg = UARTPCellID3_VAL; 356f3003a0dSAndrew Turner break; 357f3003a0dSAndrew Turner default: 358f3003a0dSAndrew Turner /* Return 0 in reads from unasigned registers */ 359f3003a0dSAndrew Turner reg = 0; 360f3003a0dSAndrew Turner break; 361f3003a0dSAndrew Turner } 362f3003a0dSAndrew Turner uart_toggle_intr(sc); 363*e10b9d66SSHENG-YI HONG uart_softc_unlock(sc->backend); 364f3003a0dSAndrew Turner 365f3003a0dSAndrew Turner return (reg); 366f3003a0dSAndrew Turner } 367f3003a0dSAndrew Turner 368f3003a0dSAndrew Turner struct uart_pl011_softc * 369f3003a0dSAndrew Turner uart_pl011_init(uart_intr_func_t intr_assert, uart_intr_func_t intr_deassert, 370f3003a0dSAndrew Turner void *arg) 371f3003a0dSAndrew Turner { 372f3003a0dSAndrew Turner struct uart_pl011_softc *sc; 373f3003a0dSAndrew Turner 374f3003a0dSAndrew Turner sc = calloc(1, sizeof(struct uart_pl011_softc)); 375f3003a0dSAndrew Turner 376f3003a0dSAndrew Turner sc->arg = arg; 377f3003a0dSAndrew Turner sc->intr_assert = intr_assert; 378f3003a0dSAndrew Turner sc->intr_deassert = intr_deassert; 379f3003a0dSAndrew Turner sc->backend = uart_init(); 380f3003a0dSAndrew Turner 381f3003a0dSAndrew Turner uart_reset(sc); 382f3003a0dSAndrew Turner 383f3003a0dSAndrew Turner return (sc); 384f3003a0dSAndrew Turner } 385f3003a0dSAndrew Turner 386f3003a0dSAndrew Turner int 387f3003a0dSAndrew Turner uart_pl011_tty_open(struct uart_pl011_softc *sc, const char *device) 388f3003a0dSAndrew Turner { 389f3003a0dSAndrew Turner return (uart_tty_open(sc->backend, device, uart_drain, sc)); 390f3003a0dSAndrew Turner } 391