1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Texas Instruments' OMAP serial driver 4 * 5 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ 6 * Lokesh Vutla <lokeshvutla@ti.com> 7 */ 8 9 #include <common.h> 10 #include <debug_uart.h> 11 #include <dm.h> 12 #include <dt-structs.h> 13 #include <ns16550.h> 14 #include <serial.h> 15 #include <clk.h> 16 17 #ifndef CONFIG_SYS_NS16550_CLK 18 #define CONFIG_SYS_NS16550_CLK 0 19 #endif 20 21 #ifdef CONFIG_DEBUG_UART_OMAP 22 23 #include <debug_uart.h> 24 25 static inline void _debug_uart_init(void) 26 { 27 struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; 28 int baud_divisor; 29 30 baud_divisor = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK, 31 CONFIG_BAUDRATE); 32 serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER); 33 serial_dout(&com_port->mdr1, 0x7); 34 serial_dout(&com_port->mcr, UART_MCRVAL); 35 serial_dout(&com_port->fcr, UART_FCR_DEFVAL); 36 37 serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL); 38 serial_dout(&com_port->dll, baud_divisor & 0xff); 39 serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff); 40 serial_dout(&com_port->lcr, UART_LCRVAL); 41 serial_dout(&com_port->mdr1, 0x0); 42 } 43 44 static inline void _debug_uart_putc(int ch) 45 { 46 struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; 47 48 while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) 49 ; 50 serial_dout(&com_port->thr, ch); 51 } 52 53 DEBUG_UART_FUNCS 54 55 #endif 56 57 #if CONFIG_IS_ENABLED(DM_SERIAL) 58 59 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 60 static int omap_serial_ofdata_to_platdata(struct udevice *dev) 61 { 62 struct ns16550_platdata *plat = dev->platdata; 63 fdt_addr_t addr; 64 struct clk clk; 65 int err; 66 67 /* try Processor Local Bus device first */ 68 addr = dev_read_addr(dev); 69 if (addr == FDT_ADDR_T_NONE) 70 return -EINVAL; 71 72 plat->base = (unsigned long)map_physmem(addr, 0, MAP_NOCACHE); 73 74 plat->reg_offset = dev_read_u32_default(dev, "reg-offset", 0); 75 plat->reg_shift = 2; 76 77 err = clk_get_by_index(dev, 0, &clk); 78 if (!err) { 79 err = clk_get_rate(&clk); 80 if (!IS_ERR_VALUE(err)) 81 plat->clock = err; 82 } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) { 83 debug("omap serial failed to get clock\n"); 84 return err; 85 } 86 87 if (!plat->clock) 88 plat->clock = dev_read_u32_default(dev, "clock-frequency", 89 CONFIG_SYS_NS16550_CLK); 90 if (!plat->clock) { 91 debug("omap serial clock not defined\n"); 92 return -EINVAL; 93 } 94 95 plat->fcr = UART_FCR_DEFVAL; 96 97 return 0; 98 } 99 100 static const struct udevice_id omap_serial_ids[] = { 101 { .compatible = "ti,omap2-uart", }, 102 { .compatible = "ti,omap3-uart", }, 103 { .compatible = "ti,omap4-uart", }, 104 { .compatible = "ti,am3352-uart", }, 105 { .compatible = "ti,am4372-uart", }, 106 { .compatible = "ti,dra742-uart", }, 107 {} 108 }; 109 #endif /* OF_CONTROL && !OF_PLATDATA */ 110 111 #if CONFIG_IS_ENABLED(SERIAL_PRESENT) 112 U_BOOT_DRIVER(omap_serial) = { 113 .name = "omap_serial", 114 .id = UCLASS_SERIAL, 115 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 116 .of_match = omap_serial_ids, 117 .ofdata_to_platdata = omap_serial_ofdata_to_platdata, 118 .platdata_auto_alloc_size = sizeof(struct ns16550_platdata), 119 #endif 120 .priv_auto_alloc_size = sizeof(struct NS16550), 121 .probe = ns16550_serial_probe, 122 .ops = &ns16550_serial_ops, 123 .flags = DM_FLAG_PRE_RELOC, 124 }; 125 #endif 126 #endif /* DM_SERIAL */ 127