void octeon_set_baud(uint32_t uart, uint32_t baud) { uint16_t divisor; uint8_t uart_index = GET_UART_INDEX(uart); uint8_t node = GET_UART_NODE(uart); cvmx_uart_lcr_t lcrval; divisor = compute_divisor(octeon_get_ioclk_hz(), baud); lcrval.u64 = cvmx_read_csr_node(node, CVMX_MIO_UARTX_LCR(uart_index)); cvmx_wait((2 * divisor * 16) + 10000); lcrval.s.dlab = 1; /* temporary to program the divisor */ cvmx_write_csr_node(node, CVMX_MIO_UARTX_LCR(uart_index), lcrval.u64); cvmx_write_csr_node(node, CVMX_MIO_UARTX_DLL(uart_index), divisor & 0xff); cvmx_write_csr_node(node, CVMX_MIO_UARTX_DLH(uart_index), (divisor >> 8) & 0xff); /* divisor is programmed now, set this back to normal */ lcrval.s.dlab = 0; cvmx_write_csr_node(node, CVMX_MIO_UARTX_LCR(uart_index), lcrval.u64); #ifndef CONFIG_OCTEON_SIM_SPEED /* spec says need to wait after you program the divisor */ cvmx_wait((2 * divisor * 16) + 10000); /* Wait a little longer..... */ mdelay(5); #endif }
int uart_configure(unsigned int uart_num, uint32_t baudrate) { UxMODE(uart_num) = 0; UxSTA(uart_num) = 0; return compute_divisor(uart_num, baudrate); }
/** * Function that does the real work of setting up the Octeon uart. * Takes all parameters as arguments, so it does not require gd * structure to be set up. * * @param uart_index Index of uart to configure * @param cpu_clock_hertz * CPU clock frequency in Hz * @param baudrate Baudrate to configure * * @return 0 on success * !0 on error */ int octeon_uart_setup2(int uart, int cpu_clock_hertz, int baudrate) { uint16_t divisor; cvmx_uart_fcr_t fcrval; cvmx_uart_mcr_t mcrval; cvmx_uart_lcr_t lcrval; uint8_t uart_index = GET_UART_INDEX(uart); uint8_t node = GET_UART_NODE(uart); #if !CONFIG_OCTEON_SIM_SPEED uint64_t read_cycle; #endif fcrval.u64 = 0; fcrval.s.en = 1; /* enable the FIFO's */ fcrval.s.rxfr = 1; /* reset the RX fifo */ fcrval.s.txfr = 1; /* reset the TX fifo */ divisor = compute_divisor(cpu_clock_hertz, baudrate); cvmx_write_csr_node(node, CVMX_MIO_UARTX_FCR(uart_index), fcrval.u64); mcrval.u64 = 0; #if CONFIG_OCTEON_SIM_SETUP if (uart_index == 1) mcrval.s.afce = 1; /* enable auto flow control for * simulator. Needed for gdb * regression callfuncs.exp. */ else mcrval.s.afce = 0; /* disable auto flow control so board * can power on without serial port * connected */ #else mcrval.s.afce = 0; /* disable auto flow control so board can power * on without serial port connected */ #endif mcrval.s.rts = 1; /* looks like this must be set for auto flow * control to work */ cvmx_read_csr_node(node, CVMX_MIO_UARTX_LSR(uart_index)); lcrval.u64 = 0; lcrval.s.cls = CVMX_UART_BITS8; lcrval.s.stop = 0; /* stop bit included? */ lcrval.s.pen = 0; /* no parity? */ lcrval.s.eps = 1; /* even parity? */ lcrval.s.dlab = 1; /* temporary to program the divisor */ cvmx_write_csr_node(node, CVMX_MIO_UARTX_LCR(uart_index), lcrval.u64); cvmx_write_csr_node(node, CVMX_MIO_UARTX_DLL(uart_index), divisor & 0xff); cvmx_write_csr_node(node, CVMX_MIO_UARTX_DLH(uart_index), (divisor >> 8) & 0xff); /* divisor is programmed now, set this back to normal */ lcrval.s.dlab = 0; cvmx_write_csr_node(node, CVMX_MIO_UARTX_LCR(uart_index), lcrval.u64); #if !CONFIG_OCTEON_SIM_SPEED /* spec says need to wait after you program the divisor */ read_cycle = octeon_get_cycles() + (2 * divisor * 16) + 10000; while (octeon_get_cycles() < read_cycle) { /* Spin */ } #endif /* Don't enable flow control until after baud rate is configured. - we * don't want to allow characters in until after the baud rate is * fully configured */ cvmx_write_csr_node(node, CVMX_MIO_UARTX_MCR(uart_index), mcrval.u64); return 0; }