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); }
void cons_init(void) { int rate; OUTW(SSCOM_UCON, 0); OUTB(SSCOM_UFCON, UFCON_TXTRIGGER_8 | UFCON_RXTRIGGER_8 | UFCON_TXFIFO_RESET | UFCON_RXFIFO_RESET | UFCON_FIFO_ENABLE); rate = sscomspeed(CONSPEED); OUTW(SSCOM_UBRDIV, rate); OUTW(SSCOM_ULCON, ULCON_PARITY_NONE|ULCON_LENGTH_8); /* enable UART */ OUTW(SSCOM_UCON, UCON_TXMODE_INT|UCON_RXMODE_INT); OUTW(SSCOM_UMCON, UMCON_RTS); }
/* * Initialize UART for use as console or KGDB line. */ static int sscom_init(bus_space_tag_t iot, bus_space_handle_t base_ioh, const struct sscom_uart_info *config, int rate, int frequency, tcflag_t cflag, bus_space_handle_t *iohp) { bus_space_handle_t ioh; bus_addr_t iobase = config->iobase; int timo = 150000; bus_space_subregion(iot, base_ioh, iobase, SSCOM_SIZE, &ioh); /* wait until all is transmitted until we enable this device */ while (!(bus_space_read_4(iot, ioh, SSCOM_UTRSTAT) & UTRSTAT_TXSHIFTER_EMPTY) && --timo); /* reset UART control */ bus_space_write_4(iot, ioh, SSCOM_UCON, 0); /* set RX/TX trigger to half values */ bus_space_write_4(iot, ioh, SSCOM_UFCON, __SHIFTIN(4, UFCON_TXTRIGGER) | __SHIFTIN(4, UFCON_RXTRIGGER) | UFCON_FIFO_ENABLE | UFCON_TXFIFO_RESET| UFCON_RXFIFO_RESET); /* tx/rx fifo reset are auto-cleared */ rate = sscomspeed(rate, frequency); bus_space_write_4(iot, ioh, SSCOM_UBRDIV, rate); bus_space_write_4(iot, ioh, SSCOM_ULCON, cflag2lcr(cflag)); /* enable UART */ bus_space_write_4(iot, ioh, SSCOM_UCON, UCON_TXMODE_INT|UCON_RXMODE_INT); bus_space_write_4(iot, ioh, SSCOM_UMCON, UMCON_RTS); *iohp = ioh; return 0; }
int sscomparam(struct tty *tp, struct termios *t) { struct sscom_softc *sc = device_lookup_private(&sscom_cd, SSCOMUNIT(tp->t_dev)); int ospeed; u_char lcr; int s; if (SSCOM_ISALIVE(sc) == 0) return EIO; ospeed = sscomspeed(t->c_ospeed, sc->sc_frequency); /* Check requested parameters. */ if (ospeed < 0) return EINVAL; if (t->c_ispeed && t->c_ispeed != t->c_ospeed) return EINVAL; /* * For the console, always force CLOCAL and !HUPCL, so that the port * is always active. */ if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || ISSET(sc->sc_hwflags, SSCOM_HW_CONSOLE)) { SET(t->c_cflag, CLOCAL); CLR(t->c_cflag, HUPCL); } /* * If there were no changes, don't do anything. This avoids dropping * input and improves performance when all we did was frob things like * VMIN and VTIME. */ if (tp->t_ospeed == t->c_ospeed && tp->t_cflag == t->c_cflag) return 0; lcr = cflag2lcr(t->c_cflag); s = splserial(); SSCOM_LOCK(sc); sc->sc_ulcon = lcr; /* * If we're not in a mode that assumes a connection is present, then * ignore carrier changes. */ if (ISSET(t->c_cflag, CLOCAL | MDMBUF)) sc->sc_msr_dcd = 0; else sc->sc_msr_dcd = MSTS_DCD; /* * Set the flow control pins depending on the current flow control * mode. */ if (ISSET(t->c_cflag, CRTSCTS)) { sc->sc_mcr_dtr = UMCON_DTR; sc->sc_mcr_rts = UMCON_RTS; sc->sc_msr_cts = MSTS_CTS; } else if (ISSET(t->c_cflag, MDMBUF)) { /* * For DTR/DCD flow control, make sure we don't toggle DTR for * carrier detection. */ sc->sc_mcr_dtr = 0; sc->sc_mcr_rts = UMCON_DTR; sc->sc_msr_cts = MSTS_DCD; } else { /* * If no flow control, then always set RTS. This will make * the other side happy if it mistakenly thinks we're doing * RTS/CTS flow control. */ sc->sc_mcr_dtr = UMCON_DTR | UMCON_RTS; sc->sc_mcr_rts = 0; sc->sc_msr_cts = 0; if (ISSET(sc->sc_umcon, UMCON_DTR)) SET(sc->sc_umcon, UMCON_RTS); else CLR(sc->sc_umcon, UMCON_RTS); } sc->sc_msr_mask = sc->sc_msr_cts | sc->sc_msr_dcd; if (ospeed == 0) CLR(sc->sc_umcon, sc->sc_mcr_dtr); else SET(sc->sc_umcon, sc->sc_mcr_dtr); sc->sc_ubrdiv = ospeed; /* And copy to tty. */ tp->t_ispeed = 0; tp->t_ospeed = t->c_ospeed; tp->t_cflag = t->c_cflag; if (!sc->sc_heldchange) { if (sc->sc_tx_busy) { sc->sc_heldtbc = sc->sc_tbc; sc->sc_tbc = 0; sc->sc_heldchange = 1; } else sscom_loadchannelregs(sc); } if (!ISSET(t->c_cflag, CHWFLOW)) { /* Disable the high water mark. */ sc->sc_r_hiwat = 0; sc->sc_r_lowat = 0; if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) { CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED); sscom_schedrx(sc); } if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) { CLR(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED); sscom_hwiflow(sc); } } else { sc->sc_r_hiwat = sscom_rbuf_hiwat; sc->sc_r_lowat = sscom_rbuf_lowat; } SSCOM_UNLOCK(sc); splx(s); /* * Update the tty layer's idea of the carrier bit, in case we changed * CLOCAL or MDMBUF. We don't hang up here; we only do that by * explicit request. */ (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msts, MSTS_DCD)); if (sscom_debug) sscomstatus(sc, "sscomparam "); if (!ISSET(t->c_cflag, CHWFLOW)) { if (sc->sc_tx_stopped) { sc->sc_tx_stopped = 0; sscomstart(tp); } } return 0; }