11378df79SJean-Christophe PLAGNIOL-VILLARD /* 21378df79SJean-Christophe PLAGNIOL-VILLARD * COM1 NS16550 support 3a47a12beSStefan Roese * originally from linux source (arch/powerpc/boot/ns16550.c) 46d0f6bcfSJean-Christophe PLAGNIOL-VILLARD * modified to use CONFIG_SYS_ISA_MEM and new defines 51378df79SJean-Christophe PLAGNIOL-VILLARD */ 61378df79SJean-Christophe PLAGNIOL-VILLARD 7fa54eb12SSimon Glass #include <common.h> 812e431b2SSimon Glass #include <dm.h> 912e431b2SSimon Glass #include <errno.h> 1012e431b2SSimon Glass #include <fdtdec.h> 111378df79SJean-Christophe PLAGNIOL-VILLARD #include <ns16550.h> 1212e431b2SSimon Glass #include <serial.h> 13a1b322a9SLadislav Michl #include <watchdog.h> 14167cdad1SGraeme Russ #include <linux/types.h> 15167cdad1SGraeme Russ #include <asm/io.h> 161378df79SJean-Christophe PLAGNIOL-VILLARD 1712e431b2SSimon Glass DECLARE_GLOBAL_DATA_PTR; 1812e431b2SSimon Glass 19200779e3SDetlev Zundel #define UART_LCRVAL UART_LCR_8N1 /* 8 data, 1 stop, no parity */ 20200779e3SDetlev Zundel #define UART_MCRVAL (UART_MCR_DTR | \ 21200779e3SDetlev Zundel UART_MCR_RTS) /* RTS/DTR */ 22200779e3SDetlev Zundel #define UART_FCRVAL (UART_FCR_FIFO_EN | \ 23200779e3SDetlev Zundel UART_FCR_RXSR | \ 24200779e3SDetlev Zundel UART_FCR_TXSR) /* Clear & enable FIFOs */ 2512e431b2SSimon Glass 2612e431b2SSimon Glass #ifndef CONFIG_DM_SERIAL 27167cdad1SGraeme Russ #ifdef CONFIG_SYS_NS16550_PORT_MAPPED 28167cdad1SGraeme Russ #define serial_out(x, y) outb(x, (ulong)y) 29167cdad1SGraeme Russ #define serial_in(y) inb((ulong)y) 3079df1208SDave Aldridge #elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE > 0) 3179df1208SDave Aldridge #define serial_out(x, y) out_be32(y, x) 3279df1208SDave Aldridge #define serial_in(y) in_be32(y) 3379df1208SDave Aldridge #elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE < 0) 3479df1208SDave Aldridge #define serial_out(x, y) out_le32(y, x) 3579df1208SDave Aldridge #define serial_in(y) in_le32(y) 36167cdad1SGraeme Russ #else 37167cdad1SGraeme Russ #define serial_out(x, y) writeb(x, y) 38167cdad1SGraeme Russ #define serial_in(y) readb(y) 39167cdad1SGraeme Russ #endif 4012e431b2SSimon Glass #endif /* !CONFIG_DM_SERIAL */ 411378df79SJean-Christophe PLAGNIOL-VILLARD 427c387646SKhoronzhuk, Ivan #if defined(CONFIG_SOC_KEYSTONE) 43ef509b90SVitaly Andrianov #define UART_REG_VAL_PWREMU_MGMT_UART_DISABLE 0 44ef509b90SVitaly Andrianov #define UART_REG_VAL_PWREMU_MGMT_UART_ENABLE ((1 << 14) | (1 << 13) | (1 << 0)) 45d57dee57SKaricheri, Muralidharan #undef UART_MCRVAL 46d57dee57SKaricheri, Muralidharan #ifdef CONFIG_SERIAL_HW_FLOW_CONTROL 47d57dee57SKaricheri, Muralidharan #define UART_MCRVAL (UART_MCR_RTS | UART_MCR_AFE) 48d57dee57SKaricheri, Muralidharan #else 49d57dee57SKaricheri, Muralidharan #define UART_MCRVAL (UART_MCR_RTS) 50d57dee57SKaricheri, Muralidharan #endif 51ef509b90SVitaly Andrianov #endif 52ef509b90SVitaly Andrianov 53a160ea0bSPrafulla Wadaskar #ifndef CONFIG_SYS_NS16550_IER 54a160ea0bSPrafulla Wadaskar #define CONFIG_SYS_NS16550_IER 0x00 55a160ea0bSPrafulla Wadaskar #endif /* CONFIG_SYS_NS16550_IER */ 56a160ea0bSPrafulla Wadaskar 5712e431b2SSimon Glass #ifdef CONFIG_DM_SERIAL 5876571674SSimon Glass 5976571674SSimon Glass static inline void serial_out_shift(unsigned char *addr, int shift, int value) 6076571674SSimon Glass { 6176571674SSimon Glass #ifdef CONFIG_SYS_NS16550_PORT_MAPPED 6276571674SSimon Glass outb(value, (ulong)addr); 6376571674SSimon Glass #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN) 6476571674SSimon Glass out_le32(addr, value); 6576571674SSimon Glass #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN) 6676571674SSimon Glass out_be32(addr, value); 6776571674SSimon Glass #elif defined(CONFIG_SYS_BIG_ENDIAN) 6876571674SSimon Glass writeb(value, addr + (1 << shift) - 1); 6976571674SSimon Glass #else 7076571674SSimon Glass writeb(value, addr); 7176571674SSimon Glass #endif 7276571674SSimon Glass } 7376571674SSimon Glass 7476571674SSimon Glass static inline int serial_in_shift(unsigned char *addr, int shift) 7576571674SSimon Glass { 7676571674SSimon Glass #ifdef CONFIG_SYS_NS16550_PORT_MAPPED 7776571674SSimon Glass return inb((ulong)addr); 7876571674SSimon Glass #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_SYS_BIG_ENDIAN) 7976571674SSimon Glass return in_le32(addr); 8076571674SSimon Glass #elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN) 8176571674SSimon Glass return in_be32(addr); 8276571674SSimon Glass #elif defined(CONFIG_SYS_BIG_ENDIAN) 8376571674SSimon Glass return readb(addr + (1 << reg_shift) - 1); 8476571674SSimon Glass #else 8576571674SSimon Glass return readb(addr); 8676571674SSimon Glass #endif 8776571674SSimon Glass } 8876571674SSimon Glass 8912e431b2SSimon Glass static void ns16550_writeb(NS16550_t port, int offset, int value) 9012e431b2SSimon Glass { 9112e431b2SSimon Glass struct ns16550_platdata *plat = port->plat; 9212e431b2SSimon Glass unsigned char *addr; 9312e431b2SSimon Glass 9412e431b2SSimon Glass offset *= 1 << plat->reg_shift; 95167efe01SSimon Glass addr = map_sysmem(plat->base, 0) + offset; 9612e431b2SSimon Glass /* 9712e431b2SSimon Glass * As far as we know it doesn't make sense to support selection of 9812e431b2SSimon Glass * these options at run-time, so use the existing CONFIG options. 9912e431b2SSimon Glass */ 10076571674SSimon Glass serial_out_shift(addr, plat->reg_shift, value); 10112e431b2SSimon Glass } 10212e431b2SSimon Glass 10312e431b2SSimon Glass static int ns16550_readb(NS16550_t port, int offset) 10412e431b2SSimon Glass { 10512e431b2SSimon Glass struct ns16550_platdata *plat = port->plat; 10612e431b2SSimon Glass unsigned char *addr; 10712e431b2SSimon Glass 10812e431b2SSimon Glass offset *= 1 << plat->reg_shift; 109167efe01SSimon Glass addr = map_sysmem(plat->base, 0) + offset; 11076571674SSimon Glass 11176571674SSimon Glass return serial_in_shift(addr, plat->reg_shift); 11212e431b2SSimon Glass } 11312e431b2SSimon Glass 11412e431b2SSimon Glass /* We can clean these up once everything is moved to driver model */ 11512e431b2SSimon Glass #define serial_out(value, addr) \ 11612e431b2SSimon Glass ns16550_writeb(com_port, addr - (unsigned char *)com_port, value) 11712e431b2SSimon Glass #define serial_in(addr) \ 11812e431b2SSimon Glass ns16550_readb(com_port, addr - (unsigned char *)com_port) 11912e431b2SSimon Glass #endif 12012e431b2SSimon Glass 121*21d00436SSimon Glass static inline int calc_divisor(NS16550_t port, int clock, int baudrate) 122fa54eb12SSimon Glass { 123fa54eb12SSimon Glass const unsigned int mode_x_div = 16; 124fa54eb12SSimon Glass 125*21d00436SSimon Glass return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate); 126*21d00436SSimon Glass } 127*21d00436SSimon Glass 128*21d00436SSimon Glass int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate) 129*21d00436SSimon Glass { 130fa54eb12SSimon Glass #ifdef CONFIG_OMAP1510 131fa54eb12SSimon Glass /* If can't cleanly clock 115200 set div to 1 */ 132fa54eb12SSimon Glass if ((clock == 12000000) && (baudrate == 115200)) { 133fa54eb12SSimon Glass port->osc_12m_sel = OSC_12M_SEL; /* enable 6.5 * divisor */ 134fa54eb12SSimon Glass return 1; /* return 1 for base divisor */ 135fa54eb12SSimon Glass } 136fa54eb12SSimon Glass port->osc_12m_sel = 0; /* clear if previsouly set */ 137fa54eb12SSimon Glass #endif 138fa54eb12SSimon Glass 139*21d00436SSimon Glass return calc_divisor(port, clock, baudrate); 140fa54eb12SSimon Glass } 141fa54eb12SSimon Glass 1428bbe33c8SSimon Glass static void NS16550_setbrg(NS16550_t com_port, int baud_divisor) 1438bbe33c8SSimon Glass { 1448bbe33c8SSimon Glass serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr); 1458bbe33c8SSimon Glass serial_out(baud_divisor & 0xff, &com_port->dll); 1468bbe33c8SSimon Glass serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm); 1478bbe33c8SSimon Glass serial_out(UART_LCRVAL, &com_port->lcr); 1488bbe33c8SSimon Glass } 1498bbe33c8SSimon Glass 1501378df79SJean-Christophe PLAGNIOL-VILLARD void NS16550_init(NS16550_t com_port, int baud_divisor) 1511378df79SJean-Christophe PLAGNIOL-VILLARD { 152956a8baeSGregoire Gentil #if (defined(CONFIG_SPL_BUILD) && \ 153956a8baeSGregoire Gentil (defined(CONFIG_OMAP34XX) || defined(CONFIG_OMAP44XX))) 154fd2aeac5SManfred Huber /* 155956a8baeSGregoire Gentil * On some OMAP3/OMAP4 devices when UART3 is configured for boot mode 156956a8baeSGregoire Gentil * before SPL starts only THRE bit is set. We have to empty the 157956a8baeSGregoire Gentil * transmitter before initialization starts. 158fd2aeac5SManfred Huber */ 159fd2aeac5SManfred Huber if ((serial_in(&com_port->lsr) & (UART_LSR_TEMT | UART_LSR_THRE)) 160fd2aeac5SManfred Huber == UART_LSR_THRE) { 16112e431b2SSimon Glass if (baud_divisor != -1) 1628bbe33c8SSimon Glass NS16550_setbrg(com_port, baud_divisor); 163fd2aeac5SManfred Huber serial_out(0, &com_port->mdr1); 164fd2aeac5SManfred Huber } 165fd2aeac5SManfred Huber #endif 166fd2aeac5SManfred Huber 167cb55b332SScott Wood while (!(serial_in(&com_port->lsr) & UART_LSR_TEMT)) 168cb55b332SScott Wood ; 169cb55b332SScott Wood 170a160ea0bSPrafulla Wadaskar serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier); 171456ccfdfSTom Rini #if defined(CONFIG_OMAP) || defined(CONFIG_AM33XX) || \ 172456ccfdfSTom Rini defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX) 173167cdad1SGraeme Russ serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/ 1741378df79SJean-Christophe PLAGNIOL-VILLARD #endif 1758bbe33c8SSimon Glass NS16550_setbrg(com_port, 0); 176167cdad1SGraeme Russ serial_out(UART_MCRVAL, &com_port->mcr); 177167cdad1SGraeme Russ serial_out(UART_FCRVAL, &com_port->fcr); 17812e431b2SSimon Glass if (baud_divisor != -1) 1798bbe33c8SSimon Glass NS16550_setbrg(com_port, baud_divisor); 1808ac22a60SMasahiro Yamada #if defined(CONFIG_OMAP) || \ 1816213a68fSMatt Porter defined(CONFIG_AM33XX) || defined(CONFIG_SOC_DA8XX) || \ 1829ed6e412STENART Antoine defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX) 1835289e83aSChandan Nath 184f8df9d0dSSimon Glass /* /16 is proper to hit 115200 with 48MHz */ 185f8df9d0dSSimon Glass serial_out(0, &com_port->mdr1); 186b4746d8bSMike Frysinger #endif /* CONFIG_OMAP */ 1877c387646SKhoronzhuk, Ivan #if defined(CONFIG_SOC_KEYSTONE) 188ef509b90SVitaly Andrianov serial_out(UART_REG_VAL_PWREMU_MGMT_UART_ENABLE, &com_port->regC); 189ef509b90SVitaly Andrianov #endif 1901378df79SJean-Christophe PLAGNIOL-VILLARD } 1911378df79SJean-Christophe PLAGNIOL-VILLARD 192f5675aa5SRon Madrid #ifndef CONFIG_NS16550_MIN_FUNCTIONS 1931378df79SJean-Christophe PLAGNIOL-VILLARD void NS16550_reinit(NS16550_t com_port, int baud_divisor) 1941378df79SJean-Christophe PLAGNIOL-VILLARD { 195a160ea0bSPrafulla Wadaskar serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier); 1968bbe33c8SSimon Glass NS16550_setbrg(com_port, 0); 197167cdad1SGraeme Russ serial_out(UART_MCRVAL, &com_port->mcr); 198167cdad1SGraeme Russ serial_out(UART_FCRVAL, &com_port->fcr); 1998bbe33c8SSimon Glass NS16550_setbrg(com_port, baud_divisor); 2001378df79SJean-Christophe PLAGNIOL-VILLARD } 201f5675aa5SRon Madrid #endif /* CONFIG_NS16550_MIN_FUNCTIONS */ 2021378df79SJean-Christophe PLAGNIOL-VILLARD 2031378df79SJean-Christophe PLAGNIOL-VILLARD void NS16550_putc(NS16550_t com_port, char c) 2041378df79SJean-Christophe PLAGNIOL-VILLARD { 205f8df9d0dSSimon Glass while ((serial_in(&com_port->lsr) & UART_LSR_THRE) == 0) 206f8df9d0dSSimon Glass ; 207167cdad1SGraeme Russ serial_out(c, &com_port->thr); 2081a2d9b30SStefan Roese 2091a2d9b30SStefan Roese /* 2101a2d9b30SStefan Roese * Call watchdog_reset() upon newline. This is done here in putc 2111a2d9b30SStefan Roese * since the environment code uses a single puts() to print the complete 2121a2d9b30SStefan Roese * environment upon "printenv". So we can't put this watchdog call 2131a2d9b30SStefan Roese * in puts(). 2141a2d9b30SStefan Roese */ 2151a2d9b30SStefan Roese if (c == '\n') 2161a2d9b30SStefan Roese WATCHDOG_RESET(); 2171378df79SJean-Christophe PLAGNIOL-VILLARD } 2181378df79SJean-Christophe PLAGNIOL-VILLARD 219f5675aa5SRon Madrid #ifndef CONFIG_NS16550_MIN_FUNCTIONS 2201378df79SJean-Christophe PLAGNIOL-VILLARD char NS16550_getc(NS16550_t com_port) 2211378df79SJean-Christophe PLAGNIOL-VILLARD { 222167cdad1SGraeme Russ while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) { 223f2041388SMarek Vasut #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_USB_TTY) 2241378df79SJean-Christophe PLAGNIOL-VILLARD extern void usbtty_poll(void); 2251378df79SJean-Christophe PLAGNIOL-VILLARD usbtty_poll(); 2261378df79SJean-Christophe PLAGNIOL-VILLARD #endif 227a1b322a9SLadislav Michl WATCHDOG_RESET(); 2281378df79SJean-Christophe PLAGNIOL-VILLARD } 229167cdad1SGraeme Russ return serial_in(&com_port->rbr); 2301378df79SJean-Christophe PLAGNIOL-VILLARD } 2311378df79SJean-Christophe PLAGNIOL-VILLARD 2321378df79SJean-Christophe PLAGNIOL-VILLARD int NS16550_tstc(NS16550_t com_port) 2331378df79SJean-Christophe PLAGNIOL-VILLARD { 234f8df9d0dSSimon Glass return (serial_in(&com_port->lsr) & UART_LSR_DR) != 0; 2351378df79SJean-Christophe PLAGNIOL-VILLARD } 2361378df79SJean-Christophe PLAGNIOL-VILLARD 237f5675aa5SRon Madrid #endif /* CONFIG_NS16550_MIN_FUNCTIONS */ 23812e431b2SSimon Glass 239*21d00436SSimon Glass #ifdef CONFIG_DEBUG_UART_NS16550 240*21d00436SSimon Glass 241*21d00436SSimon Glass #include <debug_uart.h> 242*21d00436SSimon Glass 243*21d00436SSimon Glass void debug_uart_init(void) 244*21d00436SSimon Glass { 245*21d00436SSimon Glass struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; 246*21d00436SSimon Glass int baud_divisor; 247*21d00436SSimon Glass 248*21d00436SSimon Glass /* 249*21d00436SSimon Glass * We copy the code from above because it is already horribly messy. 250*21d00436SSimon Glass * Trying to refactor to nicely remove the duplication doesn't seem 251*21d00436SSimon Glass * feasible. The better fix is to move all users of this driver to 252*21d00436SSimon Glass * driver model. 253*21d00436SSimon Glass */ 254*21d00436SSimon Glass baud_divisor = calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK, 255*21d00436SSimon Glass CONFIG_BAUDRATE); 256*21d00436SSimon Glass 257*21d00436SSimon Glass serial_out_shift(&com_port->ier, 0, CONFIG_SYS_NS16550_IER); 258*21d00436SSimon Glass serial_out_shift(&com_port->mcr, 0, UART_MCRVAL); 259*21d00436SSimon Glass serial_out_shift(&com_port->fcr, 0, UART_FCRVAL); 260*21d00436SSimon Glass 261*21d00436SSimon Glass serial_out_shift(&com_port->lcr, 0, UART_LCR_BKSE | UART_LCRVAL); 262*21d00436SSimon Glass serial_out_shift(&com_port->dll, 0, baud_divisor & 0xff); 263*21d00436SSimon Glass serial_out_shift(&com_port->dlm, 0, (baud_divisor >> 8) & 0xff); 264*21d00436SSimon Glass serial_out_shift(&com_port->lcr, 0, UART_LCRVAL); 265*21d00436SSimon Glass } 266*21d00436SSimon Glass 267*21d00436SSimon Glass static inline void _debug_uart_putc(int ch) 268*21d00436SSimon Glass { 269*21d00436SSimon Glass struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; 270*21d00436SSimon Glass 271*21d00436SSimon Glass while (!(serial_in_shift(&com_port->lsr, 0) & UART_LSR_THRE)) 272*21d00436SSimon Glass ; 273*21d00436SSimon Glass serial_out_shift(&com_port->thr, 0, ch); 274*21d00436SSimon Glass } 275*21d00436SSimon Glass 276*21d00436SSimon Glass DEBUG_UART_FUNCS 277*21d00436SSimon Glass 278*21d00436SSimon Glass #endif 279*21d00436SSimon Glass 28012e431b2SSimon Glass #ifdef CONFIG_DM_SERIAL 28112e431b2SSimon Glass static int ns16550_serial_putc(struct udevice *dev, const char ch) 28212e431b2SSimon Glass { 28312e431b2SSimon Glass struct NS16550 *const com_port = dev_get_priv(dev); 28412e431b2SSimon Glass 28512e431b2SSimon Glass if (!(serial_in(&com_port->lsr) & UART_LSR_THRE)) 28612e431b2SSimon Glass return -EAGAIN; 28712e431b2SSimon Glass serial_out(ch, &com_port->thr); 28812e431b2SSimon Glass 28912e431b2SSimon Glass /* 29012e431b2SSimon Glass * Call watchdog_reset() upon newline. This is done here in putc 29112e431b2SSimon Glass * since the environment code uses a single puts() to print the complete 29212e431b2SSimon Glass * environment upon "printenv". So we can't put this watchdog call 29312e431b2SSimon Glass * in puts(). 29412e431b2SSimon Glass */ 29512e431b2SSimon Glass if (ch == '\n') 29612e431b2SSimon Glass WATCHDOG_RESET(); 29712e431b2SSimon Glass 29812e431b2SSimon Glass return 0; 29912e431b2SSimon Glass } 30012e431b2SSimon Glass 30112e431b2SSimon Glass static int ns16550_serial_pending(struct udevice *dev, bool input) 30212e431b2SSimon Glass { 30312e431b2SSimon Glass struct NS16550 *const com_port = dev_get_priv(dev); 30412e431b2SSimon Glass 30512e431b2SSimon Glass if (input) 30612e431b2SSimon Glass return serial_in(&com_port->lsr) & UART_LSR_DR ? 1 : 0; 30712e431b2SSimon Glass else 30812e431b2SSimon Glass return serial_in(&com_port->lsr) & UART_LSR_THRE ? 0 : 1; 30912e431b2SSimon Glass } 31012e431b2SSimon Glass 31112e431b2SSimon Glass static int ns16550_serial_getc(struct udevice *dev) 31212e431b2SSimon Glass { 31312e431b2SSimon Glass struct NS16550 *const com_port = dev_get_priv(dev); 31412e431b2SSimon Glass 315aea2be20SSimon Glass if (!(serial_in(&com_port->lsr) & UART_LSR_DR)) 31612e431b2SSimon Glass return -EAGAIN; 31712e431b2SSimon Glass 31812e431b2SSimon Glass return serial_in(&com_port->rbr); 31912e431b2SSimon Glass } 32012e431b2SSimon Glass 32112e431b2SSimon Glass static int ns16550_serial_setbrg(struct udevice *dev, int baudrate) 32212e431b2SSimon Glass { 32312e431b2SSimon Glass struct NS16550 *const com_port = dev_get_priv(dev); 32412e431b2SSimon Glass struct ns16550_platdata *plat = com_port->plat; 32512e431b2SSimon Glass int clock_divisor; 32612e431b2SSimon Glass 32712e431b2SSimon Glass clock_divisor = ns16550_calc_divisor(com_port, plat->clock, baudrate); 32812e431b2SSimon Glass 32912e431b2SSimon Glass NS16550_setbrg(com_port, clock_divisor); 33012e431b2SSimon Glass 33112e431b2SSimon Glass return 0; 33212e431b2SSimon Glass } 33312e431b2SSimon Glass 33412e431b2SSimon Glass int ns16550_serial_probe(struct udevice *dev) 33512e431b2SSimon Glass { 33612e431b2SSimon Glass struct NS16550 *const com_port = dev_get_priv(dev); 33712e431b2SSimon Glass 33811c1a878SSimon Glass com_port->plat = dev_get_platdata(dev); 33912e431b2SSimon Glass NS16550_init(com_port, -1); 34012e431b2SSimon Glass 34112e431b2SSimon Glass return 0; 34212e431b2SSimon Glass } 34312e431b2SSimon Glass 34411c1a878SSimon Glass #ifdef CONFIG_OF_CONTROL 34512e431b2SSimon Glass int ns16550_serial_ofdata_to_platdata(struct udevice *dev) 34612e431b2SSimon Glass { 34712e431b2SSimon Glass struct ns16550_platdata *plat = dev->platdata; 34812e431b2SSimon Glass fdt_addr_t addr; 34912e431b2SSimon Glass 3503db886a5SBin Meng /* try Processor Local Bus device first */ 35112e431b2SSimon Glass addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg"); 3523db886a5SBin Meng #ifdef CONFIG_PCI 3533db886a5SBin Meng if (addr == FDT_ADDR_T_NONE) { 3543db886a5SBin Meng /* then try pci device */ 3553db886a5SBin Meng struct fdt_pci_addr pci_addr; 3563db886a5SBin Meng u32 bar; 3573db886a5SBin Meng int ret; 3583db886a5SBin Meng 3593db886a5SBin Meng /* we prefer to use a memory-mapped register */ 3603db886a5SBin Meng ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset, 3613db886a5SBin Meng FDT_PCI_SPACE_MEM32, "reg", 3623db886a5SBin Meng &pci_addr); 3633db886a5SBin Meng if (ret) { 3643db886a5SBin Meng /* try if there is any i/o-mapped register */ 3653db886a5SBin Meng ret = fdtdec_get_pci_addr(gd->fdt_blob, 3663db886a5SBin Meng dev->of_offset, 3673db886a5SBin Meng FDT_PCI_SPACE_IO, 3683db886a5SBin Meng "reg", &pci_addr); 3693db886a5SBin Meng if (ret) 3703db886a5SBin Meng return ret; 3713db886a5SBin Meng } 3723db886a5SBin Meng 3733db886a5SBin Meng ret = fdtdec_get_pci_bar32(gd->fdt_blob, dev->of_offset, 3743db886a5SBin Meng &pci_addr, &bar); 3753db886a5SBin Meng if (ret) 3763db886a5SBin Meng return ret; 3773db886a5SBin Meng 3783db886a5SBin Meng addr = bar; 3793db886a5SBin Meng } 3803db886a5SBin Meng #endif 3813db886a5SBin Meng 38212e431b2SSimon Glass if (addr == FDT_ADDR_T_NONE) 38312e431b2SSimon Glass return -EINVAL; 38412e431b2SSimon Glass 385167efe01SSimon Glass plat->base = addr; 38612e431b2SSimon Glass plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset, 38712e431b2SSimon Glass "reg-shift", 1); 38812e431b2SSimon Glass 38912e431b2SSimon Glass return 0; 39012e431b2SSimon Glass } 39111c1a878SSimon Glass #endif 39212e431b2SSimon Glass 39312e431b2SSimon Glass const struct dm_serial_ops ns16550_serial_ops = { 39412e431b2SSimon Glass .putc = ns16550_serial_putc, 39512e431b2SSimon Glass .pending = ns16550_serial_pending, 39612e431b2SSimon Glass .getc = ns16550_serial_getc, 39712e431b2SSimon Glass .setbrg = ns16550_serial_setbrg, 39812e431b2SSimon Glass }; 39912e431b2SSimon Glass #endif /* CONFIG_DM_SERIAL */ 400