Example #1
0
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);
}
Example #2
0
File: sscom.c Project: MarginC/kame
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;
}