static void serial_out_dynamic(struct ns16550_plat *plat, u8 *addr,
int value)
{
- if (plat->reg_width == 4) {
+ if (plat->flags & NS16550_FLAG_IO) {
+ outb(value, addr);
+ } else if (plat->reg_width == 4) {
if (plat->flags & NS16550_FLAG_ENDIAN) {
if (plat->flags & NS16550_FLAG_BE)
out_be32(addr, value);
static int serial_in_dynamic(struct ns16550_plat *plat, u8 *addr)
{
- if (plat->reg_width == 4) {
+ if (plat->flags & NS16550_FLAG_IO) {
+ return inb(addr);
+ } else if (plat->reg_width == 4) {
if (plat->flags & NS16550_FLAG_ENDIAN) {
if (plat->flags & NS16550_FLAG_BE)
return in_be32(addr);
void ns16550_init(struct ns16550 *com_port, int baud_divisor)
{
+#if defined(CONFIG_XPL_BUILD) && defined(CONFIG_OMAP34XX)
+ /*
+ * On some OMAP3/OMAP4 devices when UART3 is configured for boot mode
+ * before SPL starts only THRE bit is set. We have to empty the
+ * transmitter before initialization starts.
+ */
+ if ((serial_in(&com_port->lsr) & (UART_LSR_TEMT | UART_LSR_THRE))
+ == UART_LSR_THRE) {
+ if (baud_divisor != -1)
+ ns16550_setbrg(com_port, baud_divisor);
+ else {
+ // Re-use old baud rate divisor to flush transmit reg.
+ const int dll = serial_in(&com_port->dll);
+ const int dlm = serial_in(&com_port->dlm);
+ const int divisor = dll | (dlm << 8);
+ ns16550_setbrg(com_port, divisor);
+ }
+ serial_out(0, &com_port->mdr1);
+ }
+#endif
+
+ while (!(serial_in(&com_port->lsr) & UART_LSR_TEMT))
+ ;
+
+ serial_out(CFG_SYS_NS16550_IER, &com_port->ier);
+#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_OMAP_SERIAL)
+ serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/
+#endif
+
+ serial_out(UART_MCRVAL, &com_port->mcr);
+ serial_out(ns16550_getfcr(com_port), &com_port->fcr);
+ /* initialize serial config to 8N1 before writing baudrate */
+ serial_out(UART_LCRVAL, &com_port->lcr);
+ if (baud_divisor != -1)
+ ns16550_setbrg(com_port, baud_divisor);
+#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_SOC_DA8XX) || \
+ defined(CONFIG_OMAP_SERIAL)
+ /* /16 is proper to hit 115200 with 48MHz */
+ serial_out(0, &com_port->mdr1);
+#endif
+#if defined(CONFIG_ARCH_KEYSTONE)
+ serial_out(UART_REG_VAL_PWREMU_MGMT_UART_ENABLE, &com_port->regC);
+#endif
}
#if !CONFIG_IS_ENABLED(NS16550_MIN_FUNCTIONS)
static inline void _debug_uart_init(void)
{
- //struct ns16550 *com_port = (struct ns16550 *)CONFIG_VAL(DEBUG_UART_BASE);
- //int baud_divisor;
+ struct ns16550 *com_port = (struct ns16550 *)CONFIG_VAL(DEBUG_UART_BASE);
+ int baud_divisor;
/* Wait until tx buffer is empty */
- /*
while (!(serial_din(&com_port->lsr) & UART_LSR_TEMT))
;
- */
+
/*
* 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 = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
CONFIG_BAUDRATE);
serial_dout(&com_port->ier, CFG_SYS_NS16550_IER);
serial_dout(&com_port->dll, baud_divisor & 0xff);
serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff);
serial_dout(&com_port->lcr, UART_LCRVAL);
- */
}
static inline int NS16550_read_baud_divisor(struct ns16550 *com_port)