static int ns8250_param(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity) { int divisor; uint8_t lcr; lcr = 0; if (databits >= 8) lcr |= LCR_8BITS; else if (databits == 7) lcr |= LCR_7BITS; else if (databits == 6) lcr |= LCR_6BITS; else lcr |= LCR_5BITS; if (stopbits > 1) lcr |= LCR_STOPB; lcr |= parity << 3; /* Set baudrate. */ if (baudrate > 0) { divisor = ns8250_divisor(bas->rclk, baudrate); if (divisor == 0) return (EINVAL); uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); uart_barrier(bas); uart_setreg(bas, REG_DLL, divisor & 0xff); uart_setreg(bas, REG_DLH, (divisor >> 8) & 0xff); uart_barrier(bas); }
static int oct16550_delay (struct uart_bas *bas) { int divisor; u_char lcr; static int delay = 0; if (!delay_changed) return delay; delay_changed = 0; lcr = uart_getreg(bas, REG_LCR); uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); uart_barrier(bas); divisor = uart_getreg(bas, REG_DLL) | (uart_getreg(bas, REG_DLH) << 8); uart_barrier(bas); uart_setreg(bas, REG_LCR, lcr); uart_barrier(bas); if(!bas->rclk) return 10; /* return an approx delay value */ /* 1/10th the time to transmit 1 character (estimate). */ if (divisor <= 134) return (16000000 * divisor / bas->rclk); return (16000 * divisor / (bas->rclk / 1000)); }
static int sa1110_bus_transmit(struct uart_softc *sc) { int i; #if 0 int sr = uart_getreg(&sc->sc_bas, SACOM_SR0); while (!(uart_getreg(&sc->sc_bas, SACOM_CR3) & CR3_TIE)) uart_setreg(&sc->sc_bas, SACOM_CR3, uart_getreg(&sc->sc_bas, SACOM_CR3) | CR3_TIE); #endif sc->sc_txbusy = 1; uart_setreg(&sc->sc_bas, SACOM_CR3, uart_getreg(&sc->sc_bas, SACOM_CR3) | CR3_TIE); for (i = 0; i < sc->sc_txdatasz; i++) { while (!(uart_getreg(&sc->sc_bas, SACOM_SR1) & SR1_TNF)); uart_setreg(&sc->sc_bas, SACOM_DR, sc->sc_txbuf[i]); uart_barrier(&sc->sc_bas); } #if 0 sr = uart_getreg(&sc->sc_bas, SACOM_SR0); #endif return (0); }
/* Multiplexed I/O. */ static __inline void uart_setmreg(struct uart_bas *bas, int reg, int val) { uart_setreg(bas, REG_CTRL, reg); uart_barrier(bas); uart_setreg(bas, REG_CTRL, val); }
static int s3c24x0_uart_param(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity) { int brd, ulcon; ulcon = 0; switch(databits) { case 5: ulcon |= ULCON_LENGTH_5; break; case 6: ulcon |= ULCON_LENGTH_6; break; case 7: ulcon |= ULCON_LENGTH_7; break; case 8: ulcon |= ULCON_LENGTH_8; break; default: return (EINVAL); } switch (parity) { case UART_PARITY_NONE: ulcon |= ULCON_PARITY_NONE; break; case UART_PARITY_ODD: ulcon |= ULCON_PARITY_ODD; break; case UART_PARITY_EVEN: ulcon |= ULCON_PARITY_EVEN; break; case UART_PARITY_MARK: case UART_PARITY_SPACE: default: return (EINVAL); } if (stopbits == 2) ulcon |= ULCON_STOP; uart_setreg(bas, SSCOM_ULCON, ulcon); brd = sscomspeed(baudrate, bas->rclk); uart_setreg(bas, SSCOM_UBRDIV, brd); return (0); }
static void tegra_uart_ungrab(struct uart_softc *sc) { struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc; struct uart_bas *bas = &sc->sc_bas; /* * Restore previous interrupt mask */ uart_lock(sc->sc_hwmtx); uart_setreg(bas, REG_FCR, ns8250->fcr); uart_setreg(bas, REG_IER, ns8250->ier); uart_barrier(bas); uart_unlock(sc->sc_hwmtx); }
static void sa1110_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity) { int brd; if (bas->rclk == 0) bas->rclk = DEFAULT_RCLK; while (uart_getreg(bas, SACOM_SR1) & SR1_TBY); uart_setreg(bas, SACOM_CR3, 0); brd = SACOMSPEED(baudrate); uart_setreg(bas, SACOM_CR1, brd >> 8); uart_setreg(bas, SACOM_CR2, brd & 0xff); uart_setreg(bas, SACOM_CR3, CR3_RXE | CR3_TXE); }
static void msm_putc(struct uart_bas *bas, int c) { int limit; /* * Write to NO_CHARS_FOR_TX register the number of characters * to be transmitted. However, before writing TX_FIFO must * be empty as indicated by TX_READY interrupt in IMR register */ /* * Check if transmit FIFO is empty. * If not wait for TX_READY interrupt. */ limit = 1000; if (!(uart_getreg(bas, UART_DM_SR) & UART_DM_SR_TXEMT)) { while ((uart_getreg(bas, UART_DM_ISR) & UART_DM_TX_READY) == 0 && --limit) DELAY(4); } /* FIFO is ready, write number of characters to be written */ uart_setreg(bas, UART_DM_NO_CHARS_FOR_TX, 1); /* Wait till TX FIFO has space */ while ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_TXRDY) == 0) DELAY(4); /* TX FIFO has space. Write char */ SETREG(bas, UART_DM_TF(0), (c & 0xff)); }
static int ti8250_bus_probe(struct uart_softc *sc) { int status; int devid; clk_ident_t clkid; pcell_t prop; phandle_t node; /* * Get the device id from FDT. If it's not there we can't turn on the * right clocks, so bail, unless we're doing unit 0. We assume that's * the serial console, whose clock isn't controllable anyway, and we * sure don't want to break the console because of a config error. */ node = ofw_bus_get_node(sc->sc_dev); if ((OF_getprop(node, "uart-device-id", &prop, sizeof(prop))) <= 0) { device_printf(sc->sc_dev, "missing uart-device-id attribute in FDT\n"); if (device_get_unit(sc->sc_dev) != 0) return (ENXIO); devid = 0; } else devid = fdt32_to_cpu(prop); /* Enable clocks for this device. We can't continue if that fails. */ clkid = UART0_CLK + devid; if ((status = ti_prcm_clk_enable(clkid)) != 0) return (status); /* * Set the hardware to disabled mode, do a full device reset, then set * it to uart mode. Most devices will be reset-and-disabled already, * but you never know what a bootloader might have done. */ uart_setreg(&sc->sc_bas, MDR1_REG, MDR1_MODE_DISABLE); uart_setreg(&sc->sc_bas, SYSCC_REG, SYSCC_SOFTRESET); while (uart_getreg(&sc->sc_bas, SYSS_REG) & SYSS_STATUS_RESETDONE) continue; uart_setreg(&sc->sc_bas, MDR1_REG, MDR1_MODE_UART); status = ns8250_bus_probe(sc); if (status == 0) device_set_desc(sc->sc_dev, "TI UART (16550 compatible)"); return (status); }
static __inline uint8_t uart_getmreg(struct uart_bas *bas, int reg) { uart_setreg(bas, REG_CTRL, reg); uart_barrier(bas); return (uart_getreg(bas, REG_CTRL)); }
static void vf_uart_putc(struct uart_bas *bas, int c) { while (!(uart_getreg(bas, UART_S1) & UART_S1_TDRE)) ; uart_setreg(bas, UART_D, c); }
static int sa1110_bus_attach(struct uart_softc *sc) { bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); sc->sc_hwiflow = 0; uart_setreg(&sc->sc_bas, SACOM_CR3, CR3_RXE | CR3_TXE | CR3_RIE | CR3_TIE); return (0); }
static void s3c2410_putc(struct uart_bas *bas, int c) { while ((bus_space_read_4(bas->bst, bas->bsh, SSCOM_UFSTAT) & UFSTAT_TXFULL) == UFSTAT_TXFULL) continue; uart_setreg(bas, SSCOM_UTXH, c); }
static int sa1110_getc(struct uart_bas *bas, struct mtx *mtx) { int c; while (!(uart_getreg(bas, SACOM_SR1) & SR1_RNE)) { u_int32_t sr0; sr0 = uart_getreg(bas, SACOM_SR0); if (ISSET(sr0, SR0_RBB)) uart_setreg(bas, SACOM_SR0, SR0_RBB); if (ISSET(sr0, SR0_REB)) uart_setreg(bas, SACOM_SR0, SR0_REB); } c = uart_getreg(bas, SACOM_DR); c &= 0xff; return (c); }
static int ns8250_delay(struct uart_bas *bas) { int divisor; u_char lcr; lcr = uart_getreg(bas, REG_LCR); uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); uart_barrier(bas); divisor = uart_getreg(bas, REG_DLL) | (uart_getreg(bas, REG_DLH) << 8); uart_barrier(bas); uart_setreg(bas, REG_LCR, lcr); uart_barrier(bas); /* 1/10th the time to transmit 1 character (estimate). */ if (divisor <= 134) return (16000000 * divisor / bas->rclk); return (16000 * divisor / (bas->rclk / 1000)); }
static void tegra_uart_grab(struct uart_softc *sc) { struct uart_bas *bas = &sc->sc_bas; struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc; u_char ier; /* * turn off all interrupts to enter polling mode. Leave the * saved mask alone. We'll restore whatever it was in ungrab. * All pending interrupt signals are reset when IER is set to 0. */ uart_lock(sc->sc_hwmtx); ier = uart_getreg(bas, REG_IER); uart_setreg(bas, REG_IER, ier & ns8250->ier_mask); uart_setreg(bas, REG_FCR, 0); uart_barrier(bas); uart_unlock(sc->sc_hwmtx); }
static int sa1110_bus_param(struct uart_softc *sc, int baudrate, int databits, int stopbits, int parity) { int brd; if (baudrate > 0) { brd = SACOMSPEED(baudrate); uart_setreg(&sc->sc_bas, SACOM_CR1, brd >> 8); uart_setreg(&sc->sc_bas, SACOM_CR2, brd & 0xff); }
static void mtk_uart_putc(struct uart_bas *bas, int c) { char chr; if (!uart_output) return; chr = c; while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_THRE)); uart_setreg(bas, UART_TX_REG, c); uart_barrier(bas); while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_THRE)); }
static void s3c2410_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity) { if (bas->rclk == 0) bas->rclk = s3c2410_pclk; KASSERT(bas->rclk != 0, ("s3c2410_init: Invalid rclk")); uart_setreg(bas, SSCOM_UCON, 0); uart_setreg(bas, SSCOM_UFCON, UFCON_TXTRIGGER_8 | UFCON_RXTRIGGER_8 | UFCON_TXFIFO_RESET | UFCON_RXFIFO_RESET | UFCON_FIFO_ENABLE); s3c24x0_uart_param(bas, baudrate, databits, stopbits, parity); /* Enable UART. */ uart_setreg(bas, SSCOM_UCON, UCON_TXMODE_INT | UCON_RXMODE_INT | UCON_TOINT); uart_setreg(bas, SSCOM_UMCON, UMCON_RTS); }
static void mtk_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity) { /* CLKDIV = 384000000/ 3/ 16/ br */ /* for 384MHz CLKDIV = 8000000 / baudrate; */ switch (databits) { case 5: databits = UART_LCR_5B; break; case 6: databits = UART_LCR_6B; break; case 7: databits = UART_LCR_7B; break; case 8: databits = UART_LCR_8B; break; default: /* Unsupported */ return; } switch (parity) { case UART_PARITY_EVEN: parity = (UART_LCR_PEN|UART_LCR_EVEN); break; case UART_PARITY_ODD: parity = (UART_LCR_PEN); break; case UART_PARITY_NONE: parity = 0; break; /* Unsupported */ default: return; } if (bas->rclk && baudrate) { uart_setreg(bas, UART_CDDL_REG, bas->rclk/16/baudrate); uart_barrier(bas); } uart_setreg(bas, UART_LCR_REG, databits | (stopbits==1?0:UART_LCR_STB_15) | parity); uart_barrier(bas); }
static void adm5120_uart_putc(struct uart_bas *bas, int c) { char chr; chr = c; while (uart_getreg(bas, UART_FR_REG) & UART_FR_TX_FIFO_FULL) ; uart_setreg(bas, UART_DR_REG, c); while (uart_getreg(bas, UART_FR_REG) & UART_FR_BUSY) ; uart_barrier(bas); }
static int sa1110_bus_receive(struct uart_softc *sc) { #if 0 while (!(uart_getreg(&sc->sc_bas, SACOM_SR1) & SR1_RNE)) { u_int32_t sr0; sr0 = uart_getreg(&sc->sc_bas, SACOM_SR0); if (ISSET(sr0, SR0_RBB)) uart_setreg(&sc->sc_bas, SACOM_SR0, SR0_RBB); if (ISSET(sr0, SR0_REB)) uart_setreg(&sc->sc_bas, SACOM_SR0, SR0_REB); } #endif uart_setreg(&sc->sc_bas, SACOM_CR3, uart_getreg(&sc->sc_bas, SACOM_CR3) | CR3_RIE); uart_rx_put(sc, uart_getreg(&sc->sc_bas, SACOM_DR)); return (0); }
/* * We can only flush UARTs with FIFOs. UARTs without FIFOs should be * drained. WARNING: this function clobbers the FIFO setting! */ static void ns8250_flush(struct uart_bas *bas, int what) { uint8_t fcr; fcr = FCR_ENABLE; if (what & UART_FLUSH_TRANSMITTER) fcr |= FCR_XMT_RST; if (what & UART_FLUSH_RECEIVER) fcr |= FCR_RCV_RST; uart_setreg(bas, REG_FCR, fcr); uart_barrier(bas); }
static int msm_bus_attach(struct uart_softc *sc) { struct msm_uart_softc *u = (struct msm_uart_softc *)sc; struct uart_bas *bas = &sc->sc_bas; sc->sc_hwiflow = 0; sc->sc_hwoflow = 0; /* Set TX_READY, TXLEV, RXLEV, RXSTALE */ u->ier = UART_DM_IMR_ENABLED; /* Configure Interrupt Mask register IMR */ uart_setreg(bas, UART_DM_IMR, u->ier); return (0); }
/* * UART class interface. */ static int tegra_uart_attach(struct uart_softc *sc) { int rv; struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc; struct uart_bas *bas = &sc->sc_bas; rv = ns8250_bus_attach(sc); if (rv != 0) return (rv); ns8250->ier_rxbits = 0x1d; ns8250->ier_mask = 0xc0; ns8250->ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask; ns8250->ier = ns8250->ier_rxbits; uart_setreg(bas, REG_IER, ns8250->ier); uart_barrier(bas); return (0); }
static int msm_getc(struct uart_bas *bas, struct mtx *mtx) { int c; uart_lock(mtx); /* Wait for a character to come ready */ while ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) != UART_DM_SR_RXRDY) DELAY(4); /* Check for Overrun error. If so reset Error Status */ if (uart_getreg(bas, UART_DM_SR) & UART_DM_SR_UART_OVERRUN) uart_setreg(bas, UART_DM_CR, UART_DM_RESET_ERROR_STATUS); /* Read char */ c = uart_getreg(bas, UART_DM_RF(0)); uart_unlock(mtx); return (c); }
static int jz4780_bus_attach(struct uart_softc *sc) { struct ns8250_softc *ns8250; struct uart_bas *bas; int rv; ns8250 = (struct ns8250_softc *)sc; bas = &sc->sc_bas; rv = ns8250_bus_attach(sc); if (rv != 0) return (0); /* Configure uart to use extra IER_RXTMOUT bit */ ns8250->ier_rxbits = IER_RXTMOUT | IER_EMSC | IER_ERLS | IER_ERXRDY; ns8250->ier_mask = ~(ns8250->ier_rxbits); ns8250->ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask; ns8250->ier |= ns8250->ier_rxbits; uart_setreg(bas, REG_IER, ns8250->ier); uart_barrier(bas); return (0); }
static void msm_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity) { if (bas->rclk == 0) bas->rclk = DEF_CLK; KASSERT(bas->rclk != 0, ("msm_init: Invalid rclk")); /* Set default parameters */ msm_uart_param(bas, baudrate, databits, stopbits, parity); /* * Configure UART mode registers MR1 and MR2. * Hardware flow control isn't supported. */ uart_setreg(bas, UART_DM_MR1, 0x0); /* Reset interrupt mask register. */ uart_setreg(bas, UART_DM_IMR, 0); /* * Configure Tx and Rx watermarks configuration registers. * TX watermark value is set to 0 - interrupt is generated when * FIFO level is less than or equal to 0. */ uart_setreg(bas, UART_DM_TFWR, UART_DM_TFW_VALUE); /* Set RX watermark value */ uart_setreg(bas, UART_DM_RFWR, UART_DM_RFW_VALUE); /* * Configure Interrupt Programming Register. * Set initial Stale timeout value. */ uart_setreg(bas, UART_DM_IPR, UART_DM_STALE_TIMEOUT_LSB); /* Disable IRDA mode */ uart_setreg(bas, UART_DM_IRDA, 0x0); /* * Configure and enable sim interface if required. * Configure hunt character value in HCR register. * Keep it in reset state. */ uart_setreg(bas, UART_DM_HCR, 0x0); /* Issue soft reset command */ SETREG(bas, UART_DM_CR, UART_DM_RESET_TX); SETREG(bas, UART_DM_CR, UART_DM_RESET_RX); SETREG(bas, UART_DM_CR, UART_DM_RESET_ERROR_STATUS); SETREG(bas, UART_DM_CR, UART_DM_RESET_BREAK_INT); SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT); /* Enable/Disable Rx/Tx DM interfaces */ /* Disable Data Mover for now. */ uart_setreg(bas, UART_DM_DMEN, 0x0); /* Enable transmitter and receiver */ uart_setreg(bas, UART_DM_CR, UART_DM_CR_RX_ENABLE); uart_setreg(bas, UART_DM_CR, UART_DM_CR_TX_ENABLE); uart_barrier(bas); }
static void sa1110_putc(struct uart_bas *bas, int c) { while (!(uart_getreg(bas, SACOM_SR1) & SR1_TNF)); uart_setreg(bas, SACOM_DR, c); }
static int msm_uart_param(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity) { int ulcon; ulcon = 0; switch (databits) { case 5: ulcon |= (UART_DM_5_BPS << 4); break; case 6: ulcon |= (UART_DM_6_BPS << 4); break; case 7: ulcon |= (UART_DM_7_BPS << 4); break; case 8: ulcon |= (UART_DM_8_BPS << 4); break; default: return (EINVAL); } switch (parity) { case UART_PARITY_NONE: ulcon |= UART_DM_NO_PARITY; break; case UART_PARITY_ODD: ulcon |= UART_DM_ODD_PARITY; break; case UART_PARITY_EVEN: ulcon |= UART_DM_EVEN_PARITY; break; case UART_PARITY_SPACE: ulcon |= UART_DM_SPACE_PARITY; break; case UART_PARITY_MARK: default: return (EINVAL); } switch (stopbits) { case 1: ulcon |= (UART_DM_SBL_1 << 2); break; case 2: ulcon |= (UART_DM_SBL_2 << 2); break; default: return (EINVAL); } uart_setreg(bas, UART_DM_MR2, ulcon); /* Set 115200 for both TX and RX. */; uart_setreg(bas, UART_DM_CSR, UART_DM_CSR_115200); uart_barrier(bas); return (0); }