drivers: imx: uart: Add mxc_console

- Adds a simple register read/write abstraction to cut-down on the
  amount of typing and text required to access UART registers in this driver.

- Adds a console getc() callback.

- Adds a console putc() callback, translating '\n' to '\r' + '\n'.

- Initializes the MXC UART, take a crude method of calculating the
  BAUD rate generator. The UART clock-gates must have been enabled prior
  to launching the UART init code.
  Special care needs to be taken to ensure the UBIR is initialized before the
  UBMR and we need to ensure that UCR2.SRST comes good before trying to
  program other registers associated with the UART.

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
diff --git a/drivers/imx/uart/imx_uart.c b/drivers/imx/uart/imx_uart.c
new file mode 100644
index 0000000..0250a41
--- /dev/null
+++ b/drivers/imx/uart/imx_uart.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) Linaro 2018 Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch.h>
+#include <stdint.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <imx_uart.h>
+
+/* TX/RX FIFO threshold */
+#define TX_RX_THRESH 2
+
+struct clk_div_factors {
+	uint32_t fcr_div;
+	uint32_t bmr_div;
+};
+
+static struct clk_div_factors clk_div[] = {
+	{
+		.fcr_div = IMX_UART_FCR_RFDIV1,
+		.bmr_div = 1,
+	},
+	{
+		.fcr_div = IMX_UART_FCR_RFDIV2,
+		.bmr_div = 2,
+	},
+	{
+		.fcr_div = IMX_UART_FCR_RFDIV3,
+		.bmr_div = 3,
+	},
+	{
+		.fcr_div = IMX_UART_FCR_RFDIV4,
+		.bmr_div = 4,
+	},
+	{
+		.fcr_div = IMX_UART_FCR_RFDIV5,
+		.bmr_div = 5,
+	},
+	{
+		.fcr_div = IMX_UART_FCR_RFDIV6,
+		.bmr_div = 6,
+	},
+	{
+		.fcr_div = IMX_UART_FCR_RFDIV7,
+		.bmr_div = 7,
+	},
+};
+
+static void write_reg(uintptr_t base, uint32_t offset, uint32_t val)
+{
+	mmio_write_32(base + offset, val);
+}
+
+static uint32_t read_reg(uintptr_t base, uint32_t offset)
+{
+	return mmio_read_32(base + offset);
+}
+
+int console_core_init(uintptr_t base_addr, unsigned int uart_clk,
+		      unsigned int baud_rate)
+{
+	uint32_t val;
+	uint8_t clk_idx = 1;
+
+	/* Reset UART */
+	write_reg(base_addr, IMX_UART_CR2_OFFSET, 0);
+	do {
+		val = read_reg(base_addr, IMX_UART_CR2_OFFSET);
+	} while (!(val & IMX_UART_CR2_SRST));
+
+	/* Enable UART */
+	write_reg(base_addr, IMX_UART_CR1_OFFSET, IMX_UART_CR1_UARTEN);
+
+	/* Ignore RTS, 8N1, enable tx/rx, disable reset */
+	val = (IMX_UART_CR2_IRTS | IMX_UART_CR2_WS | IMX_UART_CR2_TXEN |
+	       IMX_UART_CR2_RXEN | IMX_UART_CR2_SRST);
+	write_reg(base_addr, IMX_UART_CR2_OFFSET, val);
+
+	/* No parity, autobaud detect-old, rxdmuxsel=1 (fixed i.mx7) */
+	val = IMX_UART_CR3_ADNIMP | IMX_UART_CR3_RXDMUXSEL;
+	write_reg(base_addr, IMX_UART_CR3_OFFSET, val);
+
+	/* Set CTS FIFO trigger to 32 bytes bits 15:10 */
+	write_reg(base_addr, IMX_UART_CR4_OFFSET, 0x8000);
+
+	/* TX/RX-thresh = 2 bytes, DTE (bit6 = 0), refclk @24MHz / 4 */
+	val = IMX_UART_FCR_TXTL(TX_RX_THRESH) | IMX_UART_FCR_RXTL(TX_RX_THRESH) |
+	      clk_div[clk_idx].fcr_div;
+	#ifdef IMX_UART_DTE
+		/* Set DTE (bit6 = 1) */
+		val |= IMX_UART_FCR_DCEDTE;
+	#endif
+	write_reg(base_addr, IMX_UART_FCR_OFFSET, val);
+
+	/*
+	 * The equation for BAUD rate calculation is
+	 * RefClk = Supplied clock / FCR_DIVx
+	 *
+	 * BAUD  =    Refclk
+	 *         ------------
+	 *       16 x (UBMR + 1/ UBIR + 1)
+	 *
+	 * We write 0x0f into UBIR to remove the 16 mult
+	 * BAUD  =    6000000
+	 *         ------------
+	 *       16 x (UBMR + 1/ 15 + 1)
+	 */
+
+	write_reg(base_addr, IMX_UART_BIR_OFFSET, 0x0f);
+	val = ((uart_clk / clk_div[clk_idx].bmr_div) / baud_rate) - 1;
+	write_reg(base_addr, IMX_UART_BMR_OFFSET, val);
+
+	return 0;
+}
+
+/* --------------------------------------------------------
+ * int console_core_putc(int c, uintptr_t base_addr)
+ * Function to output a character over the console. It
+ * returns the character printed on success or -1 on error.
+ * In : r0 - character to be printed
+ *      r1 - console base address
+ * Out : return -1 on error else return character.
+ * Clobber list : r2
+ * --------------------------------------------------------
+ */
+int console_core_putc(int c, uintptr_t base_addr)
+{
+	uint32_t val;
+
+	if (c == '\n')
+		console_core_putc('\r', base_addr);
+
+	/* Write data */
+	write_reg(base_addr, IMX_UART_TXD_OFFSET, c);
+
+	/* Wait for transmit */
+	do {
+		val = read_reg(base_addr, IMX_UART_STAT2_OFFSET);
+	} while (!(val & IMX_UART_STAT2_TXDC));
+
+	return 0;
+}
+
+/*
+ * Function to get a character from the console.
+ * It returns the character grabbed on success
+ * or -1 on error.
+ * In : r0 - console base address
+ * Clobber list : r0, r1
+ * ---------------------------------------------
+ */
+int console_core_getc(uintptr_t base_addr)
+{
+	uint32_t val;
+
+	val = read_reg(base_addr, IMX_UART_TS_OFFSET);
+	if (val & IMX_UART_TS_RXEMPTY)
+		return -1;
+
+	val = read_reg(base_addr, IMX_UART_RXD_OFFSET);
+	return (int)(val & 0x000000FF);
+}
+
+/*
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * In : r0 - console base address
+ * Out : return -1 on error else return 0.
+ * Clobber list : r0, r1
+ * ---------------------------------------------
+ */
+int console_core_flush(uintptr_t base_addr)
+{
+	return 0;
+}
+
diff --git a/drivers/imx/uart/imx_uart.h b/drivers/imx/uart/imx_uart.h
new file mode 100644
index 0000000..de42125
--- /dev/null
+++ b/drivers/imx/uart/imx_uart.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) Linaro 2018 Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __IMX_CONSOLE_H__
+#define __IMX_CONSOLE_H__
+
+#define IMX_UART_RXD_OFFSET	0x00
+#define IMX_UART_RXD_CHARRDY	BIT(15)
+#define IMX_UART_RXD_ERR	BIT(14)
+#define IMX_UART_RXD_OVERRUN	BIT(13)
+#define IMX_UART_RXD_FRMERR	BIT(12)
+#define IMX_UART_RXD_BRK	BIT(11)
+#define IMX_UART_RXD_PRERR	BIT(10)
+
+#define IMX_UART_TXD_OFFSET	0x40
+
+#define IMX_UART_CR1_OFFSET	0x80
+#define IMX_UART_CR1_ADEN	BIT(15)
+#define IMX_UART_CR1_ADBR	BIT(14)
+#define IMX_UART_CR1_TRDYEN	BIT(13)
+#define IMX_UART_CR1_IDEN	BIT(12)
+#define IMX_UART_CR1_RRDYEN	BIT(9)
+#define IMX_UART_CR1_RXDMAEN	BIT(8)
+#define IMX_UART_CR1_IREN	BIT(7)
+#define IMX_UART_CR1_TXMPTYEN	BIT(6)
+#define IMX_UART_CR1_RTSDEN	BIT(5)
+#define IMX_UART_CR1_SNDBRK	BIT(4)
+#define IMX_UART_CR1_TXDMAEN	BIT(3)
+#define IMX_UART_CR1_ATDMAEN	BIT(2)
+#define IMX_UART_CR1_DOZE	BIT(1)
+#define IMX_UART_CR1_UARTEN	BIT(0)
+
+#define IMX_UART_CR2_OFFSET	0x84
+#define IMX_UART_CR2_ESCI	BIT(15)
+#define IMX_UART_CR2_IRTS	BIT(14)
+#define IMX_UART_CR2_CTSC	BIT(13)
+#define IMX_UART_CR2_CTS	BIT(12)
+#define IMX_UART_CR2_ESCEN	BIT(11)
+#define IMX_UART_CR2_PREN	BIT(8)
+#define IMX_UART_CR2_PROE	BIT(7)
+#define IMX_UART_CR2_STPB	BIT(6)
+#define IMX_UART_CR2_WS		BIT(5)
+#define IMX_UART_CR2_RTSEN	BIT(4)
+#define IMX_UART_CR2_ATEN	BIT(3)
+#define IMX_UART_CR2_TXEN	BIT(2)
+#define IMX_UART_CR2_RXEN	BIT(1)
+#define IMX_UART_CR2_SRST	BIT(0)
+
+#define IMX_UART_CR3_OFFSET	0x88
+#define IMX_UART_CR3_DTREN	BIT(13)
+#define IMX_UART_CR3_PARERREN	BIT(12)
+#define IMX_UART_CR3_FARERREN	BIT(11)
+#define IMX_UART_CR3_DSD	BIT(10)
+#define IMX_UART_CR3_DCD	BIT(9)
+#define IMX_UART_CR3_RI		BIT(8)
+#define IMX_UART_CR3_ADNIMP	BIT(7)
+#define IMX_UART_CR3_RXDSEN	BIT(6)
+#define IMX_UART_CR3_AIRINTEN	BIT(5)
+#define IMX_UART_CR3_AWAKEN	BIT(4)
+#define IMX_UART_CR3_DTRDEN	BIT(3)
+#define IMX_UART_CR3_RXDMUXSEL	BIT(2)
+#define IMX_UART_CR3_INVT	BIT(1)
+#define IMX_UART_CR3_ACIEN	BIT(0)
+
+#define IMX_UART_CR4_OFFSET	0x8c
+#define IMX_UART_CR4_INVR	BIT(9)
+#define IMX_UART_CR4_ENIRI	BIT(8)
+#define IMX_UART_CR4_WKEN	BIT(7)
+#define IMX_UART_CR4_IDDMAEN	BIT(6)
+#define IMX_UART_CR4_IRSC	BIT(5)
+#define IMX_UART_CR4_LPBYP	BIT(4)
+#define IMX_UART_CR4_TCEN	BIT(3)
+#define IMX_UART_CR4_BKEN	BIT(2)
+#define IMX_UART_CR4_OREN	BIT(1)
+#define IMX_UART_CR4_DREN	BIT(0)
+
+#define IMX_UART_FCR_OFFSET	0x90
+#define IMX_UART_FCR_TXTL_MASK	(BIT(15) | BIT(14) | BIT(13) | BIT(12) |\
+				 BIT(11) | BIT(10))
+#define IMX_UART_FCR_TXTL(x)	((x) << 10)
+#define IMX_UART_FCR_RFDIV_MASK	(BIT(9) | BIT(8) | BIT(7))
+#define IMX_UART_FCR_RFDIV7	(BIT(9) | BIT(8))
+#define IMX_UART_FCR_RFDIV1	(BIT(9) | BIT(7))
+#define IMX_UART_FCR_RFDIV2	BIT(9)
+#define IMX_UART_FCR_RFDIV3	(BIT(8) | BIT(7))
+#define IMX_UART_FCR_RFDIV4	BIT(8)
+#define IMX_UART_FCR_RFDIV5	BIT(7)
+#define IMX_UART_FCR_RFDIV6	0
+#define IMX_UART_FCR_DCEDTE	BIT(6)
+#define IMX_UART_FCR_RXTL_MASK	(BIT(5) | BIT(4) | BIT(3) | BIT(2) |\
+				 BIT(1) | BIT(0))
+#define IMX_UART_FCR_RXTL(x)	x
+
+#define IMX_UART_STAT1_OFFSET	0x94
+#define IMX_UART_STAT1_PARITYERR	BIT(15)
+#define IMX_UART_STAT1_RTSS	BIT(14)
+#define IMX_UART_STAT1_TRDY	BIT(13)
+#define IMX_UART_STAT1_RTSD	BIT(12)
+#define IMX_UART_STAT1_ESCF	BIT(11)
+#define IMX_UART_STAT1_FRAMEERR	BIT(10)
+#define IMX_UART_STAT1_RRDY	BIT(9)
+#define IMX_UART_STAT1_AGTIM	BIT(8)
+#define IMX_UART_STAT1_DTRD	BIT(7)
+#define IMX_UART_STAT1_RXDS	BIT(6)
+#define IMX_UART_STAT1_AIRINT	BIT(5)
+#define IMX_UART_STAT1_AWAKE	BIT(4)
+#define IMX_UART_STAT1_SAD	BIT(3)
+
+#define IMX_UART_STAT2_OFFSET	0x98
+#define IMX_UART_STAT2_ADET	BIT(15)
+#define IMX_UART_STAT2_TXFE	BIT(14)
+#define IMX_UART_STAT2_DTRF	BIT(13)
+#define IMX_UART_STAT2_IDLE	BIT(12)
+#define IMX_UART_STAT2_ACST	BIT(11)
+#define IMX_UART_STAT2_RIDELT	BIT(10)
+#define IMX_UART_STAT2_RIIN	BIT(9)
+#define IMX_UART_STAT2_IRINT	BIT(8)
+#define IMX_UART_STAT2_WAKE	BIT(7)
+#define IMX_UART_STAT2_DCDDELT	BIT(6)
+#define IMX_UART_STAT2_DCDIN	BIT(5)
+#define IMX_UART_STAT2_RTSF	BIT(4)
+#define IMX_UART_STAT2_TXDC	BIT(3)
+#define IMX_UART_STAT2_BRCD	BIT(2)
+#define IMX_UART_STAT2_ORE	BIT(1)
+#define IMX_UART_STAT2_RCR	BIT(0)
+
+#define IMX_UART_ESC_OFFSET	0x9c
+
+#define IMX_UART_TIM_OFFSET	0xa0
+
+#define IMX_UART_BIR_OFFSET	0xa4
+
+#define IMX_UART_BMR_OFFSET	0xa8
+
+#define IMX_UART_BRC_OFFSET	0xac
+
+#define IMX_UART_ONEMS_OFFSET	0xb0
+
+#define IMX_UART_TS_OFFSET	0xb4
+#define IMX_UART_TS_FRCPERR	BIT(13)
+#define IMX_UART_TS_LOOP	BIT(12)
+#define IMX_UART_TS_DBGEN	BIT(11)
+#define IMX_UART_TS_LOOPIR	BIT(10)
+#define IMX_UART_TS_RXDBG	BIT(9)
+#define IMX_UART_TS_TXEMPTY	BIT(6)
+#define IMX_UART_TS_RXEMPTY	BIT(5)
+#define IMX_UART_TS_TXFULL	BIT(4)
+#define IMX_UART_TS_RXFULL	BIT(3)
+#define IMX_UART_TS_SOFTRST	BIT(0)
+
+#endif /* __IMX_UART_H__ */