summaryrefslogtreecommitdiff
path: root/drivers/serial/ns16550.c
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2015-01-26 18:27:09 -0700
committerSimon Glass <sjg@chromium.org>2015-02-19 06:20:28 -0700
commit21d004368fc8a4da07147c58dfe9a4e16d4ab761 (patch)
tree0d6b2bc4ce8caf0d56e74084c66f05d761d28ed7 /drivers/serial/ns16550.c
parent765716744f6743d6c1e6b3c92eea163b4ee59f3c (diff)
downloadu-boot-imx-21d004368fc8a4da07147c58dfe9a4e16d4ab761.zip
u-boot-imx-21d004368fc8a4da07147c58dfe9a4e16d4ab761.tar.gz
u-boot-imx-21d004368fc8a4da07147c58dfe9a4e16d4ab761.tar.bz2
serial: ns16550: Support debug UART
Add debug UART functions to permit ns16550 to provide an early debug UART. Try to avoid using the stack so that this can be called from assembler before a stack is set up (at least on ARM and PowerPC). Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/serial/ns16550.c')
-rw-r--r--drivers/serial/ns16550.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 57e6125..eb00f1c 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -118,10 +118,15 @@ static int ns16550_readb(NS16550_t port, int offset)
ns16550_readb(com_port, addr - (unsigned char *)com_port)
#endif
-int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate)
+static inline int calc_divisor(NS16550_t port, int clock, int baudrate)
{
const unsigned int mode_x_div = 16;
+ return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate);
+}
+
+int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate)
+{
#ifdef CONFIG_OMAP1510
/* If can't cleanly clock 115200 set div to 1 */
if ((clock == 12000000) && (baudrate == 115200)) {
@@ -131,7 +136,7 @@ int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate)
port->osc_12m_sel = 0; /* clear if previsouly set */
#endif
- return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate);
+ return calc_divisor(port, clock, baudrate);
}
static void NS16550_setbrg(NS16550_t com_port, int baud_divisor)
@@ -231,6 +236,47 @@ int NS16550_tstc(NS16550_t com_port)
#endif /* CONFIG_NS16550_MIN_FUNCTIONS */
+#ifdef CONFIG_DEBUG_UART_NS16550
+
+#include <debug_uart.h>
+
+void debug_uart_init(void)
+{
+ struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
+ int baud_divisor;
+
+ /*
+ * We copy the code from above because it is already horribly messy.
+ * Trying to refactor to nicely remove the duplication doesn't seem
+ * feasible. The better fix is to move all users of this driver to
+ * driver model.
+ */
+ baud_divisor = calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
+ CONFIG_BAUDRATE);
+
+ serial_out_shift(&com_port->ier, 0, CONFIG_SYS_NS16550_IER);
+ serial_out_shift(&com_port->mcr, 0, UART_MCRVAL);
+ serial_out_shift(&com_port->fcr, 0, UART_FCRVAL);
+
+ serial_out_shift(&com_port->lcr, 0, UART_LCR_BKSE | UART_LCRVAL);
+ serial_out_shift(&com_port->dll, 0, baud_divisor & 0xff);
+ serial_out_shift(&com_port->dlm, 0, (baud_divisor >> 8) & 0xff);
+ serial_out_shift(&com_port->lcr, 0, UART_LCRVAL);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
+
+ while (!(serial_in_shift(&com_port->lsr, 0) & UART_LSR_THRE))
+ ;
+ serial_out_shift(&com_port->thr, 0, ch);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
+
#ifdef CONFIG_DM_SERIAL
static int ns16550_serial_putc(struct udevice *dev, const char ch)
{