1272399Sganbold/*- 2272399Sganbold * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold@freebsd.org> 3272399Sganbold * All rights reserved. 4272399Sganbold * 5272399Sganbold * Redistribution and use in source and binary forms, with or without 6272399Sganbold * modification, are permitted provided that the following conditions 7272399Sganbold * are met: 8272399Sganbold * 9272399Sganbold * 1. Redistributions of source code must retain the above copyright 10272399Sganbold * notice, this list of conditions and the following disclaimer. 11272399Sganbold * 2. Redistributions in binary form must reproduce the above copyright 12272399Sganbold * notice, this list of conditions and the following disclaimer in the 13272399Sganbold * documentation and/or other materials provided with the distribution. 14272399Sganbold * 15272399Sganbold * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16272399Sganbold * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17272399Sganbold * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18272399Sganbold * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19272399Sganbold * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20272399Sganbold * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21272399Sganbold * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22272399Sganbold * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23272399Sganbold * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24272399Sganbold * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25272399Sganbold */ 26272399Sganbold 27272399Sganbold/* Qualcomm MSM7K/8K uart driver */ 28272399Sganbold 29272399Sganbold#include <sys/cdefs.h> 30272399Sganbold__FBSDID("$FreeBSD: releng/11.0/sys/dev/uart/uart_dev_msm.c 297793 2016-04-10 23:07:00Z pfg $"); 31272399Sganbold 32272399Sganbold#include "opt_ddb.h" 33272399Sganbold 34272399Sganbold#include <sys/param.h> 35272399Sganbold#include <sys/systm.h> 36272399Sganbold#include <sys/bus.h> 37272399Sganbold#include <sys/conf.h> 38272399Sganbold#include <sys/kdb.h> 39272399Sganbold#include <machine/bus.h> 40272399Sganbold#include <machine/fdt.h> 41272399Sganbold 42272399Sganbold#include <dev/uart/uart.h> 43272399Sganbold#include <dev/uart/uart_cpu.h> 44279724Sian#include <dev/uart/uart_cpu_fdt.h> 45272399Sganbold#include <dev/uart/uart_bus.h> 46272399Sganbold#include <dev/uart/uart_dev_msm.h> 47272399Sganbold 48272399Sganbold#include "uart_if.h" 49272399Sganbold 50272399Sganbold#define DEF_CLK 7372800 51272399Sganbold 52272399Sganbold#define GETREG(bas, reg) \ 53272399Sganbold bus_space_read_4((bas)->bst, (bas)->bsh, (reg)) 54272399Sganbold#define SETREG(bas, reg, value) \ 55272399Sganbold bus_space_write_4((bas)->bst, (bas)->bsh, (reg), (value)) 56272399Sganbold 57272399Sganboldstatic int msm_uart_param(struct uart_bas *, int, int, int, int); 58272399Sganbold 59272399Sganbold/* 60272399Sganbold * Low-level UART interface. 61272399Sganbold */ 62272399Sganboldstatic int msm_probe(struct uart_bas *bas); 63272399Sganboldstatic void msm_init(struct uart_bas *bas, int, int, int, int); 64272399Sganboldstatic void msm_term(struct uart_bas *bas); 65272399Sganboldstatic void msm_putc(struct uart_bas *bas, int); 66272399Sganboldstatic int msm_rxready(struct uart_bas *bas); 67272399Sganboldstatic int msm_getc(struct uart_bas *bas, struct mtx *mtx); 68272399Sganbold 69272399Sganboldextern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; 70272399Sganbold 71272399Sganboldstatic int 72272399Sganboldmsm_uart_param(struct uart_bas *bas, int baudrate, int databits, 73272399Sganbold int stopbits, int parity) 74272399Sganbold{ 75272399Sganbold int ulcon; 76272399Sganbold 77272399Sganbold ulcon = 0; 78272399Sganbold 79272399Sganbold switch (databits) { 80272399Sganbold case 5: 81272399Sganbold ulcon |= (UART_DM_5_BPS << 4); 82272399Sganbold break; 83272399Sganbold case 6: 84272399Sganbold ulcon |= (UART_DM_6_BPS << 4); 85272399Sganbold break; 86272399Sganbold case 7: 87272399Sganbold ulcon |= (UART_DM_7_BPS << 4); 88272399Sganbold break; 89272399Sganbold case 8: 90272399Sganbold ulcon |= (UART_DM_8_BPS << 4); 91272399Sganbold break; 92272399Sganbold default: 93272399Sganbold return (EINVAL); 94272399Sganbold } 95272399Sganbold 96272399Sganbold switch (parity) { 97272399Sganbold case UART_PARITY_NONE: 98272399Sganbold ulcon |= UART_DM_NO_PARITY; 99272399Sganbold break; 100272399Sganbold case UART_PARITY_ODD: 101272399Sganbold ulcon |= UART_DM_ODD_PARITY; 102272399Sganbold break; 103272399Sganbold case UART_PARITY_EVEN: 104272399Sganbold ulcon |= UART_DM_EVEN_PARITY; 105272399Sganbold break; 106272399Sganbold case UART_PARITY_SPACE: 107272399Sganbold ulcon |= UART_DM_SPACE_PARITY; 108272399Sganbold break; 109272399Sganbold case UART_PARITY_MARK: 110272399Sganbold default: 111272399Sganbold return (EINVAL); 112272399Sganbold } 113272399Sganbold 114272399Sganbold switch (stopbits) { 115272399Sganbold case 1: 116272399Sganbold ulcon |= (UART_DM_SBL_1 << 2); 117272399Sganbold break; 118272399Sganbold case 2: 119272399Sganbold ulcon |= (UART_DM_SBL_2 << 2); 120272399Sganbold break; 121272399Sganbold default: 122272399Sganbold return (EINVAL); 123272399Sganbold } 124272399Sganbold uart_setreg(bas, UART_DM_MR2, ulcon); 125272399Sganbold 126297793Spfg /* Set 115200 for both TX and RX. */ 127272399Sganbold uart_setreg(bas, UART_DM_CSR, UART_DM_CSR_115200); 128272399Sganbold uart_barrier(bas); 129272399Sganbold 130272399Sganbold return (0); 131272399Sganbold} 132272399Sganbold 133272399Sganboldstruct uart_ops uart_msm_ops = { 134272399Sganbold .probe = msm_probe, 135272399Sganbold .init = msm_init, 136272399Sganbold .term = msm_term, 137272399Sganbold .putc = msm_putc, 138272399Sganbold .rxready = msm_rxready, 139272399Sganbold .getc = msm_getc, 140272399Sganbold}; 141272399Sganbold 142272399Sganboldstatic int 143272399Sganboldmsm_probe(struct uart_bas *bas) 144272399Sganbold{ 145272399Sganbold 146272399Sganbold return (0); 147272399Sganbold} 148272399Sganbold 149272399Sganboldstatic void 150272399Sganboldmsm_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, 151272399Sganbold int parity) 152272399Sganbold{ 153272399Sganbold 154272399Sganbold if (bas->rclk == 0) 155272399Sganbold bas->rclk = DEF_CLK; 156272399Sganbold 157272399Sganbold KASSERT(bas->rclk != 0, ("msm_init: Invalid rclk")); 158272399Sganbold 159272399Sganbold /* Set default parameters */ 160272399Sganbold msm_uart_param(bas, baudrate, databits, stopbits, parity); 161272399Sganbold 162272399Sganbold /* 163272399Sganbold * Configure UART mode registers MR1 and MR2. 164272399Sganbold * Hardware flow control isn't supported. 165272399Sganbold */ 166272399Sganbold uart_setreg(bas, UART_DM_MR1, 0x0); 167272399Sganbold 168272399Sganbold /* Reset interrupt mask register. */ 169272399Sganbold uart_setreg(bas, UART_DM_IMR, 0); 170272399Sganbold 171272399Sganbold /* 172272399Sganbold * Configure Tx and Rx watermarks configuration registers. 173272399Sganbold * TX watermark value is set to 0 - interrupt is generated when 174272399Sganbold * FIFO level is less than or equal to 0. 175272399Sganbold */ 176272399Sganbold uart_setreg(bas, UART_DM_TFWR, UART_DM_TFW_VALUE); 177272399Sganbold 178272399Sganbold /* Set RX watermark value */ 179272399Sganbold uart_setreg(bas, UART_DM_RFWR, UART_DM_RFW_VALUE); 180272399Sganbold 181272399Sganbold /* 182272399Sganbold * Configure Interrupt Programming Register. 183272399Sganbold * Set initial Stale timeout value. 184272399Sganbold */ 185272399Sganbold uart_setreg(bas, UART_DM_IPR, UART_DM_STALE_TIMEOUT_LSB); 186272399Sganbold 187272399Sganbold /* Disable IRDA mode */ 188272399Sganbold uart_setreg(bas, UART_DM_IRDA, 0x0); 189272399Sganbold 190272399Sganbold /* 191272399Sganbold * Configure and enable sim interface if required. 192272399Sganbold * Configure hunt character value in HCR register. 193272399Sganbold * Keep it in reset state. 194272399Sganbold */ 195272399Sganbold uart_setreg(bas, UART_DM_HCR, 0x0); 196272399Sganbold 197272399Sganbold /* Issue soft reset command */ 198272399Sganbold SETREG(bas, UART_DM_CR, UART_DM_RESET_TX); 199272399Sganbold SETREG(bas, UART_DM_CR, UART_DM_RESET_RX); 200272399Sganbold SETREG(bas, UART_DM_CR, UART_DM_RESET_ERROR_STATUS); 201272399Sganbold SETREG(bas, UART_DM_CR, UART_DM_RESET_BREAK_INT); 202272399Sganbold SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT); 203272399Sganbold 204272399Sganbold /* Enable/Disable Rx/Tx DM interfaces */ 205272399Sganbold /* Disable Data Mover for now. */ 206272399Sganbold uart_setreg(bas, UART_DM_DMEN, 0x0); 207272399Sganbold 208272399Sganbold /* Enable transmitter and receiver */ 209272399Sganbold uart_setreg(bas, UART_DM_CR, UART_DM_CR_RX_ENABLE); 210272399Sganbold uart_setreg(bas, UART_DM_CR, UART_DM_CR_TX_ENABLE); 211272399Sganbold 212272399Sganbold uart_barrier(bas); 213272399Sganbold} 214272399Sganbold 215272399Sganboldstatic void 216272399Sganboldmsm_term(struct uart_bas *bas) 217272399Sganbold{ 218272399Sganbold 219272399Sganbold /* XXX */ 220272399Sganbold} 221272399Sganbold 222272399Sganboldstatic void 223272399Sganboldmsm_putc(struct uart_bas *bas, int c) 224272399Sganbold{ 225272399Sganbold int limit; 226272399Sganbold 227272399Sganbold /* 228272399Sganbold * Write to NO_CHARS_FOR_TX register the number of characters 229272399Sganbold * to be transmitted. However, before writing TX_FIFO must 230272399Sganbold * be empty as indicated by TX_READY interrupt in IMR register 231272399Sganbold */ 232272399Sganbold 233272399Sganbold /* 234272399Sganbold * Check if transmit FIFO is empty. 235272399Sganbold * If not wait for TX_READY interrupt. 236272399Sganbold */ 237272399Sganbold limit = 1000; 238272399Sganbold if (!(uart_getreg(bas, UART_DM_SR) & UART_DM_SR_TXEMT)) { 239272399Sganbold while ((uart_getreg(bas, UART_DM_ISR) & UART_DM_TX_READY) == 0 240272399Sganbold && --limit) 241272399Sganbold DELAY(4); 242272399Sganbold } 243272399Sganbold /* FIFO is ready, write number of characters to be written */ 244272399Sganbold uart_setreg(bas, UART_DM_NO_CHARS_FOR_TX, 1); 245272399Sganbold 246272399Sganbold /* Wait till TX FIFO has space */ 247272399Sganbold while ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_TXRDY) == 0) 248272399Sganbold DELAY(4); 249272399Sganbold 250272399Sganbold /* TX FIFO has space. Write char */ 251272399Sganbold SETREG(bas, UART_DM_TF(0), (c & 0xff)); 252272399Sganbold} 253272399Sganbold 254272399Sganboldstatic int 255272399Sganboldmsm_rxready(struct uart_bas *bas) 256272399Sganbold{ 257272399Sganbold 258272399Sganbold /* Wait for a character to come ready */ 259272399Sganbold return ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) == 260272399Sganbold UART_DM_SR_RXRDY); 261272399Sganbold} 262272399Sganbold 263272399Sganboldstatic int 264272399Sganboldmsm_getc(struct uart_bas *bas, struct mtx *mtx) 265272399Sganbold{ 266272399Sganbold int c; 267272399Sganbold 268272399Sganbold uart_lock(mtx); 269272399Sganbold 270272399Sganbold /* Wait for a character to come ready */ 271272399Sganbold while ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) != 272272399Sganbold UART_DM_SR_RXRDY) 273272399Sganbold DELAY(4); 274272399Sganbold 275272399Sganbold /* Check for Overrun error. If so reset Error Status */ 276272399Sganbold if (uart_getreg(bas, UART_DM_SR) & UART_DM_SR_UART_OVERRUN) 277272399Sganbold uart_setreg(bas, UART_DM_CR, UART_DM_RESET_ERROR_STATUS); 278272399Sganbold 279272399Sganbold /* Read char */ 280272399Sganbold c = uart_getreg(bas, UART_DM_RF(0)); 281272399Sganbold 282272399Sganbold uart_unlock(mtx); 283272399Sganbold 284272399Sganbold return (c); 285272399Sganbold} 286272399Sganbold 287272399Sganbold/* 288272399Sganbold * High-level UART interface. 289272399Sganbold */ 290272399Sganboldstruct msm_uart_softc { 291272399Sganbold struct uart_softc base; 292272399Sganbold uint32_t ier; 293272399Sganbold}; 294272399Sganbold 295272399Sganboldstatic int msm_bus_probe(struct uart_softc *sc); 296272399Sganboldstatic int msm_bus_attach(struct uart_softc *sc); 297272399Sganboldstatic int msm_bus_flush(struct uart_softc *, int); 298272399Sganboldstatic int msm_bus_getsig(struct uart_softc *); 299272399Sganboldstatic int msm_bus_ioctl(struct uart_softc *, int, intptr_t); 300272399Sganboldstatic int msm_bus_ipend(struct uart_softc *); 301272399Sganboldstatic int msm_bus_param(struct uart_softc *, int, int, int, int); 302272399Sganboldstatic int msm_bus_receive(struct uart_softc *); 303272399Sganboldstatic int msm_bus_setsig(struct uart_softc *, int); 304272399Sganboldstatic int msm_bus_transmit(struct uart_softc *); 305272399Sganboldstatic void msm_bus_grab(struct uart_softc *); 306272399Sganboldstatic void msm_bus_ungrab(struct uart_softc *); 307272399Sganbold 308272399Sganboldstatic kobj_method_t msm_methods[] = { 309272399Sganbold KOBJMETHOD(uart_probe, msm_bus_probe), 310272399Sganbold KOBJMETHOD(uart_attach, msm_bus_attach), 311272399Sganbold KOBJMETHOD(uart_flush, msm_bus_flush), 312272399Sganbold KOBJMETHOD(uart_getsig, msm_bus_getsig), 313272399Sganbold KOBJMETHOD(uart_ioctl, msm_bus_ioctl), 314272399Sganbold KOBJMETHOD(uart_ipend, msm_bus_ipend), 315272399Sganbold KOBJMETHOD(uart_param, msm_bus_param), 316272399Sganbold KOBJMETHOD(uart_receive, msm_bus_receive), 317272399Sganbold KOBJMETHOD(uart_setsig, msm_bus_setsig), 318272399Sganbold KOBJMETHOD(uart_transmit, msm_bus_transmit), 319272399Sganbold KOBJMETHOD(uart_grab, msm_bus_grab), 320272399Sganbold KOBJMETHOD(uart_ungrab, msm_bus_ungrab), 321272399Sganbold {0, 0 } 322272399Sganbold}; 323272399Sganbold 324272399Sganboldint 325272399Sganboldmsm_bus_probe(struct uart_softc *sc) 326272399Sganbold{ 327272399Sganbold 328272399Sganbold sc->sc_txfifosz = 64; 329272399Sganbold sc->sc_rxfifosz = 64; 330272399Sganbold 331272399Sganbold device_set_desc(sc->sc_dev, "Qualcomm HSUART"); 332272399Sganbold 333272399Sganbold return (0); 334272399Sganbold} 335272399Sganbold 336272399Sganboldstatic int 337272399Sganboldmsm_bus_attach(struct uart_softc *sc) 338272399Sganbold{ 339272399Sganbold struct msm_uart_softc *u = (struct msm_uart_softc *)sc; 340272399Sganbold struct uart_bas *bas = &sc->sc_bas; 341272399Sganbold 342272399Sganbold sc->sc_hwiflow = 0; 343272399Sganbold sc->sc_hwoflow = 0; 344272399Sganbold 345272399Sganbold /* Set TX_READY, TXLEV, RXLEV, RXSTALE */ 346272399Sganbold u->ier = UART_DM_IMR_ENABLED; 347272399Sganbold 348272399Sganbold /* Configure Interrupt Mask register IMR */ 349272399Sganbold uart_setreg(bas, UART_DM_IMR, u->ier); 350272399Sganbold 351272399Sganbold return (0); 352272399Sganbold} 353272399Sganbold 354272399Sganbold/* 355272399Sganbold * Write the current transmit buffer to the TX FIFO. 356272399Sganbold */ 357272399Sganboldstatic int 358272399Sganboldmsm_bus_transmit(struct uart_softc *sc) 359272399Sganbold{ 360272399Sganbold struct msm_uart_softc *u = (struct msm_uart_softc *)sc; 361272399Sganbold struct uart_bas *bas = &sc->sc_bas; 362272399Sganbold int i; 363272399Sganbold 364272399Sganbold uart_lock(sc->sc_hwmtx); 365272399Sganbold 366272399Sganbold /* Write some data */ 367272399Sganbold for (i = 0; i < sc->sc_txdatasz; i++) { 368272399Sganbold /* Write TX data */ 369272399Sganbold msm_putc(bas, sc->sc_txbuf[i]); 370272399Sganbold uart_barrier(bas); 371272399Sganbold } 372272399Sganbold 373272399Sganbold /* TX FIFO is empty now, enable TX_READY interrupt */ 374272399Sganbold u->ier |= UART_DM_TX_READY; 375272399Sganbold SETREG(bas, UART_DM_IMR, u->ier); 376272399Sganbold uart_barrier(bas); 377272399Sganbold 378272399Sganbold /* 379272399Sganbold * Inform upper layer that it is transmitting data to hardware, 380272399Sganbold * this will be cleared when TXIDLE interrupt occurs. 381272399Sganbold */ 382272399Sganbold sc->sc_txbusy = 1; 383272399Sganbold uart_unlock(sc->sc_hwmtx); 384272399Sganbold 385272399Sganbold return (0); 386272399Sganbold} 387272399Sganbold 388272399Sganboldstatic int 389272399Sganboldmsm_bus_setsig(struct uart_softc *sc, int sig) 390272399Sganbold{ 391272399Sganbold 392272399Sganbold return (0); 393272399Sganbold} 394272399Sganbold 395272399Sganboldstatic int 396272399Sganboldmsm_bus_receive(struct uart_softc *sc) 397272399Sganbold{ 398272399Sganbold struct msm_uart_softc *u = (struct msm_uart_softc *)sc; 399272399Sganbold struct uart_bas *bas; 400272399Sganbold int c; 401272399Sganbold 402272399Sganbold bas = &sc->sc_bas; 403272399Sganbold uart_lock(sc->sc_hwmtx); 404272399Sganbold 405272399Sganbold /* Initialize Receive Path and interrupt */ 406272399Sganbold SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT); 407272399Sganbold SETREG(bas, UART_DM_CR, UART_DM_STALE_EVENT_ENABLE); 408272399Sganbold u->ier |= UART_DM_RXLEV; 409272399Sganbold SETREG(bas, UART_DM_IMR, u->ier); 410272399Sganbold 411272399Sganbold /* Loop over until we are full, or no data is available */ 412272399Sganbold while (uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) { 413272399Sganbold if (uart_rx_full(sc)) { 414272399Sganbold /* No space left in input buffer */ 415272399Sganbold sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; 416272399Sganbold break; 417272399Sganbold } 418272399Sganbold 419272399Sganbold /* Read RX FIFO */ 420272399Sganbold c = uart_getreg(bas, UART_DM_RF(0)); 421272399Sganbold uart_barrier(bas); 422272399Sganbold 423272399Sganbold uart_rx_put(sc, c); 424272399Sganbold } 425272399Sganbold 426272399Sganbold uart_unlock(sc->sc_hwmtx); 427272399Sganbold 428272399Sganbold return (0); 429272399Sganbold} 430272399Sganbold 431272399Sganboldstatic int 432272399Sganboldmsm_bus_param(struct uart_softc *sc, int baudrate, int databits, 433272399Sganbold int stopbits, int parity) 434272399Sganbold{ 435272399Sganbold int error; 436272399Sganbold 437272399Sganbold if (sc->sc_bas.rclk == 0) 438272399Sganbold sc->sc_bas.rclk = DEF_CLK; 439272399Sganbold 440272399Sganbold KASSERT(sc->sc_bas.rclk != 0, ("msm_init: Invalid rclk")); 441272399Sganbold 442272399Sganbold uart_lock(sc->sc_hwmtx); 443272399Sganbold error = msm_uart_param(&sc->sc_bas, baudrate, databits, stopbits, 444272399Sganbold parity); 445272399Sganbold uart_unlock(sc->sc_hwmtx); 446272399Sganbold 447272399Sganbold return (error); 448272399Sganbold} 449272399Sganbold 450272399Sganboldstatic int 451272399Sganboldmsm_bus_ipend(struct uart_softc *sc) 452272399Sganbold{ 453272399Sganbold struct msm_uart_softc *u = (struct msm_uart_softc *)sc; 454272399Sganbold struct uart_bas *bas = &sc->sc_bas; 455272399Sganbold uint32_t isr; 456272399Sganbold int ipend; 457272399Sganbold 458272399Sganbold uart_lock(sc->sc_hwmtx); 459272399Sganbold 460272399Sganbold /* Get ISR status */ 461272399Sganbold isr = GETREG(bas, UART_DM_MISR); 462272399Sganbold 463272399Sganbold ipend = 0; 464272399Sganbold 465272399Sganbold /* Uart RX starting, notify upper layer */ 466272399Sganbold if (isr & UART_DM_RXLEV) { 467272399Sganbold u->ier &= ~UART_DM_RXLEV; 468272399Sganbold SETREG(bas, UART_DM_IMR, u->ier); 469272399Sganbold uart_barrier(bas); 470272399Sganbold ipend |= SER_INT_RXREADY; 471272399Sganbold } 472272399Sganbold 473272399Sganbold /* Stale RX interrupt */ 474272399Sganbold if (isr & UART_DM_RXSTALE) { 475272399Sganbold /* Disable and reset it */ 476272399Sganbold SETREG(bas, UART_DM_CR, UART_DM_STALE_EVENT_DISABLE); 477272399Sganbold SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT); 478272399Sganbold uart_barrier(bas); 479272399Sganbold ipend |= SER_INT_RXREADY; 480272399Sganbold } 481272399Sganbold 482272399Sganbold /* TX READY interrupt */ 483272399Sganbold if (isr & UART_DM_TX_READY) { 484272399Sganbold /* Clear TX Ready */ 485272399Sganbold SETREG(bas, UART_DM_CR, UART_DM_CLEAR_TX_READY); 486272399Sganbold 487272399Sganbold /* Disable TX_READY */ 488272399Sganbold u->ier &= ~UART_DM_TX_READY; 489272399Sganbold SETREG(bas, UART_DM_IMR, u->ier); 490272399Sganbold uart_barrier(bas); 491272399Sganbold 492272399Sganbold if (sc->sc_txbusy != 0) 493272399Sganbold ipend |= SER_INT_TXIDLE; 494272399Sganbold } 495272399Sganbold 496272399Sganbold if (isr & UART_DM_TXLEV) { 497272399Sganbold /* TX FIFO is empty */ 498272399Sganbold u->ier &= ~UART_DM_TXLEV; 499272399Sganbold SETREG(bas, UART_DM_IMR, u->ier); 500272399Sganbold uart_barrier(bas); 501272399Sganbold 502272399Sganbold if (sc->sc_txbusy != 0) 503272399Sganbold ipend |= SER_INT_TXIDLE; 504272399Sganbold } 505272399Sganbold 506272399Sganbold uart_unlock(sc->sc_hwmtx); 507272399Sganbold return (ipend); 508272399Sganbold} 509272399Sganbold 510272399Sganboldstatic int 511272399Sganboldmsm_bus_flush(struct uart_softc *sc, int what) 512272399Sganbold{ 513272399Sganbold 514272399Sganbold return (0); 515272399Sganbold} 516272399Sganbold 517272399Sganboldstatic int 518272399Sganboldmsm_bus_getsig(struct uart_softc *sc) 519272399Sganbold{ 520272399Sganbold 521272399Sganbold return (0); 522272399Sganbold} 523272399Sganbold 524272399Sganboldstatic int 525272399Sganboldmsm_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 526272399Sganbold{ 527272399Sganbold 528272399Sganbold return (EINVAL); 529272399Sganbold} 530272399Sganbold 531272399Sganboldstatic void 532272399Sganboldmsm_bus_grab(struct uart_softc *sc) 533272399Sganbold{ 534272399Sganbold struct uart_bas *bas = &sc->sc_bas; 535272399Sganbold 536272399Sganbold /* 537272399Sganbold * XXX: Turn off all interrupts to enter polling mode. Leave the 538272399Sganbold * saved mask alone. We'll restore whatever it was in ungrab. 539272399Sganbold */ 540272399Sganbold uart_lock(sc->sc_hwmtx); 541272399Sganbold SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT); 542272399Sganbold SETREG(bas, UART_DM_IMR, 0); 543272399Sganbold uart_barrier(bas); 544272399Sganbold uart_unlock(sc->sc_hwmtx); 545272399Sganbold} 546272399Sganbold 547272399Sganboldstatic void 548272399Sganboldmsm_bus_ungrab(struct uart_softc *sc) 549272399Sganbold{ 550272399Sganbold struct msm_uart_softc *u = (struct msm_uart_softc *)sc; 551272399Sganbold struct uart_bas *bas = &sc->sc_bas; 552272399Sganbold 553272399Sganbold /* 554272399Sganbold * Restore previous interrupt mask 555272399Sganbold */ 556272399Sganbold uart_lock(sc->sc_hwmtx); 557272399Sganbold SETREG(bas, UART_DM_IMR, u->ier); 558272399Sganbold uart_barrier(bas); 559272399Sganbold uart_unlock(sc->sc_hwmtx); 560272399Sganbold} 561272399Sganbold 562279724Sianstatic struct uart_class uart_msm_class = { 563272399Sganbold "msm", 564272399Sganbold msm_methods, 565272399Sganbold sizeof(struct msm_uart_softc), 566272399Sganbold .uc_ops = &uart_msm_ops, 567272399Sganbold .uc_range = 8, 568272399Sganbold .uc_rclk = DEF_CLK, 569281438Sandrew .uc_rshift = 0 570272399Sganbold}; 571279724Sian 572279724Sianstatic struct ofw_compat_data compat_data[] = { 573279724Sian {"qcom,msm-uartdm", (uintptr_t)&uart_msm_class}, 574279724Sian {NULL, (uintptr_t)NULL}, 575279724Sian}; 576279724SianUART_FDT_CLASS_AND_DEVICE(compat_data); 577