static void leonuart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int cr; unsigned long flags; unsigned int baud, quot; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); if (baud == 0) { panic("invalid baudrate %i\n", port->uartclk / 16); } quot = (uart_get_divisor(port, baud)) * 2; //uart_get_divisor calc a *16 uart freq, leon is *8 cr = UART_GET_CTRL(port); cr &= ~(LEON_REG_UART_CTRL_PE | LEON_REG_UART_CTRL_PS); if (termios->c_cflag & PARENB) { cr |= LEON_REG_UART_CTRL_PE; if ((termios->c_cflag & PARODD)) cr |= LEON_REG_UART_CTRL_PS; } /* * Enable flow control. */ if (termios->c_cflag & CRTSCTS) { cr |= LEON_REG_UART_CTRL_FL; } spin_lock_irqsave(&port->lock, flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); port->read_status_mask = LEON_REG_UART_STATUS_OE; if (termios->c_iflag & INPCK) port->read_status_mask |= LEON_REG_UART_STATUS_FE | LEON_REG_UART_STATUS_PE; /* * Characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= LEON_REG_UART_STATUS_FE | LEON_REG_UART_STATUS_PE; /* * Ignore all characters if CREAD is not set. */ if ((termios->c_cflag & CREAD) == 0) { port->ignore_status_mask |= UART_DUMMY_RSR_RX; } /* Set baud rate */ quot -= 1; UART_PUT_SCAL(port, quot); UART_PUT_CTRL(port, cr); spin_unlock_irqrestore(&port->lock, flags); }
static void cpm_uart_set_termios(struct uart_port *port, struct termios *termios, struct termios *old) { int baud; unsigned long flags; u16 cval, scval, prev_mode; int bits, sbits; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; volatile smc_t *smcp = pinfo->smcp; volatile scc_t *sccp = pinfo->sccp; pr_debug("CPM uart[%d]:set_termios\n", port->line); baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); /* Character length programmed into the mode register is the * sum of: 1 start bit, number of data bits, 0 or 1 parity bit, * 1 or 2 stop bits, minus 1. * The value 'bits' counts this for us. */ cval = 0; scval = 0; /* byte size */ switch (termios->c_cflag & CSIZE) { case CS5: bits = 5; break; case CS6: bits = 6; break; case CS7: bits = 7; break; case CS8: bits = 8; break; /* Never happens, but GCC is too dumb to figure it out */ default: bits = 8; break; } sbits = bits - 5; if (termios->c_cflag & CSTOPB) { cval |= SMCMR_SL; /* Two stops */ scval |= SCU_PSMR_SL; bits++; } if (termios->c_cflag & PARENB) { cval |= SMCMR_PEN; scval |= SCU_PSMR_PEN; bits++; if (!(termios->c_cflag & PARODD)) { cval |= SMCMR_PM_EVEN; scval |= (SCU_PSMR_REVP | SCU_PSMR_TEVP); } } /* * Set up parity check flag */ #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) port->read_status_mask = (BD_SC_EMPTY | BD_SC_OV); if (termios->c_iflag & INPCK) port->read_status_mask |= BD_SC_FR | BD_SC_PR; if ((termios->c_iflag & BRKINT) || (termios->c_iflag & PARMRK)) port->read_status_mask |= BD_SC_BR; /* * Characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= BD_SC_PR | BD_SC_FR; if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= BD_SC_BR; /* * If we're ignore parity and break indicators, ignore * overruns too. (For real raw support). */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= BD_SC_OV; } /* * !!! ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) port->read_status_mask &= ~BD_SC_EMPTY; spin_lock_irqsave(&port->lock, flags); /* Start bit has not been added (so don't, because we would just * subtract it later), and we need to add one for the number of * stops bits (there is always at least one). */ bits++; if (IS_SMC(pinfo)) { /* Set the mode register. We want to keep a copy of the * enables, because we want to put them back if they were * present. */ prev_mode = smcp->smc_smcmr; smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART; smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN)); } else { sccp->scc_psmr = (sbits << 12) | scval; } cpm_set_brg(pinfo->brg - 1, baud); spin_unlock_irqrestore(&port->lock, flags); }
/* * Change the port parameters */ static void at91_set_termios(struct uart_port *port, struct termios * termios, struct termios * old) { unsigned long flags; unsigned int mode, imr, quot, baud; baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); /* Get current mode register */ mode = UART_GET_MR(port) & ~(AT91_US_CHRL | AT91_US_NBSTOP | AT91_US_PAR); /* byte size */ switch (termios->c_cflag & CSIZE) { case CS5: mode |= AT91_US_CHRL_5; break; case CS6: mode |= AT91_US_CHRL_6; break; case CS7: mode |= AT91_US_CHRL_7; break; default: mode |= AT91_US_CHRL_8; break; } /* stop bits */ if (termios->c_cflag & CSTOPB) mode |= AT91_US_NBSTOP_2; /* parity */ if (termios->c_cflag & PARENB) { if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */ if (termios->c_cflag & PARODD) mode |= AT91_US_PAR_MARK; else mode |= AT91_US_PAR_SPACE; } else if (termios->c_cflag & PARODD) mode |= AT91_US_PAR_ODD; else mode |= AT91_US_PAR_EVEN; } else mode |= AT91_US_PAR_NONE; spin_lock_irqsave(&port->lock, flags); port->read_status_mask |= AT91_US_OVRE; if (termios->c_iflag & INPCK) port->read_status_mask |= AT91_US_FRAME | AT91_US_PARE; if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= AT91_US_RXBRK; /* * Characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= (AT91_US_FRAME | AT91_US_PARE); if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= AT91_US_RXBRK; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= AT91_US_OVRE; } // TODO: Ignore all characters if CREAD is set. /* update the per-port timeout */ uart_update_timeout(port, termios->c_cflag, baud); /* disable interrupts and drain transmitter */ imr = UART_GET_IMR(port); /* get interrupt mask */ UART_PUT_IDR(port, -1); /* disable all interrupts */ while (!(UART_GET_CSR(port) & AT91_US_TXEMPTY)) { barrier(); } /* disable receiver and transmitter */ UART_PUT_CR(port, AT91_US_TXDIS | AT91_US_RXDIS); /* set the parity, stop bits and data size */ UART_PUT_MR(port, mode); /* set the baud rate */ UART_PUT_BRGR(port, quot); UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); /* restore interrupts */ UART_PUT_IER(port, imr); /* CTS flow-control and modem-status interrupts */ if (UART_ENABLE_MS(port, termios->c_cflag)) port->ops->enable_ms(port); spin_unlock_irqrestore(&port->lock, flags); }
static void msm_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; unsigned int baud, mr; spin_lock_irqsave(&port->lock, flags); /* calculate and set baud rate */ baud = uart_get_baud_rate(port, termios, old, 300, 115200); baud = msm_set_baud_rate(port, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); /* calculate parity */ mr = msm_read(port, UART_MR2); mr &= ~UART_MR2_PARITY_MODE; if (termios->c_cflag & PARENB) { if (termios->c_cflag & PARODD) mr |= UART_MR2_PARITY_MODE_ODD; else if (termios->c_cflag & CMSPAR) mr |= UART_MR2_PARITY_MODE_SPACE; else mr |= UART_MR2_PARITY_MODE_EVEN; } /* calculate bits per char */ mr &= ~UART_MR2_BITS_PER_CHAR; switch (termios->c_cflag & CSIZE) { case CS5: mr |= UART_MR2_BITS_PER_CHAR_5; break; case CS6: mr |= UART_MR2_BITS_PER_CHAR_6; break; case CS7: mr |= UART_MR2_BITS_PER_CHAR_7; break; case CS8: default: mr |= UART_MR2_BITS_PER_CHAR_8; break; } /* calculate stop bits */ mr &= ~(UART_MR2_STOP_BIT_LEN_ONE | UART_MR2_STOP_BIT_LEN_TWO); if (termios->c_cflag & CSTOPB) mr |= UART_MR2_STOP_BIT_LEN_TWO; else mr |= UART_MR2_STOP_BIT_LEN_ONE; /* set parity, bits per char, and stop bit */ msm_write(port, mr, UART_MR2); /* calculate and set hardware flow control */ mr = msm_read(port, UART_MR1); mr &= ~(UART_MR1_CTS_CTL | UART_MR1_RX_RDY_CTL); if (termios->c_cflag & CRTSCTS) { mr |= UART_MR1_CTS_CTL; mr |= UART_MR1_RX_RDY_CTL; } msm_write(port, mr, UART_MR1); /* Configure status bits to ignore based on termio flags. */ port->read_status_mask = 0; if (termios->c_iflag & INPCK) port->read_status_mask |= UART_SR_PAR_FRAME_ERR; if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= UART_SR_RX_BREAK; uart_update_timeout(port, termios->c_cflag, baud); spin_unlock_irqrestore(&port->lock, flags); }
static void lh7a40xuart_set_termios (struct uart_port* port, struct termios* termios, struct termios* old) { unsigned int con; unsigned int inten; unsigned int fcon; unsigned long flags; unsigned int baud; unsigned int quot; baud = uart_get_baud_rate (port, termios, old, 8, port->uartclk/16); quot = uart_get_divisor (port, baud); /* -1 performed elsewhere */ switch (termios->c_cflag & CSIZE) { case CS5: fcon = WLEN_5; break; case CS6: fcon = WLEN_6; break; case CS7: fcon = WLEN_7; break; case CS8: default: fcon = WLEN_8; break; } if (termios->c_cflag & CSTOPB) fcon |= STP2; if (termios->c_cflag & PARENB) { fcon |= PEN; if (!(termios->c_cflag & PARODD)) fcon |= EPS; } if (port->fifosize > 1) fcon |= FEN; spin_lock_irqsave (&port->lock, flags); uart_update_timeout (port, termios->c_cflag, baud); port->read_status_mask = RxOverrunError; if (termios->c_iflag & INPCK) port->read_status_mask |= RxFramingError | RxParityError; if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= RxBreak; /* Figure mask for status we ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= RxFramingError | RxParityError; if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= RxBreak; /* Ignore overrun when ignorning parity */ /* *** FIXME: is this in the right place? */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= RxOverrunError; } /* Ignore all receive errors when receive disabled */ if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= RxError; con = UR (port, UART_R_CON); inten = (UR (port, UART_R_INTEN) & ~ModemInt); if (UART_ENABLE_MS (port, termios->c_cflag)) inten |= ModemInt; BIT_CLR (port, UART_R_CON, UARTEN); /* Disable UART */ UR (port, UART_R_INTEN) = 0; /* Disable interrupts */ UR (port, UART_R_BRCON) = quot - 1; /* Set baud rate divisor */ UR (port, UART_R_FCON) = fcon; /* Set FIFO and frame ctrl */ UR (port, UART_R_INTEN) = inten; /* Enable interrupts */ UR (port, UART_R_CON) = con; /* Restore UART mode */ spin_unlock_irqrestore(&port->lock, flags); }
static void tegra_set_termios(struct uart_port *u, struct ktermios *termios, struct ktermios *oldtermios) { struct tegra_uart_port *t; unsigned int baud; unsigned long flags; unsigned int lcr; unsigned int c_cflag = termios->c_cflag; unsigned char mcr; t = container_of(u, struct tegra_uart_port, uport); dev_vdbg(t->uport.dev, "+tegra_set_termios\n"); spin_lock_irqsave(&u->lock, flags); /* Changing configuration, it is safe to stop any rx now */ if (t->rts_active) set_rts(t, false); /* Parity */ lcr = t->lcr_shadow; lcr &= ~UART_LCR_PARITY; if (PARENB == (c_cflag & PARENB)) { if (CMSPAR == (c_cflag & CMSPAR)) { /* FIXME What is space parity? */ /* data |= SPACE_PARITY; */ } else if (c_cflag & PARODD) { lcr |= UART_LCR_PARITY; lcr &= ~UART_LCR_EPAR; lcr &= ~UART_LCR_SPAR; } else { lcr |= UART_LCR_PARITY; lcr |= UART_LCR_EPAR; lcr &= ~UART_LCR_SPAR; } } lcr &= ~UART_LCR_WLEN8; switch (c_cflag & CSIZE) { case CS5: lcr |= UART_LCR_WLEN5; break; case CS6: lcr |= UART_LCR_WLEN6; break; case CS7: lcr |= UART_LCR_WLEN7; break; default: lcr |= UART_LCR_WLEN8; break; } /* Stop bits */ if (termios->c_cflag & CSTOPB) lcr |= UART_LCR_STOP; else lcr &= ~UART_LCR_STOP; uart_writeb(t, lcr, UART_LCR); t->lcr_shadow = lcr; /* Baud rate. */ baud = uart_get_baud_rate(u, termios, oldtermios, 200, 4000000); tegra_set_baudrate(t, baud); /* Flow control */ if (termios->c_cflag & CRTSCTS) { mcr = t->mcr_shadow; mcr |= UART_MCR_CTS_EN; mcr &= ~UART_MCR_RTS_EN; t->mcr_shadow = mcr; uart_writeb(t, mcr, UART_MCR); t->use_cts_control = true; /* if top layer has asked to set rts active then do so here */ if (t->rts_active) set_rts(t, true); } else { mcr = t->mcr_shadow; mcr &= ~UART_MCR_CTS_EN; mcr &= ~UART_MCR_RTS_EN; t->mcr_shadow = mcr; uart_writeb(t, mcr, UART_MCR); t->use_cts_control = false; } /* update the port timeout based on new settings */ uart_update_timeout(u, termios->c_cflag, baud); spin_unlock_irqrestore(&u->lock, flags); dev_vdbg(t->uport.dev, "-tegra_set_termios\n"); return; }
static void s3c24xx_serial_set_termios(struct uart_port *port, struct termios *termios, struct termios *old) { struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); struct s3c24xx_uart_port *ourport = to_ourport(port); struct s3c24xx_uart_clksrc *clksrc; struct clk *clk; unsigned long flags; unsigned int baud, quot; unsigned int ulcon; unsigned int umcon; /* * We don't support modem control lines. */ termios->c_cflag &= ~(HUPCL | CMSPAR); termios->c_cflag |= CLOCAL; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, 115200*8); if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) quot = port->custom_divisor; else quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud); /* check to see if we need to change clock source */ if (ourport->clksrc != clksrc || ourport->baudclk != clk) { s3c24xx_serial_setsource(port, clksrc); if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) { clk_disable(ourport->baudclk); clk_unuse(ourport->baudclk); ourport->baudclk = NULL; } clk_use(clk); clk_enable(clk); ourport->clksrc = clksrc; ourport->baudclk = clk; } switch (termios->c_cflag & CSIZE) { case CS5: dbg("config: 5bits/char\n"); ulcon = S3C2410_LCON_CS5; break; case CS6: dbg("config: 6bits/char\n"); ulcon = S3C2410_LCON_CS6; break; case CS7: dbg("config: 7bits/char\n"); ulcon = S3C2410_LCON_CS7; break; case CS8: default: dbg("config: 8bits/char\n"); ulcon = S3C2410_LCON_CS8; break; } /* preserve original lcon IR settings */ ulcon |= (cfg->ulcon & S3C2410_LCON_IRM); if (termios->c_cflag & CSTOPB) ulcon |= S3C2410_LCON_STOPB; umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0; if (termios->c_cflag & PARENB) { if (termios->c_cflag & PARODD) ulcon |= S3C2410_LCON_PODD; else ulcon |= S3C2410_LCON_PEVEN; } else { ulcon |= S3C2410_LCON_PNONE; } spin_lock_irqsave(&port->lock, flags); dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot); wr_regl(port, S3C2410_ULCON, ulcon); wr_regl(port, S3C2410_UBRDIV, quot); wr_regl(port, S3C2410_UMCON, umcon); dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n", rd_regl(port, S3C2410_ULCON), rd_regl(port, S3C2410_UCON), rd_regl(port, S3C2410_UFCON)); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); /* * Which character status flags are we interested in? */ port->read_status_mask = S3C2410_UERSTAT_OVERRUN; if (termios->c_iflag & INPCK) port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY; /* * Which character status flags should we ignore? */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN; if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR) port->ignore_status_mask |= S3C2410_UERSTAT_FRAME; /* * Ignore all characters if CREAD is not set. */ if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= RXSTAT_DUMMY_READ; spin_unlock_irqrestore(&port->lock, flags); }
static void serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_omap_port *up = to_uart_omap_port(port); unsigned char cval = 0; unsigned long flags = 0; unsigned int baud, quot; switch (termios->c_cflag & CSIZE) { case CS5: cval = UART_LCR_WLEN5; break; case CS6: cval = UART_LCR_WLEN6; break; case CS7: cval = UART_LCR_WLEN7; break; default: case CS8: cval = UART_LCR_WLEN8; break; } if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; if (termios->c_cflag & PARENB) cval |= UART_LCR_PARITY; if (!(termios->c_cflag & PARODD)) cval |= UART_LCR_EPAR; if (termios->c_cflag & CMSPAR) cval |= UART_LCR_SPAR; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13); quot = serial_omap_get_divisor(port, baud); /* calculate wakeup latency constraint */ up->calc_latency = (USEC_PER_SEC * up->port.fifosize) / (baud / 8); up->latency = up->calc_latency; schedule_work(&up->qos_work); up->dll = quot & 0xff; up->dlh = quot >> 8; up->mdr1 = UART_OMAP_MDR1_DISABLE; up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 | UART_FCR_ENABLE_FIFO; /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ pm_runtime_get_sync(up->dev); spin_lock_irqsave(&up->port.lock, flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) up->port.read_status_mask |= UART_LSR_BI; /* * Characters to ignore */ up->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { up->port.ignore_status_mask |= UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) up->port.ignore_status_mask |= UART_LSR_DR; /* * Modem status interrupts */ up->ier &= ~UART_IER_MSI; if (UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, cval); /* reset DLAB */ up->lcr = cval; up->scr = 0; /* FIFOs and DMA Settings */ /* FCR can be changed only when the * baud clock is not running * DLL_REG and DLH_REG set to 0. */ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_DLL, 0); serial_out(up, UART_DLM, 0); serial_out(up, UART_LCR, 0); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR) & ~UART_EFR_ECB; up->efr &= ~UART_EFR_SCD; serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); up->mcr = serial_in(up, UART_MCR) & ~UART_MCR_TCRTLR; serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); /* FIFO ENABLE, DMA MODE */ up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK; /* * NOTE: Setting OMAP_UART_SCR_RX_TRIG_GRANU1_MASK * sets Enables the granularity of 1 for TRIGGER RX * level. Along with setting RX FIFO trigger level * to 1 (as noted below, 16 characters) and TLR[3:0] * to zero this will result RX FIFO threshold level * to 1 character, instead of 16 as noted in comment * below. */ /* Set receive FIFO threshold to 16 characters and * transmit FIFO threshold to 16 spaces */ up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK; up->fcr |= UART_FCR6_R_TRIGGER_16 | UART_FCR6_T_TRIGGER_24 | UART_FCR_ENABLE_FIFO; serial_out(up, UART_FCR, up->fcr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_OMAP_SCR, up->scr); /* Reset UART_MCR_TCRTLR: this must be done with the EFR_ECB bit set */ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_MCR, up->mcr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); /* Protocol, Baud Rate, and Interrupt Settings */ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) serial_omap_mdr1_errataset(up, up->mdr1); else serial_out(up, UART_OMAP_MDR1, up->mdr1); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, 0); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_DLL, up->dll); /* LS of divisor */ serial_out(up, UART_DLM, up->dlh); /* MS of divisor */ serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, cval); if (!serial_omap_baud_is_mode16(port, baud)) up->mdr1 = UART_OMAP_MDR1_13X_MODE; else up->mdr1 = UART_OMAP_MDR1_16X_MODE; if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) serial_omap_mdr1_errataset(up, up->mdr1); else serial_out(up, UART_OMAP_MDR1, up->mdr1); /* Configure flow control */ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* XON1/XOFF1 accessible mode B, TCRTLR=0, ECB=0 */ serial_out(up, UART_XON1, termios->c_cc[VSTART]); serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]); /* Enable access to TCR/TLR */ serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG); if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) { /* Enable AUTORTS and AUTOCTS */ up->efr |= UART_EFR_CTS | UART_EFR_RTS; /* Ensure MCR RTS is asserted */ up->mcr |= UART_MCR_RTS; } else { /* Disable AUTORTS and AUTOCTS */ up->efr &= ~(UART_EFR_CTS | UART_EFR_RTS); } if (up->port.flags & UPF_SOFT_FLOW) { /* clear SW control mode bits */ up->efr &= OMAP_UART_SW_CLR; /* * IXON Flag: * Enable XON/XOFF flow control on input. * Receiver compares XON1, XOFF1. */ if (termios->c_iflag & IXON) up->efr |= OMAP_UART_SW_RX; /* * IXOFF Flag: * Enable XON/XOFF flow control on output. * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXOFF) up->efr |= OMAP_UART_SW_TX; /* * IXANY Flag: * Enable any character to restart output. * Operation resumes after receiving any * character after recognition of the XOFF character */ if (termios->c_iflag & IXANY) up->mcr |= UART_MCR_XONANY; else up->mcr &= ~UART_MCR_XONANY; } serial_out(up, UART_MCR, up->mcr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, up->lcr); serial_omap_set_mctrl(&up->port, up->port.mctrl); spin_unlock_irqrestore(&up->port.lock, flags); pm_runtime_mark_last_busy(up->dev); pm_runtime_put_autosuspend(up->dev); dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line); }
static void mcf_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; unsigned int baud, baudclk; unsigned char mr1, mr2; baud = uart_get_baud_rate(port, termios, old, 0, 230400); baudclk = ((MCF_BUSCLK / baud) + 16) / 32; mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR; mr2 = 0; switch (termios->c_cflag & CSIZE) { case CS5: mr1 |= MCFUART_MR1_CS5; break; case CS6: mr1 |= MCFUART_MR1_CS6; break; case CS7: mr1 |= MCFUART_MR1_CS7; break; case CS8: default: mr1 |= MCFUART_MR1_CS8; break; } if (termios->c_cflag & PARENB) { if (termios->c_cflag & CMSPAR) { if (termios->c_cflag & PARODD) mr1 |= MCFUART_MR1_PARITYMARK; else mr1 |= MCFUART_MR1_PARITYSPACE; } else { if (termios->c_cflag & PARODD) mr1 |= MCFUART_MR1_PARITYODD; else mr1 |= MCFUART_MR1_PARITYEVEN; } } else { mr1 |= MCFUART_MR1_PARITYNONE; } if (termios->c_cflag & CSTOPB) mr2 |= MCFUART_MR2_STOP2; else mr2 |= MCFUART_MR2_STOP1; if (termios->c_cflag & CRTSCTS) { mr1 |= MCFUART_MR1_RXRTS; mr2 |= MCFUART_MR2_TXCTS; } spin_lock_irqsave(&port->lock, flags); writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR); writeb(MCFUART_UCR_CMDRESETMRPTR, port->membase + MCFUART_UCR); writeb(mr1, port->membase + MCFUART_UMR); writeb(mr2, port->membase + MCFUART_UMR); writeb((baudclk & 0xff00) >> 8, port->membase + MCFUART_UBG1); writeb((baudclk & 0xff), port->membase + MCFUART_UBG2); writeb(MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER, port->membase + MCFUART_UCSR); writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE, port->membase + MCFUART_UCR); spin_unlock_irqrestore(&port->lock, flags); }
/* * Change the port parameters. */ static void tilegx_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { int err; UART_DIVISOR_t divisor; UART_TYPE_t type; unsigned int baud; struct tile_uart_port *tile_uart; gxio_uart_context_t *context; tile_uart = container_of(port, struct tile_uart_port, uart); if (!mutex_trylock(&tile_uart->mutex)) return; context = &tile_uart->context; /* Open the hypervisor device if we haven't already. */ if (context->fd < 0) { err = gxio_uart_init(context, port->line); if (err) { mutex_unlock(&tile_uart->mutex); return; } } divisor.word = gxio_uart_read(context, UART_DIVISOR); type.word = gxio_uart_read(context, UART_TYPE); /* Divisor. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); divisor.divisor = uart_get_divisor(port, baud); /* Byte size. */ if ((termios->c_cflag & CSIZE) == CS7) type.dbits = UART_TYPE__DBITS_VAL_SEVEN_DBITS; else type.dbits = UART_TYPE__DBITS_VAL_EIGHT_DBITS; /* Parity. */ if (termios->c_cflag & PARENB) { /* Mark or Space parity. */ if (termios->c_cflag & CMSPAR) if (termios->c_cflag & PARODD) type.ptype = UART_TYPE__PTYPE_VAL_MARK; else type.ptype = UART_TYPE__PTYPE_VAL_SPACE; else if (termios->c_cflag & PARODD) type.ptype = UART_TYPE__PTYPE_VAL_ODD; else type.ptype = UART_TYPE__PTYPE_VAL_EVEN; } else type.ptype = UART_TYPE__PTYPE_VAL_NONE; /* Stop bits. */ if (termios->c_cflag & CSTOPB) type.sbits = UART_TYPE__SBITS_VAL_TWO_SBITS; else type.sbits = UART_TYPE__SBITS_VAL_ONE_SBITS; /* Set the uart paramters. */ gxio_uart_write(context, UART_DIVISOR, divisor.word); gxio_uart_write(context, UART_TYPE, type.word); mutex_unlock(&tile_uart->mutex); }
static void clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int ubrlcr, baud, quot; unsigned long flags; /* * We don't implement CREAD. */ termios->c_cflag |= CREAD; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); switch (termios->c_cflag & CSIZE) { case CS5: ubrlcr = UBRLCR_WRDLEN5; break; case CS6: ubrlcr = UBRLCR_WRDLEN6; break; case CS7: ubrlcr = UBRLCR_WRDLEN7; break; default: // CS8 ubrlcr = UBRLCR_WRDLEN8; break; } if (termios->c_cflag & CSTOPB) ubrlcr |= UBRLCR_XSTOP; if (termios->c_cflag & PARENB) { ubrlcr |= UBRLCR_PRTEN; if (!(termios->c_cflag & PARODD)) ubrlcr |= UBRLCR_EVENPRT; } if (port->fifosize > 1) ubrlcr |= UBRLCR_FIFOEN; spin_lock_irqsave(&port->lock, flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); port->read_status_mask = UARTDR_OVERR; if (termios->c_iflag & INPCK) port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR; /* * Characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR; if (termios->c_iflag & IGNBRK) { /* * If we're ignoring parity and break indicators, * ignore overruns to (for real raw support). */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= UARTDR_OVERR; } quot -= 1; clps_writel(ubrlcr | quot, UBRLCR(port)); spin_unlock_irqrestore(&port->lock, flags); }
static void ks8695uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int lcr, fcr = 0; unsigned long flags; unsigned int baud, quot; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); switch (termios->c_cflag & CSIZE) { case CS5: lcr = URCL_5; break; case CS6: lcr = URCL_6; break; case CS7: lcr = URCL_7; break; default: lcr = URCL_8; break; } /* stop bits */ if (termios->c_cflag & CSTOPB) lcr |= URLC_URSB; /* parity */ if (termios->c_cflag & PARENB) { if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */ if (termios->c_cflag & PARODD) lcr |= URPE_MARK; else lcr |= URPE_SPACE; } else if (termios->c_cflag & PARODD) lcr |= URPE_ODD; else lcr |= URPE_EVEN; } if (port->fifosize > 1) fcr = URFC_URFRT_8 | URFC_URTFR | URFC_URRFR | URFC_URFE; spin_lock_irqsave(&port->lock, flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); port->read_status_mask = URLS_URROE; if (termios->c_iflag & INPCK) port->read_status_mask |= (URLS_URFE | URLS_URPE); if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= URLS_URBI; /* * Characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= (URLS_URFE | URLS_URPE); if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= URLS_URBI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= URLS_URROE; } /* * Ignore all characters if CREAD is not set. */ if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= UART_DUMMY_LSR_RX; /* first, disable everything */ if (UART_ENABLE_MS(port, termios->c_cflag)) ks8695uart_enable_ms(port); else ks8695uart_disable_ms(port); /* Set baud rate */ UART_PUT_BRDR(port, quot); UART_PUT_LCR(port, lcr); UART_PUT_FCR(port, fcr); spin_unlock_irqrestore(&port->lock, flags); }
static void cpm_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { int baud; unsigned long flags; u16 cval, scval, prev_mode; int bits, sbits; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; smc_t __iomem *smcp = pinfo->smcp; scc_t __iomem *sccp = pinfo->sccp; int maxidl; pr_debug("CPM uart[%d]:set_termios\n", port->line); baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); if (baud < HW_BUF_SPD_THRESHOLD || (pinfo->port.state && pinfo->port.state->port.low_latency)) pinfo->rx_fifosize = 1; else pinfo->rx_fifosize = RX_BUF_SIZE; /* MAXIDL is the timeout after which a receive buffer is closed * when not full if no more characters are received. * We calculate it from the baudrate so that the duration is * always the same at standard rates: about 4ms. */ maxidl = baud / 2400; if (maxidl < 1) maxidl = 1; if (maxidl > 0x10) maxidl = 0x10; /* Character length programmed into the mode register is the * sum of: 1 start bit, number of data bits, 0 or 1 parity bit, * 1 or 2 stop bits, minus 1. * The value 'bits' counts this for us. */ cval = 0; scval = 0; /* byte size */ switch (termios->c_cflag & CSIZE) { case CS5: bits = 5; break; case CS6: bits = 6; break; case CS7: bits = 7; break; case CS8: bits = 8; break; /* Never happens, but GCC is too dumb to figure it out */ default: bits = 8; break; } sbits = bits - 5; if (termios->c_cflag & CSTOPB) { cval |= SMCMR_SL; /* Two stops */ scval |= SCU_PSMR_SL; bits++; } if (termios->c_cflag & PARENB) { cval |= SMCMR_PEN; scval |= SCU_PSMR_PEN; bits++; if (!(termios->c_cflag & PARODD)) { cval |= SMCMR_PM_EVEN; scval |= (SCU_PSMR_REVP | SCU_PSMR_TEVP); } } /* * Update the timeout */ uart_update_timeout(port, termios->c_cflag, baud); /* * Set up parity check flag */ #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) port->read_status_mask = (BD_SC_EMPTY | BD_SC_OV); if (termios->c_iflag & INPCK) port->read_status_mask |= BD_SC_FR | BD_SC_PR; if ((termios->c_iflag & BRKINT) || (termios->c_iflag & PARMRK)) port->read_status_mask |= BD_SC_BR; /* * Characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= BD_SC_PR | BD_SC_FR; if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= BD_SC_BR; /* * If we're ignore parity and break indicators, ignore * overruns too. (For real raw support). */ if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= BD_SC_OV; } /* * !!! ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) port->read_status_mask &= ~BD_SC_EMPTY; spin_lock_irqsave(&port->lock, flags); /* Start bit has not been added (so don't, because we would just * subtract it later), and we need to add one for the number of * stops bits (there is always at least one). */ bits++; if (IS_SMC(pinfo)) { /* * MRBLR can be changed while an SMC/SCC is operating only * if it is done in a single bus cycle with one 16-bit move * (not two 8-bit bus cycles back-to-back). This occurs when * the cp shifts control to the next RxBD, so the change does * not take effect immediately. To guarantee the exact RxBD * on which the change occurs, change MRBLR only while the * SMC/SCC receiver is disabled. */ out_be16(&pinfo->smcup->smc_mrblr, pinfo->rx_fifosize); out_be16(&pinfo->smcup->smc_maxidl, maxidl); /* Set the mode register. We want to keep a copy of the * enables, because we want to put them back if they were * present. */ prev_mode = in_be16(&smcp->smc_smcmr) & (SMCMR_REN | SMCMR_TEN); /* Output in *one* operation, so we don't interrupt RX/TX if they * were already enabled. */ out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval | SMCMR_SM_UART | prev_mode); } else { out_be16(&pinfo->sccup->scc_genscc.scc_mrblr, pinfo->rx_fifosize); out_be16(&pinfo->sccup->scc_maxidl, maxidl); out_be16(&sccp->scc_psmr, (sbits << 12) | scval); } if (pinfo->clk) clk_set_rate(pinfo->clk, baud); else cpm_set_brg(pinfo->brg - 1, baud); spin_unlock_irqrestore(&port->lock, flags); }
static void imx_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct imx_port *sport = (struct imx_port *)port; unsigned long flags; unsigned int ucr2, old_ucr1, old_txrxen, baud, quot; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; unsigned int div, ufcr; unsigned long num, denom; uint64_t tdiv64; /* * If we don't support modem control lines, don't allow * these to be set. */ if (0) { termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR); termios->c_cflag |= CLOCAL; } /* * We only support CS7 and CS8. */ while ((termios->c_cflag & CSIZE) != CS7 && (termios->c_cflag & CSIZE) != CS8) { termios->c_cflag &= ~CSIZE; termios->c_cflag |= old_csize; old_csize = CS8; } if ((termios->c_cflag & CSIZE) == CS8) ucr2 = UCR2_WS | UCR2_SRST | UCR2_IRTS; else ucr2 = UCR2_SRST | UCR2_IRTS; if (termios->c_cflag & CRTSCTS) { if( sport->have_rtscts ) { ucr2 &= ~UCR2_IRTS; ucr2 |= UCR2_CTSC; } else { termios->c_cflag &= ~CRTSCTS; } } if (termios->c_cflag & CSTOPB) ucr2 |= UCR2_STPB; if (termios->c_cflag & PARENB) { ucr2 |= UCR2_PREN; if (termios->c_cflag & PARODD) ucr2 |= UCR2_PROE; } /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16); quot = uart_get_divisor(port, baud); spin_lock_irqsave(&sport->port.lock, flags); sport->port.read_status_mask = 0; if (termios->c_iflag & INPCK) sport->port.read_status_mask |= (URXD_FRMERR | URXD_PRERR); if (termios->c_iflag & (BRKINT | PARMRK)) sport->port.read_status_mask |= URXD_BRK; /* * Characters to ignore */ sport->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= URXD_PRERR; if (termios->c_iflag & IGNBRK) { sport->port.ignore_status_mask |= URXD_BRK; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= URXD_OVRRUN; } del_timer_sync(&sport->timer); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); /* * disable interrupts and drain transmitter */ old_ucr1 = readl(sport->port.membase + UCR1); writel(old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN), sport->port.membase + UCR1); while ( !(readl(sport->port.membase + USR2) & USR2_TXDC)) barrier(); /* then, disable everything */ old_txrxen = readl(sport->port.membase + UCR2); writel(old_txrxen & ~( UCR2_TXEN | UCR2_RXEN), sport->port.membase + UCR2); old_txrxen &= (UCR2_TXEN | UCR2_RXEN); if (USE_IRDA(sport)) { /* * use maximum available submodule frequency to * avoid missing short pulses due to low sampling rate */ div = 1; } else { div = sport->port.uartclk / (baud * 16); if (div > 7) div = 7; if (!div) div = 1; } rational_best_approximation(16 * div * baud, sport->port.uartclk, 1 << 16, 1 << 16, &num, &denom); if (port->state && port->state->port.tty) { tdiv64 = sport->port.uartclk; tdiv64 *= num; do_div(tdiv64, denom * 16 * div); tty_encode_baud_rate(sport->port.state->port.tty, (speed_t)tdiv64, (speed_t)tdiv64); } num -= 1; denom -= 1; ufcr = readl(sport->port.membase + UFCR); ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div); writel(ufcr, sport->port.membase + UFCR); writel(num, sport->port.membase + UBIR); writel(denom, sport->port.membase + UBMR); if (!cpu_is_mx1()) writel(sport->port.uartclk / div / 1000, sport->port.membase + MX2_ONEMS); writel(old_ucr1, sport->port.membase + UCR1); /* set the parity, stop bits and data size */ writel(ucr2 | old_txrxen, sport->port.membase + UCR2); if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) imx_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock, flags); }
static void pl010_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int lcr_h, old_cr; unsigned long flags; unsigned int baud, quot; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16); quot = uart_get_divisor(port, baud); switch (termios->c_cflag & CSIZE) { case CS5: lcr_h = UART01x_LCRH_WLEN_5; break; case CS6: lcr_h = UART01x_LCRH_WLEN_6; break; case CS7: lcr_h = UART01x_LCRH_WLEN_7; break; default: // CS8 lcr_h = UART01x_LCRH_WLEN_8; break; } if (termios->c_cflag & CSTOPB) lcr_h |= UART01x_LCRH_STP2; if (termios->c_cflag & PARENB) { lcr_h |= UART01x_LCRH_PEN; if (!(termios->c_cflag & PARODD)) lcr_h |= UART01x_LCRH_EPS; } if (uap->port.fifosize > 1) lcr_h |= UART01x_LCRH_FEN; spin_lock_irqsave(&uap->port.lock, flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); uap->port.read_status_mask = UART01x_RSR_OE; if (termios->c_iflag & INPCK) uap->port.read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) uap->port.read_status_mask |= UART01x_RSR_BE; /* * Characters to ignore */ uap->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) uap->port.ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; if (termios->c_iflag & IGNBRK) { uap->port.ignore_status_mask |= UART01x_RSR_BE; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) uap->port.ignore_status_mask |= UART01x_RSR_OE; } /* * Ignore all characters if CREAD is not set. */ if ((termios->c_cflag & CREAD) == 0) uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX; /* first, disable everything */ old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE; if (UART_ENABLE_MS(port, termios->c_cflag)) old_cr |= UART010_CR_MSIE; writel(0, uap->port.membase + UART010_CR); /* Set baud rate */ quot -= 1; writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM); writel(quot & 0xff, uap->port.membase + UART010_LCRL); /* * ----------v----------v----------v----------v----- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L * ----------^----------^----------^----------^----- */ writel(lcr_h, uap->port.membase + UART010_LCRH); writel(old_cr, uap->port.membase + UART010_CR); spin_unlock_irqrestore(&uap->port.lock, flags); }
static void mxs_auart_settermios(struct uart_port *u, struct ktermios *termios, struct ktermios *old) { u32 bm, ctrl, ctrl2, div; unsigned int cflag, baud; cflag = termios->c_cflag; ctrl = AUART_LINECTRL_FEN; ctrl2 = readl(u->membase + AUART_CTRL2); /* byte size */ switch (cflag & CSIZE) { case CS5: bm = 0; break; case CS6: bm = 1; break; case CS7: bm = 2; break; case CS8: bm = 3; break; default: return; } ctrl |= AUART_LINECTRL_WLEN(bm); /* parity */ if (cflag & PARENB) { ctrl |= AUART_LINECTRL_PEN; if ((cflag & PARODD) == 0) ctrl |= AUART_LINECTRL_EPS; } u->read_status_mask = 0; if (termios->c_iflag & INPCK) u->read_status_mask |= AUART_STAT_PERR; if (termios->c_iflag & (BRKINT | PARMRK)) u->read_status_mask |= AUART_STAT_BERR; /* * Characters to ignore */ u->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) u->ignore_status_mask |= AUART_STAT_PERR; if (termios->c_iflag & IGNBRK) { u->ignore_status_mask |= AUART_STAT_BERR; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) u->ignore_status_mask |= AUART_STAT_OERR; } /* * ignore all characters if CREAD is not set */ if (cflag & CREAD) ctrl2 |= AUART_CTRL2_RXE; else ctrl2 &= ~AUART_CTRL2_RXE; /* figure out the stop bits requested */ if (cflag & CSTOPB) ctrl |= AUART_LINECTRL_STP2; /* figure out the hardware flow control settings */ if (cflag & CRTSCTS) ctrl2 |= AUART_CTRL2_CTSEN; else ctrl2 &= ~AUART_CTRL2_CTSEN; /* set baud rate */ baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk); div = u->uartclk * 32 / baud; ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F); ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6); writel(ctrl, u->membase + AUART_LINECTRL); writel(ctrl2, u->membase + AUART_CTRL2); }
static void sa1100_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sa1100_port *sport = (struct sa1100_port *)port; unsigned long flags; unsigned int utcr0, old_utcr3, baud, quot; unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; /* * We only support CS7 and CS8. */ while ((termios->c_cflag & CSIZE) != CS7 && (termios->c_cflag & CSIZE) != CS8) { termios->c_cflag &= ~CSIZE; termios->c_cflag |= old_csize; old_csize = CS8; } if ((termios->c_cflag & CSIZE) == CS8) utcr0 = UTCR0_DSS; else utcr0 = 0; if (termios->c_cflag & CSTOPB) utcr0 |= UTCR0_SBS; if (termios->c_cflag & PARENB) { utcr0 |= UTCR0_PE; if (!(termios->c_cflag & PARODD)) utcr0 |= UTCR0_OES; } /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); spin_lock_irqsave(&sport->port.lock, flags); sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS); sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR); if (termios->c_iflag & INPCK) sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (termios->c_iflag & (BRKINT | PARMRK)) sport->port.read_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); /* * Characters to ignore */ sport->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= UTSR1_TO_SM(UTSR1_FRE | UTSR1_PRE); if (termios->c_iflag & IGNBRK) { sport->port.ignore_status_mask |= UTSR0_TO_SM(UTSR0_RBB | UTSR0_REB); /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) sport->port.ignore_status_mask |= UTSR1_TO_SM(UTSR1_ROR); } del_timer_sync(&sport->timer); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); /* * disable interrupts and drain transmitter */ old_utcr3 = UART_GET_UTCR3(sport); UART_PUT_UTCR3(sport, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)); while (UART_GET_UTSR1(sport) & UTSR1_TBY) barrier(); /* then, disable everything */ UART_PUT_UTCR3(sport, 0); /* set the parity, stop bits and data size */ UART_PUT_UTCR0(sport, utcr0); /* set the baud rate */ quot -= 1; UART_PUT_UTCR1(sport, ((quot & 0xf00) >> 8)); UART_PUT_UTCR2(sport, (quot & 0xff)); UART_PUT_UTSR0(sport, -1); UART_PUT_UTCR3(sport, old_utcr3); if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) sa1100_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock, flags); }
static void serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned char cval = 0; unsigned char efr = 0; unsigned long flags = 0; unsigned int baud, quot; switch (termios->c_cflag & CSIZE) { case CS5: cval = UART_LCR_WLEN5; break; case CS6: cval = UART_LCR_WLEN6; break; case CS7: cval = UART_LCR_WLEN7; break; default: case CS8: cval = UART_LCR_WLEN8; break; } if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; if (termios->c_cflag & PARENB) cval |= UART_LCR_PARITY; if (!(termios->c_cflag & PARODD)) cval |= UART_LCR_EPAR; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13); /* Added for the suporrt of DPLL, frequency changes * This value can be used to recalculate the DLLand * DLH values. If this function is not called for * particulate UART it would remain as 0. */ up->baud_rate = baud; quot = serial_omap_get_divisor(port, baud); up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 | UART_FCR_ENABLE_FIFO; if (up->use_dma) up->fcr |= UART_FCR_DMA_SELECT; /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ spin_lock_irqsave(&up->port.lock, flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) up->port.read_status_mask |= UART_LSR_BI; /* * Characters to ignore */ up->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { up->port.ignore_status_mask |= UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) up->port.ignore_status_mask |= UART_LSR_DR; /* * Modem status interrupts */ up->ier &= ~UART_IER_MSI; if (UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, cval); /* reset DLAB */ /* FIFOs and DMA Settings */ /* FCR can be changed only when the * baud clock is not running * DLL_REG and DLH_REG set to 0. */ serial_out(up, UART_LCR, UART_LCR_DLAB); serial_out(up, UART_DLL, 0); serial_out(up, UART_DLM, 0); serial_out(up, UART_LCR, 0); serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, 0); up->mcr = serial_in(up, UART_MCR); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); /* FIFO ENABLE, DMA MODE */ serial_out(up, UART_FCR, up->fcr); serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); if (up->use_dma) { if (up->uart_dma.tx_threshold) { serial_out(up, UART_MDR3, SET_DMA_TX_THRESHOLD); serial_out(up, UART_TX_DMA_THRESHOLD, TX_FIFO_THR_LVL); } serial_out(up, UART_TI752_TLR, 0); serial_out(up, UART_OMAP_SCR, (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8)); } serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, UART_LCR_DLAB); serial_out(up, UART_MCR, up->mcr); /* Protocol, Baud Rate, and Interrupt Settings */ serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_DISABLE); serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, 0); serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, cval); if (baud > 230400 && baud != 3000000) serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE13X); else serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE16X); /* Hardware Flow Control Configuration */ if (termios->c_cflag & CRTSCTS) { efr |= (UART_EFR_CTS | UART_EFR_RTS); serial_out(up, UART_LCR, UART_LCR_DLAB); up->mcr = serial_in(up, UART_MCR); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG); serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */ serial_out(up, UART_LCR, UART_LCR_DLAB); serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS); serial_out(up, UART_LCR, cval); } serial_omap_set_mctrl(&up->port, up->port.mctrl); /* Software Flow Control Configuration */ if (termios->c_iflag & (IXON | IXOFF)) serial_omap_configure_xonxoff(up, termios); spin_unlock_irqrestore(&up->port.lock, flags); dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id); }
/** * xuartps_set_termios - termios operations, handling data length, parity, * stop bits, flow control, baud rate * @port: Handle to the uart port structure * @termios: Handle to the input termios structure * @old: Values of the previously saved termios structure * **/ static void xuartps_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int cval = 0; unsigned int baud; unsigned long flags; unsigned int ctrl_reg, mode_reg; spin_lock_irqsave(&port->lock, flags); /* Empty the receive FIFO 1st before making changes */ while ((xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) { xuartps_readl(XUARTPS_FIFO_OFFSET); } /* Disable the TX and RX to set baud rate */ xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | (XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS), XUARTPS_CR_OFFSET); /* Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk */ baud = uart_get_baud_rate(port, termios, old, 0, 10000000); baud = xuartps_set_baud_rate(port, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); /* Set TX/RX Reset */ xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) | (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST), XUARTPS_CR_OFFSET); ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET); /* Clear the RX disable and TX disable bits and then set the TX enable * bit and RX enable bit to enable the transmitter and receiver. */ xuartps_writel( (ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) | (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN), XUARTPS_CR_OFFSET); xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG | XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT; port->ignore_status_mask = 0; if (termios->c_iflag & INPCK) port->read_status_mask |= XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN; /* ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN; mode_reg = xuartps_readl(XUARTPS_MR_OFFSET); /* Handling Data Size */ switch (termios->c_cflag & CSIZE) { case CS6: cval |= XUARTPS_MR_CHARLEN_6_BIT; break; case CS7: cval |= XUARTPS_MR_CHARLEN_7_BIT; break; default: case CS8: cval |= XUARTPS_MR_CHARLEN_8_BIT; termios->c_cflag &= ~CSIZE; termios->c_cflag |= CS8; break; } /* Handling Parity and Stop Bits length */ if (termios->c_cflag & CSTOPB) cval |= XUARTPS_MR_STOPMODE_2_BIT; /* 2 STOP bits */ else cval |= XUARTPS_MR_STOPMODE_1_BIT; /* 1 STOP bit */ if (termios->c_cflag & PARENB) { /* Mark or Space parity */ if (termios->c_cflag & CMSPAR) { if (termios->c_cflag & PARODD) cval |= XUARTPS_MR_PARITY_MARK; else cval |= XUARTPS_MR_PARITY_SPACE; } else if (termios->c_cflag & PARODD) cval |= XUARTPS_MR_PARITY_ODD; else cval |= XUARTPS_MR_PARITY_EVEN; } else cval |= XUARTPS_MR_PARITY_NONE; xuartps_writel(cval , XUARTPS_MR_OFFSET); spin_unlock_irqrestore(&port->lock, flags); }
/* * OMAP can use "CLK / (16 or 13) / div" for baud rate. And then we have have * some differences in how we want to handle flow control. */ static void omap_8250_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_8250_port *up = up_to_u8250p(port); struct omap8250_priv *priv = up->port.private_data; unsigned char cval = 0; unsigned int baud; switch (termios->c_cflag & CSIZE) { case CS5: cval = UART_LCR_WLEN5; break; case CS6: cval = UART_LCR_WLEN6; break; case CS7: cval = UART_LCR_WLEN7; break; default: case CS8: cval = UART_LCR_WLEN8; break; } if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; if (termios->c_cflag & PARENB) cval |= UART_LCR_PARITY; if (!(termios->c_cflag & PARODD)) cval |= UART_LCR_EPAR; if (termios->c_cflag & CMSPAR) cval |= UART_LCR_SPAR; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, port->uartclk / 16 / UART_DIV_MAX, port->uartclk / 13); omap_8250_get_divisor(port, baud, priv); /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ pm_runtime_get_sync(port->dev); spin_lock_irq(&port->lock); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (IGNBRK | PARMRK)) up->port.read_status_mask |= UART_LSR_BI; /* * Characters to ignore */ up->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { up->port.ignore_status_mask |= UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) up->port.ignore_status_mask |= UART_LSR_DR; /* * Modem status interrupts */ up->ier &= ~UART_IER_MSI; if (UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; up->lcr = cval; /* Up to here it was mostly serial8250_do_set_termios() */ /* * We enable TRIG_GRANU for RX and TX and additionaly we set * SCR_TX_EMPTY bit. The result is the following: * - RX_TRIGGER amount of bytes in the FIFO will cause an interrupt. * - less than RX_TRIGGER number of bytes will also cause an interrupt * once the UART decides that there no new bytes arriving. * - Once THRE is enabled, the interrupt will be fired once the FIFO is * empty - the trigger level is ignored here. * * Once DMA is enabled: * - UART will assert the TX DMA line once there is room for TX_TRIGGER * bytes in the TX FIFO. On each assert the DMA engine will move * TX_TRIGGER bytes into the FIFO. * - UART will assert the RX DMA line once there are RX_TRIGGER bytes in * the FIFO and move RX_TRIGGER bytes. * This is because threshold and trigger values are the same. */ up->fcr = UART_FCR_ENABLE_FIFO; up->fcr |= TRIGGER_FCR_MASK(TX_TRIGGER) << OMAP_UART_FCR_TX_TRIG; up->fcr |= TRIGGER_FCR_MASK(RX_TRIGGER) << OMAP_UART_FCR_RX_TRIG; priv->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY | OMAP_UART_SCR_TX_TRIG_GRANU1_MASK; if (up->dma) priv->scr |= OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL; priv->xon = termios->c_cc[VSTART]; priv->xoff = termios->c_cc[VSTOP]; priv->efr = 0; up->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); if (termios->c_cflag & CRTSCTS && up->port.flags & UPF_HARD_FLOW) { /* Enable AUTOCTS (autoRTS is enabled when RTS is raised) */ up->port.status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; priv->efr |= UART_EFR_CTS; } else if (up->port.flags & UPF_SOFT_FLOW) { /* * OMAP rx s/w flow control is borked; the transmitter remains * stuck off even if rx flow control is subsequently disabled */ /* * IXOFF Flag: * Enable XON/XOFF flow control on output. * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXOFF) { up->port.status |= UPSTAT_AUTOXOFF; priv->efr |= OMAP_UART_SW_TX; } } omap8250_restore_regs(up); spin_unlock_irq(&up->port.lock); pm_runtime_mark_last_busy(port->dev); pm_runtime_put_autosuspend(port->dev); /* calculate wakeup latency constraint */ priv->calc_latency = USEC_PER_SEC * 64 * 8 / baud; priv->latency = priv->calc_latency; schedule_work(&priv->qos_work); /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); }
/** * cdns_uart_set_termios - termios operations, handling data length, parity, * stop bits, flow control, baud rate * @port: Handle to the uart port structure * @termios: Handle to the input termios structure * @old: Values of the previously saved termios structure */ static void cdns_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int cval = 0; unsigned int baud, minbaud, maxbaud; unsigned long flags; unsigned int ctrl_reg, mode_reg; spin_lock_irqsave(&port->lock, flags); /* Wait for the transmit FIFO to empty before making changes */ if (!(cdns_uart_readl(CDNS_UART_CR_OFFSET) & CDNS_UART_CR_TX_DIS)) { while (!(cdns_uart_readl(CDNS_UART_SR_OFFSET) & CDNS_UART_SR_TXEMPTY)) { cpu_relax(); } } /* Disable the TX and RX to set baud rate */ ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET); ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS; cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET); /* * Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk * min and max baud should be calculated here based on port->uartclk. * this way we get a valid baud and can safely call set_baud() */ minbaud = port->uartclk / ((CDNS_UART_BDIV_MAX + 1) * CDNS_UART_CD_MAX * 8); maxbaud = port->uartclk / (CDNS_UART_BDIV_MIN + 1); baud = uart_get_baud_rate(port, termios, old, minbaud, maxbaud); baud = cdns_uart_set_baud_rate(port, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); /* Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); /* Set TX/RX Reset */ ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET); ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST; cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET); /* * Clear the RX disable and TX disable bits and then set the TX enable * bit and RX enable bit to enable the transmitter and receiver. */ ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET); ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS); ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET); cdns_uart_writel(rx_timeout, CDNS_UART_RXTOUT_OFFSET); port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT; port->ignore_status_mask = 0; if (termios->c_iflag & INPCK) port->read_status_mask |= CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING; /* ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT | CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN; mode_reg = cdns_uart_readl(CDNS_UART_MR_OFFSET); /* Handling Data Size */ switch (termios->c_cflag & CSIZE) { case CS6: cval |= CDNS_UART_MR_CHARLEN_6_BIT; break; case CS7: cval |= CDNS_UART_MR_CHARLEN_7_BIT; break; default: case CS8: cval |= CDNS_UART_MR_CHARLEN_8_BIT; termios->c_cflag &= ~CSIZE; termios->c_cflag |= CS8; break; } /* Handling Parity and Stop Bits length */ if (termios->c_cflag & CSTOPB) cval |= CDNS_UART_MR_STOPMODE_2_BIT; /* 2 STOP bits */ else cval |= CDNS_UART_MR_STOPMODE_1_BIT; /* 1 STOP bit */ if ((termios->c_cflag & PARENB) || (termios->c_cflag & PARODD)) { /* Mark or Space parity */ if (termios->c_cflag & CMSPAR) { if (termios->c_cflag & PARODD) cval |= CDNS_UART_MR_PARITY_MARK; else cval |= CDNS_UART_MR_PARITY_SPACE; } else { if (termios->c_cflag & PARODD) cval |= CDNS_UART_MR_PARITY_ODD; else cval |= CDNS_UART_MR_PARITY_EVEN; } } else { cval |= CDNS_UART_MR_PARITY_NONE; } cval |= mode_reg & 1; cdns_uart_writel(cval, CDNS_UART_MR_OFFSET); spin_unlock_irqrestore(&port->lock, flags); }
static void serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_omap_port *up = (struct uart_omap_port *)port; unsigned char cval = 0; unsigned long flags = 0; unsigned int baud, quot; unsigned int status; switch (termios->c_cflag & CSIZE) { case CS5: cval = UART_LCR_WLEN5; break; case CS6: cval = UART_LCR_WLEN6; break; case CS7: cval = UART_LCR_WLEN7; break; default: case CS8: cval = UART_LCR_WLEN8; break; } if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; if (termios->c_cflag & PARENB) cval |= UART_LCR_PARITY; if (!(termios->c_cflag & PARODD)) cval |= UART_LCR_EPAR; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13); quot = serial_omap_get_divisor(port, baud); up->dll = quot & 0xff; up->dlh = quot >> 8; up->mdr1 = UART_OMAP_MDR1_DISABLE; up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 | UART_FCR_ENABLE_FIFO; if (up->use_dma) up->fcr |= UART_FCR_DMA_SELECT; /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ serial_omap_port_enable(up); spin_lock_irqsave(&up->port.lock, flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) up->port.read_status_mask |= UART_LSR_BI; /* * Characters to ignore */ up->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { up->port.ignore_status_mask |= UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) up->port.ignore_status_mask |= UART_LSR_DR; /* * Modem status interrupts */ up->ier &= ~UART_IER_MSI; //if (UART_ENABLE_MS(&up->port, termios->c_cflag)) if (UART_ENABLE_MS(&up->port, termios->c_cflag)) { status = serial_in(up, UART_MSR); if (status & UART_MSR_CTS) uart_handle_cts_change(&up->port, status & UART_MSR_CTS); up->ier |= UART_IER_MSI; } serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, cval); /* reset DLAB */ up->lcr = cval; up->scr = OMAP_UART_SCR_TX_EMPTY; /* FIFOs and DMA Settings */ /* FCR can be changed only when the * baud clock is not running * DLL_REG and DLH_REG set to 0. */ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_DLL, 0); serial_out(up, UART_DLM, 0); serial_out(up, UART_LCR, 0); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); up->mcr = serial_in(up, UART_MCR); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); /* FIFO ENABLE, DMA MODE */ serial_out(up, UART_FCR, up->fcr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); if (up->use_dma) { if (up->errata & OMAP4_UART_ERRATA_i659_TX_THR) { serial_out(up, UART_MDR3, SET_DMA_TX_THRESHOLD); serial_out(up, UART_TX_DMA_THRESHOLD, TX_FIFO_THR_LVL); } serial_out(up, UART_TI752_TLR, 0); up->scr |= (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8); } serial_out(up, UART_OMAP_SCR, up->scr); serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); serial_out(up, UART_MCR, up->mcr); /* Protocol, Baud Rate, and Interrupt Settings */ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) omap_uart_mdr1_errataset(up, up->mdr1); else serial_out(up, UART_OMAP_MDR1, up->mdr1); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, 0); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_DLL, up->dll); /* LS of divisor */ serial_out(up, UART_DLM, up->dlh); /* MS of divisor */ serial_out(up, UART_LCR, 0); serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, cval); if (baud > 230400 && baud != 3000000) up->mdr1 = UART_OMAP_MDR1_13X_MODE; else up->mdr1 = UART_OMAP_MDR1_16X_MODE; if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) omap_uart_mdr1_errataset(up, up->mdr1); else serial_out(up, UART_OMAP_MDR1, up->mdr1); /* Hardware Flow Control Configuration */ if (termios->c_cflag & CRTSCTS) { serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); up->mcr = serial_in(up, UART_MCR); serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG); up->efr |= (UART_EFR_CTS | UART_EFR_RTS); serial_out(up, UART_EFR, up->efr); /* Enable AUTORTS and AUTOCTS */ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); up->mcr |= UART_MCR_RTS; serial_out(up, UART_MCR, up->mcr); serial_out(up, UART_LCR, cval); } else { serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); up->efr &= ~(UART_EFR_CTS | UART_EFR_RTS); serial_out(up, UART_EFR, up->efr); /* Disable AUTORTS and AUTOCTS */ serial_out(up, UART_LCR, cval); } serial_omap_set_mctrl(&up->port, up->port.mctrl); /* Software Flow Control Configuration */ serial_omap_configure_xonxoff(up, termios); /* Now we are ready for RX data: enable rts line */ if (up->rts_mux_driver_control && up->rts_pullup_in_suspend) { omap_rts_mux_write(0, up->port.line); up->rts_pullup_in_suspend = 0; } spin_unlock_irqrestore(&up->port.lock, flags); serial_omap_port_disable(up); dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id); }
static void tegra_uart_set_termios(struct uart_port *u, struct ktermios *termios, struct ktermios *oldtermios) { struct tegra_uart_port *tup = to_tegra_uport(u); unsigned int baud; unsigned long flags; unsigned int lcr; int symb_bit = 1; struct clk *parent_clk = clk_get_parent(tup->uart_clk); unsigned long parent_clk_rate = clk_get_rate(parent_clk); int max_divider = (tup->cdata->support_clk_src_div) ? 0x7FFF : 0xFFFF; max_divider *= 16; spin_lock_irqsave(&u->lock, flags); /* Changing configuration, it is safe to stop any rx now */ if (tup->rts_active) set_rts(tup, false); /* Clear all interrupts as configuration is going to be change */ tegra_uart_write(tup, tup->ier_shadow | UART_IER_RDI, UART_IER); tegra_uart_read(tup, UART_IER); tegra_uart_write(tup, 0, UART_IER); tegra_uart_read(tup, UART_IER); /* Parity */ lcr = tup->lcr_shadow; lcr &= ~UART_LCR_PARITY; /* CMSPAR isn't supported by this driver */ termios->c_cflag &= ~CMSPAR; if ((termios->c_cflag & PARENB) == PARENB) { symb_bit++; if (termios->c_cflag & PARODD) { lcr |= UART_LCR_PARITY; lcr &= ~UART_LCR_EPAR; lcr &= ~UART_LCR_SPAR; } else { lcr |= UART_LCR_PARITY; lcr |= UART_LCR_EPAR; lcr &= ~UART_LCR_SPAR; } } lcr &= ~UART_LCR_WLEN8; switch (termios->c_cflag & CSIZE) { case CS5: lcr |= UART_LCR_WLEN5; symb_bit += 5; break; case CS6: lcr |= UART_LCR_WLEN6; symb_bit += 6; break; case CS7: lcr |= UART_LCR_WLEN7; symb_bit += 7; break; default: lcr |= UART_LCR_WLEN8; symb_bit += 8; break; } /* Stop bits */ if (termios->c_cflag & CSTOPB) { lcr |= UART_LCR_STOP; symb_bit += 2; } else { lcr &= ~UART_LCR_STOP; symb_bit++; } tegra_uart_write(tup, lcr, UART_LCR); tup->lcr_shadow = lcr; tup->symb_bit = symb_bit; /* Baud rate. */ baud = uart_get_baud_rate(u, termios, oldtermios, parent_clk_rate/max_divider, parent_clk_rate/16); spin_unlock_irqrestore(&u->lock, flags); tegra_set_baudrate(tup, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); spin_lock_irqsave(&u->lock, flags); /* Flow control */ if (termios->c_cflag & CRTSCTS) { tup->mcr_shadow |= TEGRA_UART_MCR_CTS_EN; tup->mcr_shadow &= ~TEGRA_UART_MCR_RTS_EN; tegra_uart_write(tup, tup->mcr_shadow, UART_MCR); /* if top layer has asked to set rts active then do so here */ if (tup->rts_active) set_rts(tup, true); } else { tup->mcr_shadow &= ~TEGRA_UART_MCR_CTS_EN; tup->mcr_shadow &= ~TEGRA_UART_MCR_RTS_EN; tegra_uart_write(tup, tup->mcr_shadow, UART_MCR); } /* update the port timeout based on new settings */ uart_update_timeout(u, termios->c_cflag, baud); /* Make sure all write has completed */ tegra_uart_read(tup, UART_IER); /* Reenable interrupt */ tegra_uart_write(tup, tup->ier_shadow, UART_IER); tegra_uart_read(tup, UART_IER); spin_unlock_irqrestore(&u->lock, flags); return; }
static void msm_hsl_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned long flags; unsigned int baud, mr; spin_lock_irqsave(&port->lock, flags); clk_en(port, 1); /* calculate and set baud rate */ baud = uart_get_baud_rate(port, termios, old, 300, 460800); msm_hsl_set_baud_rate(port, baud); /* calculate parity */ mr = msm_hsl_read(port, UARTDM_MR2_ADDR); mr &= ~UARTDM_MR2_PARITY_MODE_BMSK; if (termios->c_cflag & PARENB) { if (termios->c_cflag & PARODD) mr |= ODD_PARITY; else if (termios->c_cflag & CMSPAR) mr |= SPACE_PARITY; else mr |= EVEN_PARITY; } /* calculate bits per char */ mr &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK; switch (termios->c_cflag & CSIZE) { case CS5: mr |= FIVE_BPC; break; case CS6: mr |= SIX_BPC; break; case CS7: mr |= SEVEN_BPC; break; case CS8: default: mr |= EIGHT_BPC; break; } /* calculate stop bits */ mr &= ~(STOP_BIT_ONE | STOP_BIT_TWO); if (termios->c_cflag & CSTOPB) mr |= STOP_BIT_TWO; else mr |= STOP_BIT_ONE; /* set parity, bits per char, and stop bit */ msm_hsl_write(port, mr, UARTDM_MR2_ADDR); /* calculate and set hardware flow control */ mr = msm_hsl_read(port, UARTDM_MR1_ADDR); mr &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK); if (termios->c_cflag & CRTSCTS) { mr |= UARTDM_MR1_CTS_CTL_BMSK; mr |= UARTDM_MR1_RX_RDY_CTL_BMSK; } msm_hsl_write(port, mr, UARTDM_MR1_ADDR); /* Configure status bits to ignore based on termio flags. */ port->read_status_mask = 0; if (termios->c_iflag & INPCK) port->read_status_mask |= UARTDM_SR_PAR_FRAME_BMSK; if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= UARTDM_SR_RX_BREAK_BMSK; uart_update_timeout(port, termios->c_cflag, baud); clk_en(port, 0); spin_unlock_irqrestore(&port->lock, flags); }
static void vt8500_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct vt8500_port *vt8500_port = container_of(port, struct vt8500_port, uart); unsigned long flags; unsigned int baud, lcr; unsigned int loops = 1000; spin_lock_irqsave(&port->lock, flags); /* calculate and set baud rate */ baud = uart_get_baud_rate(port, termios, old, 900, 921600); baud = vt8500_set_baud_rate(port, baud); if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); /* calculate parity */ lcr = vt8500_read(&vt8500_port->uart, VT8500_URLCR); lcr &= ~(VT8500_PARENB | VT8500_PARODD); if (termios->c_cflag & PARENB) { lcr |= VT8500_PARENB; termios->c_cflag &= ~CMSPAR; if (termios->c_cflag & PARODD) lcr |= VT8500_PARODD; } /* calculate bits per char */ lcr &= ~VT8500_CS8; switch (termios->c_cflag & CSIZE) { case CS7: break; case CS8: default: lcr |= VT8500_CS8; termios->c_cflag &= ~CSIZE; termios->c_cflag |= CS8; break; } /* calculate stop bits */ lcr &= ~VT8500_CSTOPB; if (termios->c_cflag & CSTOPB) lcr |= VT8500_CSTOPB; lcr &= ~VT8500_SWRTSCTS; if (vt8500_port->vt8500_uart_flags & VT8500_HAS_SWRTSCTS_SWITCH) lcr |= VT8500_SWRTSCTS; /* set parity, bits per char, and stop bit */ vt8500_write(&vt8500_port->uart, lcr, VT8500_URLCR); /* Configure status bits to ignore based on termio flags. */ port->read_status_mask = 0; if (termios->c_iflag & IGNPAR) port->read_status_mask = FER | PER; uart_update_timeout(port, termios->c_cflag, baud); /* Reset FIFOs */ vt8500_write(&vt8500_port->uart, 0x88c, VT8500_URFCR); while ((vt8500_read(&vt8500_port->uart, VT8500_URFCR) & 0xc) && --loops) cpu_relax(); /* Every possible FIFO-related interrupt */ vt8500_port->ier = RX_FIFO_INTS | TX_FIFO_INTS; /* * CTS flow control */ if (UART_ENABLE_MS(&vt8500_port->uart, termios->c_cflag)) vt8500_port->ier |= TCTS; vt8500_write(&vt8500_port->uart, 0x881, VT8500_URFCR); vt8500_write(&vt8500_port->uart, vt8500_port->ier, VT8500_URIER); spin_unlock_irqrestore(&port->lock, flags); }
static void sc26xx_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); unsigned int quot = uart_get_divisor(port, baud); unsigned int iflag, cflag; unsigned long flags; u8 mr1, mr2, csr; spin_lock_irqsave(&port->lock, flags); while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc) udelay(2); WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX); iflag = termios->c_iflag; cflag = termios->c_cflag; port->read_status_mask = SR_OVERRUN; if (iflag & INPCK) port->read_status_mask |= SR_PARITY | SR_FRAME; if (iflag & (BRKINT | PARMRK)) port->read_status_mask |= SR_BREAK; port->ignore_status_mask = 0; if (iflag & IGNBRK) port->ignore_status_mask |= SR_BREAK; if ((cflag & CREAD) == 0) port->ignore_status_mask |= SR_BREAK | SR_FRAME | SR_PARITY | SR_OVERRUN; switch (cflag & CSIZE) { case CS5: mr1 = 0x00; break; case CS6: mr1 = 0x01; break; case CS7: mr1 = 0x02; break; default: case CS8: mr1 = 0x03; break; } mr2 = 0x07; if (cflag & CSTOPB) mr2 = 0x0f; if (cflag & PARENB) { if (cflag & PARODD) mr1 |= (1 << 2); } else mr1 |= (2 << 3); switch (baud) { case 50: csr = 0x00; break; case 110: csr = 0x11; break; case 134: csr = 0x22; break; case 200: csr = 0x33; break; case 300: csr = 0x44; break; case 600: csr = 0x55; break; case 1200: csr = 0x66; break; case 2400: csr = 0x88; break; case 4800: csr = 0x99; break; default: case 9600: csr = 0xbb; break; case 19200: csr = 0xcc; break; } WRITE_SC_PORT(port, CR, CR_RES_MR); WRITE_SC_PORT(port, MRx, mr1); WRITE_SC_PORT(port, MRx, mr2); WRITE_SC(port, ACR, 0x80); WRITE_SC_PORT(port, CSR, csr); WRITE_SC_PORT(port, CR, CR_RES_RX); WRITE_SC_PORT(port, CR, CR_RES_TX); WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX); while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc) udelay(2); uart_update_timeout(port, cflag, (port->uartclk / (16 * quot))); spin_unlock_irqrestore(&port->lock, flags); }
static void serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_max3110 *max = container_of(port, struct uart_max3110, port); unsigned char cval; unsigned int baud, parity = 0; int clk_div = -1; u16 new_conf = max->cur_conf; switch (termios->c_cflag & CSIZE) { case CS7: cval = UART_LCR_WLEN7; new_conf |= WC_7BIT_WORD; break; default: /* We only support CS7 & CS8 */ termios->c_cflag &= ~CSIZE; termios->c_cflag |= CS8; case CS8: cval = UART_LCR_WLEN8; new_conf |= WC_8BIT_WORD; break; } baud = uart_get_baud_rate(port, termios, old, 0, 230400); /* First calc the div for 1.8MHZ clock case */ switch (baud) { case 300: clk_div = WC_BAUD_DR384; break; case 600: clk_div = WC_BAUD_DR192; break; case 1200: clk_div = WC_BAUD_DR96; break; case 2400: clk_div = WC_BAUD_DR48; break; case 4800: clk_div = WC_BAUD_DR24; break; case 9600: clk_div = WC_BAUD_DR12; break; case 19200: clk_div = WC_BAUD_DR6; break; case 38400: clk_div = WC_BAUD_DR3; break; case 57600: clk_div = WC_BAUD_DR2; break; case 115200: clk_div = WC_BAUD_DR1; break; case 230400: if (max->clock & MAX3110_HIGH_CLK) break; default: /* Pick the previous baud rate */ baud = max->baud; clk_div = max->cur_conf & WC_BAUD_DIV_MASK; tty_termios_encode_baud_rate(termios, baud, baud); } if (max->clock & MAX3110_HIGH_CLK) { clk_div += 1; /* High clk version max3110 doesn't support B300 */ if (baud == 300) { baud = 600; clk_div = WC_BAUD_DR384; } if (baud == 230400) clk_div = WC_BAUD_DR1; tty_termios_encode_baud_rate(termios, baud, baud); } new_conf = (new_conf & ~WC_BAUD_DIV_MASK) | clk_div; if (unlikely(termios->c_cflag & CMSPAR)) termios->c_cflag &= ~CMSPAR; if (termios->c_cflag & CSTOPB) new_conf |= WC_2_STOPBITS; else new_conf &= ~WC_2_STOPBITS; if (termios->c_cflag & PARENB) { new_conf |= WC_PARITY_ENABLE; parity |= UART_LCR_PARITY; } else new_conf &= ~WC_PARITY_ENABLE; if (!(termios->c_cflag & PARODD)) parity |= UART_LCR_EPAR; max->parity = parity; uart_update_timeout(port, termios->c_cflag, baud); new_conf |= WC_TAG; if (new_conf != max->cur_conf) { if (!max3110_out(max, new_conf)) { max->cur_conf = new_conf; max->baud = baud; } } }
static void serial_pxa_set_termios(struct uart_port *port, struct termios *termios, struct termios *old) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; unsigned char cval, fcr = 0; unsigned long flags; unsigned int baud, quot; switch (termios->c_cflag & CSIZE) { case CS5: cval = UART_LCR_WLEN5; break; case CS6: cval = UART_LCR_WLEN6; break; case CS7: cval = UART_LCR_WLEN7; break; default: case CS8: cval = UART_LCR_WLEN8; break; } if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; if (termios->c_cflag & PARENB) cval |= UART_LCR_PARITY; if (!(termios->c_cflag & PARODD)) cval |= UART_LCR_EPAR; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); if ((up->port.uartclk / quot) < (2400 * 16)) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1; else if ((up->port.uartclk / quot) < (230400 * 16)) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8; else fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32; /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ spin_lock_irqsave(&up->port.lock, flags); /* * Ensure the port will be enabled. * This is required especially for serial console. */ up->ier |= IER_UUE; /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) up->port.read_status_mask |= UART_LSR_BI; /* * Characters to ignore */ up->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { up->port.ignore_status_mask |= UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) up->port.ignore_status_mask |= UART_LSR_DR; /* * CTS flow control flag and modem status interrupts */ up->ier &= ~UART_IER_MSI; if (UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ serial_out(up, UART_LCR, cval); /* reset DLAB */ up->lcr = cval; /* Save LCR */ serial_pxa_set_mctrl(&up->port, up->port.mctrl); serial_out(up, UART_FCR, fcr); spin_unlock_irqrestore(&up->port.lock, flags); }
static void serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; unsigned char cval, fcr = 0; unsigned long flags; unsigned int baud, quot = 0; unsigned int dll; switch (termios->c_cflag & CSIZE) { case CS5: cval = UART_LCR_WLEN5; break; case CS6: cval = UART_LCR_WLEN6; break; case CS7: cval = UART_LCR_WLEN7; break; default: case CS8: cval = UART_LCR_WLEN8; break; } if (termios->c_cflag & CSTOPB) cval |= UART_LCR_STOP; if (termios->c_cflag & PARENB) cval |= UART_LCR_PARITY; if (!(termios->c_cflag & PARODD)) cval |= UART_LCR_EPAR; /* * Ask the core to calculate the divisor for us. */ baud = uart_get_baud_rate(port, termios, old, 0, 921600*16*4/16); if (baud > 921600) { port->uartclk = 921600*16*4; /* 58.9823MHz as the clk src */ if (B1500000 == (termios->c_cflag & B1500000)) quot = 2; if (B3500000 == (termios->c_cflag & B3500000)) quot = 1; if (quot == 0) quot = uart_get_divisor(port, baud); } else { quot = uart_get_divisor(port, baud); } if (up->dma_enable) { fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32 | UART_FCR_PXA_TRAIL; fcr &= ~UART_FCR_PXA_BUS32; } else { if ((up->port.uartclk / quot) < (2400 * 16)) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1; else if ((up->port.uartclk / quot) < (230400 * 16)) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8; else fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR32; } /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ spin_lock_irqsave(&up->port.lock, flags); if (baud > 921600) up->ier |= UART_IER_HSE; else up->ier &= ~UART_IER_HSE; /* * Ensure the port will be enabled. * This is required especially for serial console. */ up->ier |= UART_IER_UUE; /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; if (termios->c_iflag & INPCK) up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (termios->c_iflag & (BRKINT | PARMRK)) up->port.read_status_mask |= UART_LSR_BI; /* * Characters to ignore */ up->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; if (termios->c_iflag & IGNBRK) { up->port.ignore_status_mask |= UART_LSR_BI; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) up->port.ignore_status_mask |= UART_LSR_OE; } /* * ignore all characters if CREAD is not set */ if ((termios->c_cflag & CREAD) == 0) up->port.ignore_status_mask |= UART_LSR_DR; /* * CTS flow control flag and modem status interrupts */ if (!up->dma_enable) { /* Don't enable modem status interrupt if DMA is enabled. * Inherited from the old code. * Please also refer to serial_pxa_enable_ms(). */ up->ier &= ~UART_IER_MSI; if (UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; } serial_out(up, UART_IER, up->ier); if (termios->c_cflag & CRTSCTS) up->mcr |= UART_MCR_AFE; else up->mcr &= ~UART_MCR_AFE; serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ /* * work around Errata #75 according to Intel(R) PXA27x Processor Family * Specification Update (Nov 2005) */ dll = serial_in(up, UART_DLL); WARN_ON(dll != (quot & 0xff)); serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ serial_out(up, UART_LCR, cval); /* reset DLAB */ up->lcr = cval; /* Save LCR */ serial_pxa_set_mctrl(&up->port, up->port.mctrl); serial_out(up, UART_FCR, fcr); spin_unlock_irqrestore(&up->port.lock, flags); }
static void sirfsoc_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sirfsoc_uart_port *sirfport = to_sirfport(port); struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; unsigned long config_reg = 0; unsigned long baud_rate; unsigned long set_baud; unsigned long flags; unsigned long ic; unsigned int clk_div_reg = 0; unsigned long txfifo_op_reg, ioclk_rate; unsigned long rx_time_out; int threshold_div; u32 data_bit_len, stop_bit_len, len_val; unsigned long sample_div_reg = 0xf; ioclk_rate = port->uartclk; switch (termios->c_cflag & CSIZE) { default: case CS8: data_bit_len = 8; config_reg |= SIRFUART_DATA_BIT_LEN_8; break; case CS7: data_bit_len = 7; config_reg |= SIRFUART_DATA_BIT_LEN_7; break; case CS6: data_bit_len = 6; config_reg |= SIRFUART_DATA_BIT_LEN_6; break; case CS5: data_bit_len = 5; config_reg |= SIRFUART_DATA_BIT_LEN_5; break; } if (termios->c_cflag & CSTOPB) { config_reg |= SIRFUART_STOP_BIT_LEN_2; stop_bit_len = 2; } else stop_bit_len = 1; spin_lock_irqsave(&port->lock, flags); port->read_status_mask = uint_en->sirfsoc_rx_oflow_en; port->ignore_status_mask = 0; if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { if (termios->c_iflag & INPCK) port->read_status_mask |= uint_en->sirfsoc_frm_err_en | uint_en->sirfsoc_parity_err_en; } else { if (termios->c_iflag & INPCK) port->read_status_mask |= uint_en->sirfsoc_frm_err_en; } if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) port->read_status_mask |= uint_en->sirfsoc_rxd_brk_en; if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= uint_en->sirfsoc_frm_err_en | uint_en->sirfsoc_parity_err_en; if (termios->c_cflag & PARENB) { if (termios->c_cflag & CMSPAR) { if (termios->c_cflag & PARODD) config_reg |= SIRFUART_STICK_BIT_MARK; else config_reg |= SIRFUART_STICK_BIT_SPACE; } else { if (termios->c_cflag & PARODD) config_reg |= SIRFUART_STICK_BIT_ODD; else config_reg |= SIRFUART_STICK_BIT_EVEN; } } } else { if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= uint_en->sirfsoc_frm_err_en; if (termios->c_cflag & PARENB) dev_warn(port->dev, "USP-UART not support parity err\n"); } if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= uint_en->sirfsoc_rxd_brk_en; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= uint_en->sirfsoc_rx_oflow_en; } if ((termios->c_cflag & CREAD) == 0) port->ignore_status_mask |= SIRFUART_DUMMY_READ; /* Hardware Flow Control Settings */ if (UART_ENABLE_MS(port, termios->c_cflag)) { if (!sirfport->ms_enabled) sirfsoc_uart_enable_ms(port); } else { if (sirfport->ms_enabled) sirfsoc_uart_disable_ms(port); } baud_rate = uart_get_baud_rate(port, termios, old, 0, 4000000); if (ioclk_rate == 150000000) { for (ic = 0; ic < SIRF_BAUD_RATE_SUPPORT_NR; ic++) if (baud_rate == baudrate_to_regv[ic].baud_rate) clk_div_reg = baudrate_to_regv[ic].reg_val; } set_baud = baud_rate; if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { if (unlikely(clk_div_reg == 0)) clk_div_reg = sirfsoc_uart_calc_sample_div(baud_rate, ioclk_rate, &set_baud); wr_regl(port, ureg->sirfsoc_divisor, clk_div_reg); } else { clk_div_reg = sirfsoc_usp_calc_sample_div(baud_rate, ioclk_rate, &sample_div_reg); sample_div_reg--; set_baud = ((ioclk_rate / (clk_div_reg+1) - 1) / (sample_div_reg + 1)); /* setting usp mode 2 */ len_val = ((1 << SIRFSOC_USP_MODE2_RXD_DELAY_OFFSET) | (1 << SIRFSOC_USP_MODE2_TXD_DELAY_OFFSET)); len_val |= ((clk_div_reg & SIRFSOC_USP_MODE2_CLK_DIVISOR_MASK) << SIRFSOC_USP_MODE2_CLK_DIVISOR_OFFSET); wr_regl(port, ureg->sirfsoc_mode2, len_val); } if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, set_baud, set_baud); /* set receive timeout && data bits len */ rx_time_out = SIRFSOC_UART_RX_TIMEOUT(set_baud, 20000); rx_time_out = SIRFUART_RECV_TIMEOUT_VALUE(rx_time_out); txfifo_op_reg = rd_regl(port, ureg->sirfsoc_tx_fifo_op); wr_regl(port, ureg->sirfsoc_tx_fifo_op, (txfifo_op_reg & ~SIRFUART_FIFO_START)); if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) { config_reg |= SIRFUART_UART_RECV_TIMEOUT(rx_time_out); wr_regl(port, ureg->sirfsoc_line_ctrl, config_reg); } else { /*tx frame ctrl*/ len_val = (data_bit_len - 1) << SIRFSOC_USP_TX_DATA_LEN_OFFSET; len_val |= (data_bit_len + 1 + stop_bit_len - 1) << SIRFSOC_USP_TX_FRAME_LEN_OFFSET; len_val |= ((data_bit_len - 1) << SIRFSOC_USP_TX_SHIFTER_LEN_OFFSET); len_val |= (((clk_div_reg & 0xc00) >> 10) << SIRFSOC_USP_TX_CLK_DIVISOR_OFFSET); wr_regl(port, ureg->sirfsoc_tx_frame_ctrl, len_val); /*rx frame ctrl*/ len_val = (data_bit_len - 1) << SIRFSOC_USP_RX_DATA_LEN_OFFSET; len_val |= (data_bit_len + 1 + stop_bit_len - 1) << SIRFSOC_USP_RX_FRAME_LEN_OFFSET; len_val |= (data_bit_len - 1) << SIRFSOC_USP_RX_SHIFTER_LEN_OFFSET; len_val |= (((clk_div_reg & 0xf000) >> 12) << SIRFSOC_USP_RX_CLK_DIVISOR_OFFSET); wr_regl(port, ureg->sirfsoc_rx_frame_ctrl, len_val); /*async param*/ wr_regl(port, ureg->sirfsoc_async_param_reg, (SIRFUART_USP_RECV_TIMEOUT(rx_time_out)) | (sample_div_reg & SIRFSOC_USP_ASYNC_DIV2_MASK) << SIRFSOC_USP_ASYNC_DIV2_OFFSET); } if (sirfport->tx_dma_chan) wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_DMA_MODE); else wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE); if (sirfport->rx_dma_chan) wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) & ~SIRFUART_IO_MODE); else wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) | SIRFUART_IO_MODE); sirfport->rx_period_time = 20000000; /* Reset Rx/Tx FIFO Threshold level for proper baudrate */ if (set_baud < 1000000) threshold_div = 1; else threshold_div = 2; wr_regl(port, ureg->sirfsoc_tx_fifo_ctrl, SIRFUART_FIFO_THD(port) / threshold_div); wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port) / threshold_div); txfifo_op_reg |= SIRFUART_FIFO_START; wr_regl(port, ureg->sirfsoc_tx_fifo_op, txfifo_op_reg); uart_update_timeout(port, termios->c_cflag, set_baud); wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_TX_EN | SIRFUART_RX_EN); spin_unlock_irqrestore(&port->lock, flags); }