/* * If the port was already initialised (eg, by a boot loader), try to determine * the current setup. */ static void __init atmel_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { unsigned int mr, quot; // TODO: CR is a write-only register // unsigned int cr; // // cr = UART_GET_CR(port) & (ATMEL_US_RXEN | ATMEL_US_TXEN); // if (cr == (ATMEL_US_RXEN | ATMEL_US_TXEN)) { // /* ok, the port was enabled */ // } mr = UART_GET_MR(port) & ATMEL_US_CHRL; if (mr == ATMEL_US_CHRL_8) *bits = 8; else *bits = 7; mr = UART_GET_MR(port) & ATMEL_US_PAR; if (mr == ATMEL_US_PAR_EVEN) *parity = 'e'; else if (mr == ATMEL_US_PAR_ODD) *parity = 'o'; /* * The serial core only rounds down when matching this to a * supported baud rate. Make sure we don't end up slightly * lower than one of those, as it would make us fall through * to a much lower baud rate than we really want. */ quot = UART_GET_BRGR(port); *baud = port->uartclk / (16 * (quot - 1)); }
/* * If the port was already initialised (eg, by a boot loader), try to determine * the current setup. */ static void __init atmel_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { unsigned int mr, quot; /* * If the baud rate generator isn't running, the port wasn't * initialized by the boot loader. */ quot = UART_GET_BRGR(port); if (!quot) return; mr = UART_GET_MR(port) & ATMEL_US_CHRL; if (mr == ATMEL_US_CHRL_8) *bits = 8; else *bits = 7; mr = UART_GET_MR(port) & ATMEL_US_PAR; if (mr == ATMEL_US_PAR_EVEN) *parity = 'e'; else if (mr == ATMEL_US_PAR_ODD) *parity = 'o'; /* * The serial core only rounds down when matching this to a * supported baud rate. Make sure we don't end up slightly * lower than one of those, as it would make us fall through * to a much lower baud rate than we really want. */ *baud = port->uartclk / (16 * (quot - 1)); }
/* * If the port was already initialised (eg, by a boot loader), try to determine * the current setup. */ static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { unsigned int mr, quot; // TODO: CR is a write-only register // unsigned int cr; // // cr = UART_GET_CR(port) & (AT91_US_RXEN | AT91_US_TXEN); // if (cr == (AT91_US_RXEN | AT91_US_TXEN)) { // /* ok, the port was enabled */ // } mr = UART_GET_MR(port) & AT91_US_CHRL; if (mr == AT91_US_CHRL_8) *bits = 8; else *bits = 7; mr = UART_GET_MR(port) & AT91_US_PAR; if (mr == AT91_US_PAR_EVEN) *parity = 'e'; else if (mr == AT91_US_PAR_ODD) *parity = 'o'; quot = UART_GET_BRGR(port); *baud = port->uartclk / (16 * (quot)); }
/* * Set state of the modem control output lines */ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) { unsigned int control = 0; unsigned int mode; #ifdef CONFIG_ARCH_AT91RM9200 if (cpu_is_at91rm9200()) { /* * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21. * We need to drive the pin manually. */ if (port->mapbase == AT91RM9200_BASE_US0) { if (mctrl & TIOCM_RTS) at91_set_gpio_value(AT91_PIN_PA21, 0); else at91_set_gpio_value(AT91_PIN_PA21, 1); } } #endif if (mctrl & TIOCM_RTS) control |= ATMEL_US_RTSEN; else control |= ATMEL_US_RTSDIS; if (mctrl & TIOCM_DTR) control |= ATMEL_US_DTREN; else control |= ATMEL_US_DTRDIS; UART_PUT_CR(port, control); /* Local loopback mode? */ mode = UART_GET_MR(port) & ~ATMEL_US_CHMODE; if (mctrl & TIOCM_LOOP) mode |= ATMEL_US_CHMODE_LOC_LOOP; else mode |= ATMEL_US_CHMODE_NORMAL; UART_PUT_MR(port, mode); }
/* * Change the port parameters */ static void atmel_set_termios(struct uart_port *port, struct ktermios * termios, struct ktermios * old) { struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; unsigned long flags; unsigned int mode, imr, quot, baud; /* Get current mode register */ mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP | ATMEL_US_PAR); baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); if (quot > 65535) { /* BRGR is 16-bit, so switch to slower clock */ quot /= 8; mode |= ATMEL_US_USCLKS_MCK_DIV8; } /* byte size */ switch (termios->c_cflag & CSIZE) { case CS5: mode |= ATMEL_US_CHRL_5; break; case CS6: mode |= ATMEL_US_CHRL_6; break; case CS7: mode |= ATMEL_US_CHRL_7; break; default: mode |= ATMEL_US_CHRL_8; break; } /* stop bits */ if (termios->c_cflag & CSTOPB) mode |= ATMEL_US_NBSTOP_2; /* parity */ if (termios->c_cflag & PARENB) { if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */ if (termios->c_cflag & PARODD) mode |= ATMEL_US_PAR_MARK; else mode |= ATMEL_US_PAR_SPACE; } else if (termios->c_cflag & PARODD) mode |= ATMEL_US_PAR_ODD; else mode |= ATMEL_US_PAR_EVEN; } else mode |= ATMEL_US_PAR_NONE; spin_lock_irqsave(&port->lock, flags); port->read_status_mask = ATMEL_US_OVRE; if (termios->c_iflag & INPCK) port->read_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE); if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= ATMEL_US_RXBRK; if (atmel_port->use_dma_rx) /* need to enable error interrupts */ UART_PUT_IER(port, port->read_status_mask); /* * Characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) port->ignore_status_mask |= (ATMEL_US_FRAME | ATMEL_US_PARE); if (termios->c_iflag & IGNBRK) { port->ignore_status_mask |= ATMEL_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 |= ATMEL_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) & ATMEL_US_TXEMPTY)) cpu_relax(); /* disable receiver and transmitter */ UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_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, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_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); }